ivt_image.cpp
Go to the documentation of this file.
00001 
00018 #include <ivt_bridge/ivt_image.h>
00019 #include <opencv2/imgproc/imgproc.hpp>
00020 #include <Image/ImageProcessor.h>
00021 #include <sensor_msgs/image_encodings.h>
00022 #include <boost/make_shared.hpp>
00023 
00024 namespace enc = sensor_msgs::image_encodings;
00025 
00026 namespace ivt_bridge {
00027 
00028 int getCvType(const std::string& encoding) {
00029   // Check for the most common encodings first
00030   if (encoding == enc::BGR8)   return CV_8UC3;
00031   if (encoding == enc::MONO8)  return CV_8UC1;
00032   if (encoding == enc::RGB8)   return CV_8UC3;
00033   if (encoding == enc::MONO16) return CV_16UC1;
00034   if (encoding == enc::BGR16)  return CV_16UC3;
00035   if (encoding == enc::RGB16)  return CV_16UC3;
00036   if (encoding == enc::BGRA8)  return CV_8UC4;
00037   if (encoding == enc::RGBA8)  return CV_8UC4;
00038   if (encoding == enc::BGRA16) return CV_16UC4;
00039   if (encoding == enc::RGBA16) return CV_16UC4;
00040 
00041   // For bayer, return one-channel
00042   if (encoding == enc::BAYER_RGGB8) return CV_8UC1;
00043   if (encoding == enc::BAYER_BGGR8) return CV_8UC1;
00044   if (encoding == enc::BAYER_GBRG8) return CV_8UC1;
00045   if (encoding == enc::BAYER_GRBG8) return CV_8UC1;
00046   if (encoding == enc::BAYER_RGGB16) return CV_16UC1;
00047   if (encoding == enc::BAYER_BGGR16) return CV_16UC1;
00048   if (encoding == enc::BAYER_GBRG16) return CV_16UC1;
00049   if (encoding == enc::BAYER_GRBG16) return CV_16UC1;
00050 
00051   // Check all the generic content encodings
00052 #define CHECK_ENCODING(code)                            \
00053   if (encoding == enc::TYPE_##code) return CV_##code    \
00054   /***/
00055 #define CHECK_CHANNEL_TYPE(t)                   \
00056   CHECK_ENCODING(t##1);                         \
00057   CHECK_ENCODING(t##2);                         \
00058   CHECK_ENCODING(t##3);                         \
00059   CHECK_ENCODING(t##4);                         \
00060   /***/
00061 
00062   CHECK_CHANNEL_TYPE(8UC);
00063   CHECK_CHANNEL_TYPE(8SC);
00064   CHECK_CHANNEL_TYPE(16UC);
00065   CHECK_CHANNEL_TYPE(16SC);
00066   CHECK_CHANNEL_TYPE(32SC);
00067   CHECK_CHANNEL_TYPE(32FC);
00068   CHECK_CHANNEL_TYPE(64FC);
00069 
00070 #undef CHECK_CHANNEL_TYPE
00071 #undef CHECK_ENCODING
00072 
00073   throw Exception("Unrecognized image encoding [" + encoding + "]");
00074 }
00075 
00076 CByteImage::ImageType getIvtType(const std::string& encoding) {
00077           if (encoding == enc::RGB8)   return CByteImage::eRGB24;
00078           if (encoding == enc::MONO8)  return CByteImage::eGrayScale;
00079           throw Exception("No IVT equivalent to image encoding [" + encoding + "]");
00080 }
00081 
00083 
00084 enum Format { INVALID = -1, GRAY = 0, RGB, BGR, RGBA, BGRA };
00085 
00086 Format getFormat(const std::string& encoding) {
00087   if (encoding == enc::BGR8)   return BGR;
00088   if (encoding == enc::MONO8)  return GRAY;
00089   if (encoding == enc::RGB8)   return RGB;
00090   if (encoding == enc::MONO16) return GRAY;
00091   if (encoding == enc::BGR16)  return BGR;
00092   if (encoding == enc::RGB16)  return RGB;
00093   if (encoding == enc::BGRA8)  return BGRA;
00094   if (encoding == enc::RGBA8)  return RGBA;
00095   if (encoding == enc::BGRA16) return BGRA;
00096   if (encoding == enc::RGBA16) return RGBA;
00097 
00098   // We don't support conversions to/from other types
00099   return INVALID;
00100 }
00101 
00102 static const int SAME_FORMAT = -1;
00103 
00104 int getConversionCode(Format src_format, Format dst_format) {
00105   static const int CONVERSION_CODES[] = { SAME_FORMAT, CV_GRAY2RGB, CV_GRAY2BGR, CV_GRAY2RGBA, CV_GRAY2BGRA,
00106                                                                                   CV_RGB2GRAY, SAME_FORMAT, CV_RGB2BGR, CV_RGB2RGBA, CV_RGB2BGRA,
00107                                                                                   CV_BGR2GRAY, CV_BGR2RGB, SAME_FORMAT, CV_BGR2RGBA, CV_BGR2BGRA,
00108                                                                                   CV_RGBA2GRAY, CV_RGBA2RGB, CV_RGBA2BGR, SAME_FORMAT, CV_RGBA2BGRA,
00109                                                                                   CV_BGRA2GRAY, CV_BGRA2RGB,  CV_BGRA2BGR, CV_BGRA2RGBA, SAME_FORMAT };
00110   return CONVERSION_CODES[src_format*5 + dst_format];
00111 }
00112 
00113 // Internal, used by toCvCopy and cvtColor
00114 IvtImagePtr toIvtCopyImpl(const cv::Mat& source, const std_msgs::Header& src_header, const std::string& src_encoding, const std::string& dst_encoding) {
00116   
00117   // Copy metadata
00118   IvtImagePtr ptr = boost::make_shared<IvtImage>();
00119   ptr->header = src_header;
00120   
00121   // Get outputformat
00122   Format src_format = getFormat(src_encoding);
00123   if (dst_encoding.empty()) {
00124     if (src_format == GRAY)
00125         ptr->encoding = enc::MONO8;
00126     else
00127         ptr->encoding = enc::RGB8;
00128   }
00129   else
00130             ptr->encoding = dst_encoding;
00131   Format dst_format = getFormat(ptr->encoding);
00132 
00133   cv::Mat tmp;
00134   if (ptr->encoding == src_encoding) {
00135     tmp = source;
00136   }
00137   else {
00138     // Convert the source data to the desired encoding
00139     if (src_format == INVALID || dst_format == INVALID)
00140       throw Exception("Unsupported conversion from [" + src_encoding + "] to [" + ptr->encoding + "]");
00141 
00142     int conversion_code = getConversionCode(src_format, dst_format);
00143     if (conversion_code == SAME_FORMAT) {
00144       // Same number of channels, but different bit depth
00145       double alpha = 1.0;
00146       int src_depth = enc::bitDepth(src_encoding);
00147       int dst_depth = enc::bitDepth(dst_encoding);
00148       // Do scaling between CV_8U [0,255] and CV_16U [0,65535] images.
00149       if (src_depth == 8 && dst_depth == 16)
00150         alpha = 65535. / 255.;
00151       else if (src_depth == 16 && dst_depth == 8)
00152         alpha = 255. / 65535.;
00153       source.convertTo(tmp, getCvType(ptr->encoding), alpha);
00154     }
00155     else {
00156       // Perform color conversion
00157       cv::cvtColor(source, tmp, conversion_code);
00158     }
00159   }
00160 
00161   ptr->image = new CByteImage(tmp.cols, tmp.rows, getIvtType(ptr->encoding));
00162   // Compensate for padding on row end.
00163   if (tmp.step == tmp.cols * tmp.elemSize()) {
00164           memcpy(ptr->image->pixels, tmp.data, tmp.cols * tmp.rows * tmp.elemSize());
00165   } else {
00166           int ivtImgStep = ptr->image->bytesPerPixel*ptr->image->width;
00167           uchar *ivtImgPtr = ptr->image->pixels;
00168           uchar *cvImgPtr = tmp.data;
00169           for (int i=0; i < tmp.rows; i++){
00170                   memcpy(ivtImgPtr, cvImgPtr, ivtImgStep);
00171                   ivtImgPtr += ivtImgStep;
00172                   cvImgPtr +=  tmp.step;
00173           }
00174   }
00175   return ptr;
00176 }
00177 
00179 
00180 IvtImage::~IvtImage(){
00181         delete image;
00182 }
00183 
00184 sensor_msgs::ImagePtr IvtImage::toImageMsg() const {
00185   sensor_msgs::ImagePtr ptr = boost::make_shared<sensor_msgs::Image>();
00186   toImageMsg(*ptr);
00187   return ptr;
00188 }
00189 
00190 void IvtImage::toImageMsg(sensor_msgs::Image& ros_image) const {
00191   ros_image.header = header;
00192   ros_image.height = image->height;
00193   ros_image.width = image->width;
00194   ros_image.encoding = encoding;
00195   ros_image.is_bigendian = false;
00196   ros_image.step = 0;
00197   size_t size = image->width * image->height * image->bytesPerPixel;
00198   ros_image.data.resize(size);
00199   memcpy((char*)(&ros_image.data[0]), image->pixels, size);
00200 }
00201 
00202 // Deep copy data, returnee is mutable
00203 IvtImagePtr toIvtCopy(const sensor_msgs::ImageConstPtr& source, const std::string& encoding) {
00204   return toIvtCopy(*source, encoding);
00205 }
00206 
00207 IvtImagePtr toIvtCopy(const sensor_msgs::Image& source, const std::string& encoding) {
00208         // Construct matrix pointing to source data
00209         if (encoding != enc::MONO8 && encoding != enc::RGB8 && !encoding.empty())
00210                 throw Exception("Encoding " + encoding + " not supported");
00211         int source_type = getCvType(source.encoding);
00212         const cv::Mat tmp((int)source.height, (int)source.width, source_type, const_cast<uint8_t*>(&source.data[0]), (size_t)source.step);
00213         return toIvtCopyImpl(tmp, source.header, source.encoding, encoding);
00214 }
00215 
00217 IvtImageConstPtr toIvtShare(const sensor_msgs::ImageConstPtr& source, const std::string& encoding) {
00218   return toIvtShare(*source, source, encoding);
00219 }
00220 
00221 IvtImageConstPtr toIvtShare(const sensor_msgs::Image& source, const boost::shared_ptr<void const>& tracked_object, const std::string& encoding) {
00222         bool hasPadding = source.step != source.width * (source.encoding == enc::RGB8 ? 3 : 1);
00223         if ((!encoding.empty() && source.encoding != encoding) || (source.encoding != enc::MONO8 && source.encoding != enc::RGB8) || hasPadding)
00224                 return toIvtCopy(source, encoding);
00225         IvtImagePtr ptr = boost::make_shared<IvtImage>();
00226         ptr->header = source.header;
00227         ptr->encoding = source.encoding;
00228         ptr->tracked_object_ = tracked_object;
00229         ptr->image = new CByteImage(source.width, source.height, getIvtType(ptr->encoding), true);
00230         ptr->image->pixels = const_cast<uchar*>(&source.data[0]);
00231         return ptr;
00232 }
00233 
00234 
00235 
00236 } //namespace ivt_bridge


asr_ivt_bridge
Author(s): Hutmacher Robin, Kleinert Daniel, Meißner Pascal
autogenerated on Sat Jun 8 2019 19:52:36