ivt_image.cpp
Go to the documentation of this file.
1 
18 #include <ivt_bridge/ivt_image.h>
19 #include <opencv2/imgproc/imgproc.hpp>
20 #include <Image/ImageProcessor.h>
22 #include <boost/make_shared.hpp>
23 
25 
26 namespace ivt_bridge {
27 
28 int getCvType(const std::string& encoding) {
29  // Check for the most common encodings first
30  if (encoding == enc::BGR8) return CV_8UC3;
31  if (encoding == enc::MONO8) return CV_8UC1;
32  if (encoding == enc::RGB8) return CV_8UC3;
33  if (encoding == enc::MONO16) return CV_16UC1;
34  if (encoding == enc::BGR16) return CV_16UC3;
35  if (encoding == enc::RGB16) return CV_16UC3;
36  if (encoding == enc::BGRA8) return CV_8UC4;
37  if (encoding == enc::RGBA8) return CV_8UC4;
38  if (encoding == enc::BGRA16) return CV_16UC4;
39  if (encoding == enc::RGBA16) return CV_16UC4;
40 
41  // For bayer, return one-channel
42  if (encoding == enc::BAYER_RGGB8) return CV_8UC1;
43  if (encoding == enc::BAYER_BGGR8) return CV_8UC1;
44  if (encoding == enc::BAYER_GBRG8) return CV_8UC1;
45  if (encoding == enc::BAYER_GRBG8) return CV_8UC1;
46  if (encoding == enc::BAYER_RGGB16) return CV_16UC1;
47  if (encoding == enc::BAYER_BGGR16) return CV_16UC1;
48  if (encoding == enc::BAYER_GBRG16) return CV_16UC1;
49  if (encoding == enc::BAYER_GRBG16) return CV_16UC1;
50 
51  // Check all the generic content encodings
52 #define CHECK_ENCODING(code) \
53  if (encoding == enc::TYPE_##code) return CV_##code \
54  /***/
55 #define CHECK_CHANNEL_TYPE(t) \
56  CHECK_ENCODING(t##1); \
57  CHECK_ENCODING(t##2); \
58  CHECK_ENCODING(t##3); \
59  CHECK_ENCODING(t##4); \
60  /***/
61 
62  CHECK_CHANNEL_TYPE(8UC);
63  CHECK_CHANNEL_TYPE(8SC);
64  CHECK_CHANNEL_TYPE(16UC);
65  CHECK_CHANNEL_TYPE(16SC);
66  CHECK_CHANNEL_TYPE(32SC);
67  CHECK_CHANNEL_TYPE(32FC);
68  CHECK_CHANNEL_TYPE(64FC);
69 
70 #undef CHECK_CHANNEL_TYPE
71 #undef CHECK_ENCODING
72 
73  throw Exception("Unrecognized image encoding [" + encoding + "]");
74 }
75 
76 CByteImage::ImageType getIvtType(const std::string& encoding) {
77  if (encoding == enc::RGB8) return CByteImage::eRGB24;
78  if (encoding == enc::MONO8) return CByteImage::eGrayScale;
79  throw Exception("No IVT equivalent to image encoding [" + encoding + "]");
80 }
81 
83 
84 enum Format { INVALID = -1, GRAY = 0, RGB, BGR, RGBA, BGRA };
85 
86 Format getFormat(const std::string& encoding) {
87  if (encoding == enc::BGR8) return BGR;
88  if (encoding == enc::MONO8) return GRAY;
89  if (encoding == enc::RGB8) return RGB;
90  if (encoding == enc::MONO16) return GRAY;
91  if (encoding == enc::BGR16) return BGR;
92  if (encoding == enc::RGB16) return RGB;
93  if (encoding == enc::BGRA8) return BGRA;
94  if (encoding == enc::RGBA8) return RGBA;
95  if (encoding == enc::BGRA16) return BGRA;
96  if (encoding == enc::RGBA16) return RGBA;
97 
98  // We don't support conversions to/from other types
99  return INVALID;
100 }
101 
102 static const int SAME_FORMAT = -1;
103 
104 int getConversionCode(Format src_format, Format dst_format) {
105  static const int CONVERSION_CODES[] = { SAME_FORMAT, CV_GRAY2RGB, CV_GRAY2BGR, CV_GRAY2RGBA, CV_GRAY2BGRA,
106  CV_RGB2GRAY, SAME_FORMAT, CV_RGB2BGR, CV_RGB2RGBA, CV_RGB2BGRA,
107  CV_BGR2GRAY, CV_BGR2RGB, SAME_FORMAT, CV_BGR2RGBA, CV_BGR2BGRA,
108  CV_RGBA2GRAY, CV_RGBA2RGB, CV_RGBA2BGR, SAME_FORMAT, CV_RGBA2BGRA,
109  CV_BGRA2GRAY, CV_BGRA2RGB, CV_BGRA2BGR, CV_BGRA2RGBA, SAME_FORMAT };
110  return CONVERSION_CODES[src_format*5 + dst_format];
111 }
112 
113 // Internal, used by toCvCopy and cvtColor
114 IvtImagePtr toIvtCopyImpl(const cv::Mat& source, const std_msgs::Header& src_header, const std::string& src_encoding, const std::string& dst_encoding) {
116 
117  // Copy metadata
118  IvtImagePtr ptr = boost::make_shared<IvtImage>();
119  ptr->header = src_header;
120 
121  // Get outputformat
122  Format src_format = getFormat(src_encoding);
123  if (dst_encoding.empty()) {
124  if (src_format == GRAY)
125  ptr->encoding = enc::MONO8;
126  else
127  ptr->encoding = enc::RGB8;
128  }
129  else
130  ptr->encoding = dst_encoding;
131  Format dst_format = getFormat(ptr->encoding);
132 
133  cv::Mat tmp;
134  if (ptr->encoding == src_encoding) {
135  tmp = source;
136  }
137  else {
138  // Convert the source data to the desired encoding
139  if (src_format == INVALID || dst_format == INVALID)
140  throw Exception("Unsupported conversion from [" + src_encoding + "] to [" + ptr->encoding + "]");
141 
142  int conversion_code = getConversionCode(src_format, dst_format);
143  if (conversion_code == SAME_FORMAT) {
144  // Same number of channels, but different bit depth
145  double alpha = 1.0;
146  int src_depth = enc::bitDepth(src_encoding);
147  int dst_depth = enc::bitDepth(dst_encoding);
148  // Do scaling between CV_8U [0,255] and CV_16U [0,65535] images.
149  if (src_depth == 8 && dst_depth == 16)
150  alpha = 65535. / 255.;
151  else if (src_depth == 16 && dst_depth == 8)
152  alpha = 255. / 65535.;
153  source.convertTo(tmp, getCvType(ptr->encoding), alpha);
154  }
155  else {
156  // Perform color conversion
157  cv::cvtColor(source, tmp, conversion_code);
158  }
159  }
160 
161  ptr->image = new CByteImage(tmp.cols, tmp.rows, getIvtType(ptr->encoding));
162  // Compensate for padding on row end.
163  if (tmp.step == tmp.cols * tmp.elemSize()) {
164  memcpy(ptr->image->pixels, tmp.data, tmp.cols * tmp.rows * tmp.elemSize());
165  } else {
166  int ivtImgStep = ptr->image->bytesPerPixel*ptr->image->width;
167  uchar *ivtImgPtr = ptr->image->pixels;
168  uchar *cvImgPtr = tmp.data;
169  for (int i=0; i < tmp.rows; i++){
170  memcpy(ivtImgPtr, cvImgPtr, ivtImgStep);
171  ivtImgPtr += ivtImgStep;
172  cvImgPtr += tmp.step;
173  }
174  }
175  return ptr;
176 }
177 
179 
181  delete image;
182 }
183 
184 sensor_msgs::ImagePtr IvtImage::toImageMsg() const {
185  sensor_msgs::ImagePtr ptr = boost::make_shared<sensor_msgs::Image>();
186  toImageMsg(*ptr);
187  return ptr;
188 }
189 
190 void IvtImage::toImageMsg(sensor_msgs::Image& ros_image) const {
191  ros_image.header = header;
192  ros_image.height = image->height;
193  ros_image.width = image->width;
194  ros_image.encoding = encoding;
195  ros_image.is_bigendian = false;
196  ros_image.step = 0;
197  size_t size = image->width * image->height * image->bytesPerPixel;
198  ros_image.data.resize(size);
199  memcpy((char*)(&ros_image.data[0]), image->pixels, size);
200 }
201 
202 // Deep copy data, returnee is mutable
203 IvtImagePtr toIvtCopy(const sensor_msgs::ImageConstPtr& source, const std::string& encoding) {
204  return toIvtCopy(*source, encoding);
205 }
206 
207 IvtImagePtr toIvtCopy(const sensor_msgs::Image& source, const std::string& encoding) {
208  // Construct matrix pointing to source data
209  if (encoding != enc::MONO8 && encoding != enc::RGB8 && !encoding.empty())
210  throw Exception("Encoding " + encoding + " not supported");
211  int source_type = getCvType(source.encoding);
212  const cv::Mat tmp((int)source.height, (int)source.width, source_type, const_cast<uint8_t*>(&source.data[0]), (size_t)source.step);
213  return toIvtCopyImpl(tmp, source.header, source.encoding, encoding);
214 }
215 
217 IvtImageConstPtr toIvtShare(const sensor_msgs::ImageConstPtr& source, const std::string& encoding) {
218  return toIvtShare(*source, source, encoding);
219 }
220 
221 IvtImageConstPtr toIvtShare(const sensor_msgs::Image& source, const boost::shared_ptr<void const>& tracked_object, const std::string& encoding) {
222  bool hasPadding = source.step != source.width * (source.encoding == enc::RGB8 ? 3 : 1);
223  if ((!encoding.empty() && source.encoding != encoding) || (source.encoding != enc::MONO8 && source.encoding != enc::RGB8) || hasPadding)
224  return toIvtCopy(source, encoding);
225  IvtImagePtr ptr = boost::make_shared<IvtImage>();
226  ptr->header = source.header;
227  ptr->encoding = source.encoding;
228  ptr->tracked_object_ = tracked_object;
229  ptr->image = new CByteImage(source.width, source.height, getIvtType(ptr->encoding), true);
230  ptr->image->pixels = const_cast<uchar*>(&source.data[0]);
231  return ptr;
232 }
233 
234 
235 
236 } //namespace ivt_bridge
std::string encoding
Image encoding ("mono8", "bgr8", etc.)
Definition: ivt_image.h:49
#define CHECK_CHANNEL_TYPE(t)
CByteImage::ImageType getIvtType(const std::string &encoding)
Get the CByteImage type enum corresponding to the encoding.
Definition: ivt_image.cpp:76
IvtImagePtr toIvtCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
Convert a sensor_msgs::Image message to an Ivt-compatible CByteImage, copying the image data...
Definition: ivt_image.cpp:203
int getCvType(const std::string &encoding)
Convert a IvtImage to another encoding.
Definition: ivt_image.cpp:28
sensor_msgs::ImagePtr toImageMsg() const
Convert this message to a ROS sensor_msgs::Image message.
Definition: ivt_image.cpp:184
IvtImageConstPtr toIvtShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
Convert an immutable sensor_msgs::Image message to an Ivt-compatible CByteImage, sharing the image da...
Definition: ivt_image.cpp:217
CByteImage * image
Image data for use with Ivt.
Definition: ivt_image.h:50
std_msgs::Header header
ROS header.
Definition: ivt_image.h:48


asr_ivt_bridge
Author(s): Hutmacher Robin, Kleinert Daniel, Meißner Pascal
autogenerated on Mon Jun 10 2019 12:39:24