ros_support.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2016-2017, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE 
00021 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00023 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00024 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00027 // DAMAGE.
00028 //
00029 // *****************************************************************************
00030 
00031 #include <cv_bridge/cv_bridge.h>
00032 #include <opencv2/highgui/highgui.hpp>
00033 #include <boost/make_shared.hpp>
00034 #include <imagezero_ros/ros_support.h>
00035 #include <ros/ros.h>
00036 #include <sensor_msgs/image_encodings.h>
00037 
00038 using namespace cv;
00039 using namespace std;
00040 
00051 namespace enc = sensor_msgs::image_encodings;
00052 
00053 namespace IZ
00054 {
00055   sensor_msgs::CompressedImage compressImage(const sensor_msgs::Image& image)
00056   {
00057     if (!encode_tables_initialized) {
00058       encode_tables_initialized = true;
00059       IZ::initEncodeTable();
00060     }
00061 
00062     // Compressed image message
00063     sensor_msgs::CompressedImage compressed;
00064     compressed.header = image.header;
00065     compressed.format = image.encoding;
00066 
00067     // Compression settings
00068     std::vector<int> params;
00069 
00070     // Bit depth of image encoding
00071     int bitDepth = enc::bitDepth(image.encoding);
00072 
00073     params.push_back(CV_IMWRITE_PXM_BINARY);
00074     params.push_back(1);
00075 
00076     // Update ros message format header
00077     compressed.format += "; iz compressed ";
00078 
00079     // Check input format
00080     if ((bitDepth == 8) || (bitDepth == 16))
00081     {
00082 
00083       // Target image format
00084       stringstream targetFormat;
00085       if (enc::isColor(image.encoding))
00086       {
00087         // convert color images to RGB domain
00088         targetFormat << "bgr" << bitDepth;
00089         compressed.format += targetFormat.str();
00090       }
00091 
00092       // OpenCV-ros bridge
00093       try
00094       {
00095         boost::shared_ptr<sensor_msgs::CompressedImagePtr> tracked_object;
00096         cv_bridge::CvImageConstPtr cv_ptr = cv_bridge::toCvShare(image, tracked_object, targetFormat.str());
00097 
00098         IZ::PortableImage pi;
00099 
00100         // Compress image
00101         std::vector<unsigned char> ppm_buffer;
00102         ros::Time now = ros::Time::now();
00103         if (cv::imencode(".ppm", cv_ptr->image, ppm_buffer, params))
00104         {
00105           if (!pi.readHeader((const unsigned char*) &ppm_buffer[0]))
00106           {
00107             std::stringstream ss;
00108             for (int i = 0; i < 20; i++)
00109             {
00110               ss << ppm_buffer[i];
00111             }
00112             ROS_ERROR("Unable to read PPM produced by OpenCV.  First few bytes: %s", ss.str().c_str());
00113             return sensor_msgs::CompressedImage();
00114           }
00115           if (pi.components() != 3)
00116           {
00117             ROS_ERROR("Can only handle 24-bit PPM files.");
00118             return sensor_msgs::CompressedImage();
00119           }
00120           unsigned char *dest = static_cast<unsigned char*>(malloc(pi.height() * pi.width() * 4 + 33));
00121           //IZ::initEncodeTable();
00122           unsigned char *destEnd = IZ::encodeImage(pi, dest);
00123           size_t size = destEnd - dest;
00124           compressed.data.resize(size);
00125           memcpy(&compressed.data[0], dest, size);
00126           free(dest);
00127           ros::Time iz_time = ros::Time::now();
00128           ROS_DEBUG_THROTTLE(1, "Took %lums to compress %lu bytes to %lu bytes (%f ratio)",
00129                              (iz_time - now).toNSec()/1000000L,
00130                              image.data.size(),
00131                              compressed.data.size(),
00132                              (double)image.data.size() / (double)image.data.size());
00133         }
00134         else
00135         {
00136           ROS_ERROR("cv::imencode (ppm) failed on input image");
00137           return sensor_msgs::CompressedImage();
00138         }
00139       }
00140       catch (cv_bridge::Exception& e)
00141       {
00142         ROS_ERROR("%s", e.what());
00143         return sensor_msgs::CompressedImage();
00144       }
00145       catch (cv::Exception& e)
00146       {
00147         ROS_ERROR("%s", e.what());
00148         return sensor_msgs::CompressedImage();
00149       }
00150       
00151       return compressed;
00152     }
00153     else
00154     {
00155       ROS_ERROR(
00156           "Compressed Image Transport - ImageZero compression requires 8/16-bit encoded color format (input format is: %s)",
00157           image.encoding.c_str());
00158     }
00159 
00160     return sensor_msgs::CompressedImage();
00161   }
00162 
00163   sensor_msgs::Image decompressImage(const sensor_msgs::CompressedImageConstPtr& compressed)
00164   {
00165     if (!decode_tables_initialized){
00166       decode_tables_initialized = true;
00167       IZ::initDecodeTable();
00168     }
00169 
00170     IZ::PortableImage pi;
00171     //IZ::initDecodeTable();
00172     IZ::decodeImageSize(pi, &compressed->data[0]);
00173     pi.setComponents(3);
00174     const unsigned int dataSize = pi.width() * pi.height() * pi.components();
00175     unsigned char* dest = (unsigned char*) malloc(dataSize + 33);
00176     pi.writeHeader(dest);
00177     IZ::decodeImage(pi, &compressed->data[0]);
00178 
00179     std::vector<unsigned char> ppm_data;
00180     size_t size = pi.data() - dest + dataSize;
00181     ppm_data.resize(size);
00182     memcpy(&ppm_data[0], dest, size);
00183     free(dest);
00184 
00185     cv_bridge::CvImagePtr cv_ptr(new cv_bridge::CvImage);
00186 
00187     // Copy compressed header
00188     cv_ptr->header = compressed->header;
00189 
00190     // Decode color/mono image
00191     try
00192     {
00193       cv_ptr->image = cv::imdecode(cv::Mat(ppm_data), CV_LOAD_IMAGE_COLOR);
00194 
00195       // Assign image encoding string
00196       const size_t split_pos = compressed->format.find(';');
00197       if (split_pos == std::string::npos)
00198       {
00199         switch (cv_ptr->image.channels())
00200         {
00201           case 1:
00202             cv_ptr->encoding = enc::MONO8;
00203             break;
00204           case 3:
00205             cv_ptr->encoding = enc::BGR8;
00206             break;
00207           default:
00208             ROS_ERROR("Unsupported number of channels: %i", cv_ptr->image.channels());
00209             break;
00210         }
00211       }
00212       else
00213       {
00214         std::string image_encoding = compressed->format.substr(0, split_pos);
00215 
00216         cv_ptr->encoding = image_encoding;
00217 
00218         if (enc::isColor(image_encoding))
00219         {
00220           std::string compressed_encoding = compressed->format.substr(split_pos);
00221           bool compressed_bgr_image = (compressed_encoding.find("compressed bgr") != std::string::npos);
00222 
00223           // Revert color transformation
00224           if (compressed_bgr_image)
00225           {
00226             // if necessary convert colors from bgr to rgb
00227             if ((image_encoding == enc::RGB8) || (image_encoding == enc::RGB16))
00228             {
00229               cv::cvtColor(cv_ptr->image, cv_ptr->image, CV_BGR2RGB);
00230             }
00231 
00232             if ((image_encoding == enc::RGBA8) || (image_encoding == enc::RGBA16))
00233             {
00234               cv::cvtColor(cv_ptr->image, cv_ptr->image, CV_BGR2RGBA);
00235             }
00236 
00237             if ((image_encoding == enc::BGRA8) || (image_encoding == enc::BGRA16))
00238             {
00239               cv::cvtColor(cv_ptr->image, cv_ptr->image, CV_BGR2BGRA);
00240             }
00241           }
00242           else
00243           {
00244             // if necessary convert colors from rgb to bgr
00245             if ((image_encoding == enc::BGR8) || (image_encoding == enc::BGR16))
00246             {
00247               cv::cvtColor(cv_ptr->image, cv_ptr->image, CV_RGB2BGR);
00248             }
00249 
00250             if ((image_encoding == enc::BGRA8) || (image_encoding == enc::BGRA16))
00251             {
00252               cv::cvtColor(cv_ptr->image, cv_ptr->image, CV_RGB2BGRA);
00253             }
00254 
00255             if ((image_encoding == enc::RGBA8) || (image_encoding == enc::RGBA16))
00256             {
00257               cv::cvtColor(cv_ptr->image, cv_ptr->image, CV_RGB2RGBA);
00258             }
00259           }
00260         }
00261       }
00262     }
00263     catch (cv::Exception& e)
00264     {
00265       ROS_ERROR("%s", e.what());
00266     }
00267 
00268     size_t rows = cv_ptr->image.rows;
00269     size_t cols = cv_ptr->image.cols;
00270 
00271     if ((rows > 0) && (cols > 0))
00272     {
00273       // Publish message to user callback
00274       sensor_msgs::Image msg;
00275       cv_ptr->toImageMsg(msg);
00276       return msg;
00277     }
00278 
00279     return sensor_msgs::Image();
00280   }
00281 }


imagezero_ros
Author(s): P. J. Reed
autogenerated on Thu Jun 6 2019 21:34:58