Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00063 sensor_msgs::CompressedImage compressed;
00064 compressed.header = image.header;
00065 compressed.format = image.encoding;
00066
00067
00068 std::vector<int> params;
00069
00070
00071 int bitDepth = enc::bitDepth(image.encoding);
00072
00073 params.push_back(CV_IMWRITE_PXM_BINARY);
00074 params.push_back(1);
00075
00076
00077 compressed.format += "; iz compressed ";
00078
00079
00080 if ((bitDepth == 8) || (bitDepth == 16))
00081 {
00082
00083
00084 stringstream targetFormat;
00085 if (enc::isColor(image.encoding))
00086 {
00087
00088 targetFormat << "bgr" << bitDepth;
00089 compressed.format += targetFormat.str();
00090 }
00091
00092
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
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
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
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
00188 cv_ptr->header = compressed->header;
00189
00190
00191 try
00192 {
00193 cv_ptr->image = cv::imdecode(cv::Mat(ppm_data), CV_LOAD_IMAGE_COLOR);
00194
00195
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
00224 if (compressed_bgr_image)
00225 {
00226
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
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
00274 sensor_msgs::Image msg;
00275 cv_ptr->toImageMsg(msg);
00276 return msg;
00277 }
00278
00279 return sensor_msgs::Image();
00280 }
00281 }