36 #include "boost/endian/conversion.hpp" 
   40 #include <boost/make_shared.hpp> 
   41 #include <boost/regex.hpp> 
   43 #include <opencv2/imgcodecs.hpp> 
   44 #include <opencv2/imgproc/imgproc.hpp> 
   58   } 
else if (depth == 
"8S") {
 
   60   } 
else if (depth == 
"16U") {
 
   62   } 
else if (depth == 
"16S") {
 
   64   } 
else if (depth == 
"32S") {
 
   66   } 
else if (depth == 
"32F") {
 
   72 int getCvType(
const std::string& encoding)
 
   75   if (encoding == enc::BGR8)   
return CV_8UC3;
 
   76   if (encoding == enc::MONO8)  
return CV_8UC1;
 
   77   if (encoding == enc::RGB8)   
return CV_8UC3;
 
   78   if (encoding == enc::MONO16) 
return CV_16UC1;
 
   79   if (encoding == enc::BGR16)  
return CV_16UC3;
 
   80   if (encoding == enc::RGB16)  
return CV_16UC3;
 
   81   if (encoding == enc::BGRA8)  
return CV_8UC4;
 
   82   if (encoding == enc::RGBA8)  
return CV_8UC4;
 
   83   if (encoding == enc::BGRA16) 
return CV_16UC4;
 
   84   if (encoding == enc::RGBA16) 
return CV_16UC4;
 
   87   if (encoding == enc::BAYER_RGGB8) 
return CV_8UC1;
 
   88   if (encoding == enc::BAYER_BGGR8) 
return CV_8UC1;
 
   89   if (encoding == enc::BAYER_GBRG8) 
return CV_8UC1;
 
   90   if (encoding == enc::BAYER_GRBG8) 
return CV_8UC1;
 
   91   if (encoding == enc::BAYER_RGGB16) 
return CV_16UC1;
 
   92   if (encoding == enc::BAYER_BGGR16) 
return CV_16UC1;
 
   93   if (encoding == enc::BAYER_GBRG16) 
return CV_16UC1;
 
   94   if (encoding == enc::BAYER_GRBG16) 
return CV_16UC1;
 
   97   if (encoding == enc::YUV422) 
return CV_8UC2;
 
  102   if (boost::regex_match(encoding.c_str(), m,
 
  103         boost::regex(
"(8U|8S|16U|16S|32S|32F|64F)C([0-9]+)"))) {
 
  104     return CV_MAKETYPE(
depthStrToInt(m[1].str()), atoi(m[2].str().c_str()));
 
  107   if (boost::regex_match(encoding.c_str(), m,
 
  108         boost::regex(
"(8U|8S|16U|16S|32S|32F|64F)"))) {
 
  112   throw Exception(
"Unrecognized image encoding [" + encoding + 
"]");
 
  117 enum Encoding { INVALID = -1, 
GRAY = 0, RGB, BGR, RGBA, BGRA, 
YUV422, BAYER_RGGB, BAYER_BGGR, BAYER_GBRG, BAYER_GRBG};
 
  119 Encoding getEncoding(
const std::string& encoding)
 
  121   if ((encoding == enc::MONO8) || (encoding == enc::MONO16)) 
return GRAY;
 
  122   if ((encoding == enc::BGR8) || (encoding == enc::BGR16))  
return BGR;
 
  123   if ((encoding == enc::RGB8) || (encoding == enc::RGB16))  
return RGB;
 
  124   if ((encoding == enc::BGRA8) || (encoding == enc::BGRA16))  
return BGRA;
 
  125   if ((encoding == enc::RGBA8) || (encoding == enc::RGBA16))  
return RGBA;
 
  126   if (encoding == enc::YUV422) 
return YUV422;
 
  128   if ((encoding == enc::BAYER_RGGB8) || (encoding == enc::BAYER_RGGB16)) 
return BAYER_RGGB;
 
  129   if ((encoding == enc::BAYER_BGGR8) || (encoding == enc::BAYER_BGGR16)) 
return BAYER_BGGR;
 
  130   if ((encoding == enc::BAYER_GBRG8) || (encoding == enc::BAYER_GBRG16)) 
return BAYER_GBRG;
 
  131   if ((encoding == enc::BAYER_GRBG8) || (encoding == enc::BAYER_GRBG16)) 
return BAYER_GRBG;
 
  137 static const int SAME_FORMAT = -1;
 
  143 std::map<std::pair<Encoding, Encoding>, std::vector<int> > getConversionCodes() {
 
  144   std::map<std::pair<Encoding, Encoding>, std::vector<int> > res;
 
  145   for(
int i=0; i<=5; ++i)
 
  146     res[std::pair<Encoding, Encoding>(Encoding(i),Encoding(i))].push_back(SAME_FORMAT);
 
  148   res[std::make_pair(
GRAY, RGB)].push_back(cv::COLOR_GRAY2RGB);
 
  149   res[std::make_pair(
GRAY, BGR)].push_back(cv::COLOR_GRAY2BGR);
 
  150   res[std::make_pair(
GRAY, RGBA)].push_back(cv::COLOR_GRAY2RGBA);
 
  151   res[std::make_pair(
GRAY, BGRA)].push_back(cv::COLOR_GRAY2BGRA);
 
  153   res[std::make_pair(RGB, 
GRAY)].push_back(cv::COLOR_RGB2GRAY);
 
  154   res[std::make_pair(RGB, BGR)].push_back(cv::COLOR_RGB2BGR);
 
  155   res[std::make_pair(RGB, RGBA)].push_back(cv::COLOR_RGB2RGBA);
 
  156   res[std::make_pair(RGB, BGRA)].push_back(cv::COLOR_RGB2BGRA);
 
  158   res[std::make_pair(BGR, 
GRAY)].push_back(cv::COLOR_BGR2GRAY);
 
  159   res[std::make_pair(BGR, RGB)].push_back(cv::COLOR_BGR2RGB);
 
  160   res[std::make_pair(BGR, RGBA)].push_back(cv::COLOR_BGR2RGBA);
 
  161   res[std::make_pair(BGR, BGRA)].push_back(cv::COLOR_BGR2BGRA);
 
  163   res[std::make_pair(RGBA, 
GRAY)].push_back(cv::COLOR_RGBA2GRAY);
 
  164   res[std::make_pair(RGBA, RGB)].push_back(cv::COLOR_RGBA2RGB);
 
  165   res[std::make_pair(RGBA, BGR)].push_back(cv::COLOR_RGBA2BGR);
 
  166   res[std::make_pair(RGBA, BGRA)].push_back(cv::COLOR_RGBA2BGRA);
 
  168   res[std::make_pair(BGRA, 
GRAY)].push_back(cv::COLOR_BGRA2GRAY);
 
  169   res[std::make_pair(BGRA, RGB)].push_back(cv::COLOR_BGRA2RGB);
 
  170   res[std::make_pair(BGRA, BGR)].push_back(cv::COLOR_BGRA2BGR);
 
  171   res[std::make_pair(BGRA, RGBA)].push_back(cv::COLOR_BGRA2RGBA);
 
  173   res[std::make_pair(YUV422, 
GRAY)].push_back(cv::COLOR_YUV2GRAY_UYVY);
 
  174   res[std::make_pair(YUV422, RGB)].push_back(cv::COLOR_YUV2RGB_UYVY);
 
  175   res[std::make_pair(YUV422, BGR)].push_back(cv::COLOR_YUV2BGR_UYVY);
 
  176   res[std::make_pair(YUV422, RGBA)].push_back(cv::COLOR_YUV2RGBA_UYVY);
 
  177   res[std::make_pair(YUV422, BGRA)].push_back(cv::COLOR_YUV2BGRA_UYVY);
 
  180   res[std::make_pair(BAYER_RGGB, 
GRAY)].push_back(cv::COLOR_BayerBG2GRAY);
 
  181   res[std::make_pair(BAYER_RGGB, RGB)].push_back(cv::COLOR_BayerBG2RGB);
 
  182   res[std::make_pair(BAYER_RGGB, BGR)].push_back(cv::COLOR_BayerBG2BGR);
 
  184   res[std::make_pair(BAYER_BGGR, 
GRAY)].push_back(cv::COLOR_BayerRG2GRAY);
 
  185   res[std::make_pair(BAYER_BGGR, RGB)].push_back(cv::COLOR_BayerRG2RGB);
 
  186   res[std::make_pair(BAYER_BGGR, BGR)].push_back(cv::COLOR_BayerRG2BGR);
 
  188   res[std::make_pair(BAYER_GBRG, 
GRAY)].push_back(cv::COLOR_BayerGR2GRAY);
 
  189   res[std::make_pair(BAYER_GBRG, RGB)].push_back(cv::COLOR_BayerGR2RGB);
 
  190   res[std::make_pair(BAYER_GBRG, BGR)].push_back(cv::COLOR_BayerGR2BGR);
 
  192   res[std::make_pair(BAYER_GRBG, 
GRAY)].push_back(cv::COLOR_BayerGB2GRAY);
 
  193   res[std::make_pair(BAYER_GRBG, RGB)].push_back(cv::COLOR_BayerGB2RGB);
 
  194   res[std::make_pair(BAYER_GRBG, BGR)].push_back(cv::COLOR_BayerGB2BGR);
 
  199 const std::vector<int> getConversionCode(std::string src_encoding, std::string dst_encoding)
 
  201   Encoding src_encod = getEncoding(src_encoding);
 
  202   Encoding dst_encod = getEncoding(dst_encoding);
 
  211   if (!is_src_color_format) {
 
  212     if (is_dst_color_format)
 
  213       throw Exception(
"[" + src_encoding + 
"] is not a color format. but [" + dst_encoding +
 
  214                       "] is. The conversion does not make sense");
 
  215     if (!is_num_channels_the_same)
 
  216       throw Exception(
"[" + src_encoding + 
"] and [" + dst_encoding + 
"] do not have the same number of channel");
 
  217     return std::vector<int>(1, SAME_FORMAT);
 
  222   if (!is_dst_color_format) {
 
  223     if (!is_num_channels_the_same)
 
  224       throw Exception(
"[" + src_encoding + 
"] is a color format but [" + dst_encoding + 
"] " +
 
  225                       "is not so they must have the same OpenCV type, CV_8UC3, CV16UC1 ....");
 
  226     return std::vector<int>(1, SAME_FORMAT);
 
  230   static const std::map<std::pair<Encoding, Encoding>, std::vector<int> > CONVERSION_CODES = getConversionCodes();
 
  232   std::pair<Encoding, Encoding> key(src_encod, dst_encod);
 
  233   std::map<std::pair<Encoding, Encoding>, std::vector<int> >::const_iterator val = CONVERSION_CODES.find(key);
 
  234   if (val == CONVERSION_CODES.end())
 
  235     throw Exception(
"Unsupported conversion from [" + src_encoding +
 
  236                       "] to [" + dst_encoding + 
"]");
 
  239   std::vector<int> res = val->second;
 
  240   if ((enc::bitDepth(src_encoding) != enc::bitDepth(dst_encoding)) && (getEncoding(src_encoding) != getEncoding(dst_encoding)))
 
  241     res.push_back(SAME_FORMAT);
 
  249 cv::Mat matFromImage(
const sensor_msgs::Image& source)
 
  251   int source_type = 
getCvType(source.encoding);
 
  255   if (source.step < source.width * byte_depth * num_channels)
 
  257     std::stringstream ss;
 
  258     ss << 
"Image is wrongly formed: step < width * byte_depth * num_channels  or  " << source.step << 
" != " <<
 
  259         source.width << 
" * " << byte_depth << 
" * " << num_channels;
 
  260     throw Exception(ss.str());
 
  263   if (source.height * source.step != source.data.size())
 
  265     std::stringstream ss;
 
  266     ss << 
"Image is wrongly formed: height * step != size  or  " << source.height << 
" * " <<
 
  267               source.step << 
" != " << source.data.size();
 
  268     throw Exception(ss.str());
 
  272   cv::Mat mat(source.height, source.width, source_type, 
const_cast<uchar*
>(&source.data[0]), source.step);
 
  273   if ((boost::endian::order::native == boost::endian::order::big && source.is_bigendian) ||
 
  274       (boost::endian::order::native == boost::endian::order::little && !source.is_bigendian) ||
 
  279   mat = cv::Mat(source.height, source.width, CV_MAKETYPE(CV_8U, num_channels*byte_depth),
 
  280                 const_cast<uchar*
>(&source.data[0]), source.step);
 
  281   cv::Mat mat_swap(source.height, source.width, mat.type());
 
  283   std::vector<int> fromTo;
 
  284   fromTo.reserve(num_channels*byte_depth);
 
  285   for(
int i = 0; i < num_channels; ++i)
 
  286     for(
int j = 0; j < byte_depth; ++j)
 
  288       fromTo.push_back(byte_depth*i + j);
 
  289       fromTo.push_back(byte_depth*i + byte_depth - 1 - j);
 
  291   cv::mixChannels(std::vector<cv::Mat>(1, mat), std::vector<cv::Mat>(1, mat_swap), fromTo);
 
  294   mat_swap.reshape(num_channels);
 
  300 CvImagePtr toCvCopyImpl(
const cv::Mat& source,
 
  301                         const std_msgs::Header& src_header,
 
  302                         const std::string& src_encoding,
 
  303                         const std::string& dst_encoding)
 
  306   CvImagePtr ptr = boost::make_shared<CvImage>();
 
  307   ptr->header = src_header;
 
  310   if (dst_encoding.empty() || dst_encoding == src_encoding)
 
  312     ptr->encoding = src_encoding;
 
  313     source.copyTo(ptr->image);
 
  318     const std::vector<int> conversion_codes = getConversionCode(src_encoding, dst_encoding);
 
  319     cv::Mat image1 = source;
 
  321     for(
size_t i=0; i<conversion_codes.size(); ++i) {
 
  322       int conversion_code = conversion_codes[i];
 
  323       if (conversion_code == SAME_FORMAT)
 
  329         int image2_type = CV_MAKETYPE(CV_MAT_DEPTH(
getCvType(dst_encoding)), image1.channels());
 
  332         if (src_depth == 8 && dst_depth == 16)
 
  333           image1.convertTo(image2, image2_type, 65535. / 255.);
 
  334         else if (src_depth == 16 && dst_depth == 8)
 
  335           image1.convertTo(image2, image2_type, 255. / 65535.);
 
  337           image1.convertTo(image2, image2_type);
 
  347     ptr->encoding = dst_encoding;
 
  357   sensor_msgs::ImagePtr ptr = boost::make_shared<sensor_msgs::Image>();
 
  364   ros_image.header = 
header;
 
  365   ros_image.height = 
image.rows;
 
  366   ros_image.width = 
image.cols;
 
  368   ros_image.is_bigendian = (boost::endian::order::native == boost::endian::order::big);
 
  369   ros_image.step = 
image.cols * 
image.elemSize();
 
  370   size_t size = ros_image.step * 
image.rows;
 
  371   ros_image.data.resize(size);
 
  373   if (
image.isContinuous())
 
  375     memcpy((
char*)(&ros_image.data[0]), 
image.data, size);
 
  380     uchar* ros_data_ptr = (uchar*)(&ros_image.data[0]);
 
  381     uchar* cv_data_ptr = 
image.data;
 
  382     for (
int i = 0; i < 
image.rows; ++i)
 
  384       memcpy(ros_data_ptr, cv_data_ptr, ros_image.step);
 
  385       ros_data_ptr += ros_image.step;
 
  386       cv_data_ptr += 
image.step;
 
  393                     const std::string& encoding)
 
  399                     const std::string& encoding)
 
  402   return toCvCopyImpl(matFromImage(source), source.header, source.encoding, encoding);
 
  407                           const std::string& encoding)
 
  409   return toCvShare(*source, source, encoding);
 
  414                           const std::string& encoding)
 
  417   if ((!encoding.empty() && source.encoding != encoding) || (source.is_bigendian &&
 
  418       (boost::endian::order::native != boost::endian::order::big)))
 
  421   CvImagePtr ptr = boost::make_shared<CvImage>();
 
  422   ptr->header = source.header;
 
  423   ptr->encoding = source.encoding;
 
  424   ptr->tracked_object_ = tracked_object;
 
  425   ptr->image = matFromImage(source);
 
  430                     const std::string& encoding)
 
  432   return toCvCopyImpl(source->image, source->header, source->encoding, encoding);
 
  439   sensor_msgs::CompressedImagePtr ptr = boost::make_shared<sensor_msgs::CompressedImage>();
 
  482   ros_image.header = 
header;
 
  490     CvImagePtr tempThis = boost::make_shared<CvImage>(*
this);
 
  494       temp = 
cvtColor(tempThis, enc::BGRA8);
 
  498       temp = 
cvtColor(tempThis, enc::BGR8);
 
  503   std::string format = 
getFormat(dst_format);
 
  504   ros_image.format = format;
 
  505   cv::imencode(
"." + format, 
image, ros_image.data);
 
  510                     const std::string& encoding)
 
  515 CvImagePtr toCvCopy(
const sensor_msgs::CompressedImage& source, 
const std::string& encoding)
 
  518   const cv::Mat_<uchar> in(1, source.data.size(), 
const_cast<uchar*
>(&source.data[0]));
 
  520   const cv::Mat rgb_a = cv::imdecode(in, cv::IMREAD_UNCHANGED);
 
  522   if (encoding != enc::MONO16) {
 
  523     switch (rgb_a.channels())
 
  526         return toCvCopyImpl(rgb_a, source.header, enc::BGRA8, encoding);
 
  529         return toCvCopyImpl(rgb_a, source.header, enc::BGR8, encoding);
 
  532         return toCvCopyImpl(rgb_a, source.header, enc::MONO8, encoding);
 
  539     return toCvCopyImpl(rgb_a, source.header, enc::MONO16, encoding);
 
  544                                    const std::string& encoding_out,
 
  551     throw Exception(
"cv_bridge.cvtColorForDisplay() called with empty image.");
 
  553   std::string encoding = encoding_out;
 
  554   if (encoding.empty())
 
  559       if (enc::numChannels(source->encoding) == 1)
 
  561         if ((source->encoding == enc::TYPE_32SC1) ||
 
  562             (enc::bitDepth(source->encoding) == 8) ||
 
  563             (enc::bitDepth(source->encoding) == 16) ||
 
  564             (enc::bitDepth(source->encoding) == 32))
 
  565           encoding = enc::BGR8;
 
  567           throw std::runtime_error(
"Unsupported depth of the source encoding " + encoding);
 
  572         if ((enc::bitDepth(source->encoding) == 8) ||
 
  573             (enc::bitDepth(source->encoding) == 16))
 
  574           encoding = enc::BGR8;
 
  576           throw std::runtime_error(
"Unsupported depth of the source encoding " + encoding);
 
  580     catch (
const std::runtime_error& e)
 
  582       throw Exception(
"cv_bridge.cvtColorForDisplay() output encoding is empty and cannot be guessed.");
 
  587     if ((!enc::isColor(encoding_out) && !enc::isMono(encoding_out)) ||
 
  588         (enc::bitDepth(encoding) != 8))
 
  589       throw Exception(
"cv_bridge.cvtColorForDisplay() does not have an output encoding that is color or mono, and has is bit in depth");
 
  595       source->encoding == enc::TYPE_32SC1)
 
  598     result->header = source->header;
 
  599     result->encoding = encoding;
 
  600     result->image = cv::Mat(source->image.rows, source->image.cols, CV_8UC3);
 
  601     for (
size_t j = 0; j < source->image.rows; ++j) {
 
  602       for (
size_t i = 0; i < source->image.cols; ++i) {
 
  603         int label = source->image.at<
int>(j, i);
 
  605           result->image.at<cv::Vec3b>(j, i) = cv::Vec3b(0, 0, 0);
 
  611           result->image.at<cv::Vec3b>(j, i) = cv::Vec3b(
int(rgb[2] * 255), int(rgb[1] * 255), int(rgb[0] * 255));
 
  621     cv::minMaxLoc(source->image, &min_image_value, &max_image_value);
 
  622     if (min_image_value == max_image_value)
 
  625       result->header = source->header;
 
  626       result->encoding = encoding;
 
  627       if (enc::bitDepth(encoding) == 1)
 
  629         result->image = cv::Mat(source->image.size(), CV_8UC1);
 
  630         result->image.setTo(255./2.);
 
  632         result->image = cv::Mat(source->image.size(), CV_8UC3);
 
  633         result->image.setTo(cv::Scalar(1., 1., 1.)*255./2.);
 
  639   if (min_image_value != max_image_value)
 
  641     if (enc::numChannels(source->encoding) != 1)
 
  642       throw Exception(
"cv_bridge.cvtColorForDisplay() scaling for images with more than one channel is unsupported");
 
  644     img_scaled->header = source->header;
 
  647       cv::Mat(source->image-min_image_value).convertTo(img_scaled->image, CV_8UC1, 255.0 /
 
  648         (max_image_value - min_image_value));
 
  651       cv::Mat(source->image-min_image_value).convertTo(img_scaled->image, CV_8UC3, 255.0 /
 
  652         (max_image_value - min_image_value));
 
  653       cv::applyColorMap(img_scaled->image, img_scaled->image, options.
colormap);
 
  655       if (source->encoding == enc::TYPE_32FC1) {
 
  656         for (
size_t j = 0; j < source->image.rows; ++j) {
 
  657           for (
size_t i = 0; i < source->image.cols; ++i) {
 
  658             float float_value = source->image.at<
float>(j, i);
 
  659             if (std::isnan(float_value)) {
 
  660               img_scaled->image.at<cv::Vec3b>(j, i) = cv::Vec3b(0, 0, 0);
 
  666     return cvtColor(img_scaled, encoding);
 
  671   source_typed->image = source->image;
 
  672   source_typed->header = source->header;
 
  673   source_typed->encoding = source->encoding;
 
  676   if (source->encoding == 
"CV_8UC1")
 
  678   else if (source->encoding == 
"16UC1")
 
  680   else if (source->encoding == 
"CV_8UC3")
 
  682   else if (source->encoding == 
"CV_8UC4")
 
  684   else if (source->encoding == 
"CV_16UC3")
 
  686   else if (source->encoding == 
"CV_16UC4")
 
  690   if (source_typed->encoding == encoding)
 
  696     return cvtColor(source_typed, encoding);
 
  700     throw Exception(
"cv_bridge.cvtColorForDisplay() while trying to convert image from '" + source->encoding + 
"' to '" + encoding + 
"' an exception was thrown (" + e.what() + 
")");