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
00032
00033
00034
00035 #include "compressed_image_transport/compressed_publisher.h"
00036 #include <cv_bridge/cv_bridge.h>
00037 #include <sensor_msgs/image_encodings.h>
00038 #include <cv.h>
00039 #include <highgui.h>
00040 #include <boost/make_shared.hpp>
00041
00042 #include "compressed_image_transport/compression_common.h"
00043
00044 #include <vector>
00045 #include <sstream>
00046
00047 using namespace cv;
00048 using namespace std;
00049
00050 namespace enc = sensor_msgs::image_encodings;
00051
00052 namespace compressed_image_transport
00053 {
00054
00055 void CompressedPublisher::advertiseImpl(ros::NodeHandle &nh, const std::string &base_topic, uint32_t queue_size,
00056 const image_transport::SubscriberStatusCallback &user_connect_cb,
00057 const image_transport::SubscriberStatusCallback &user_disconnect_cb,
00058 const ros::VoidPtr &tracked_object, bool latch)
00059 {
00060 typedef image_transport::SimplePublisherPlugin<sensor_msgs::CompressedImage> Base;
00061 Base::advertiseImpl(nh, base_topic, queue_size, user_connect_cb, user_disconnect_cb, tracked_object, latch);
00062
00063
00064 reconfigure_server_ = boost::make_shared<ReconfigureServer>(this->nh());
00065 ReconfigureServer::CallbackType f = boost::bind(&CompressedPublisher::configCb, this, _1, _2);
00066 reconfigure_server_->setCallback(f);
00067 }
00068
00069 void CompressedPublisher::configCb(Config& config, uint32_t level)
00070 {
00071 config_ = config;
00072 }
00073
00074 void CompressedPublisher::publish(const sensor_msgs::Image& message, const PublishFn& publish_fn) const
00075 {
00076
00077 sensor_msgs::CompressedImage compressed;
00078 compressed.header = message.header;
00079 compressed.format = message.encoding;
00080
00081
00082 std::vector<int> params;
00083 params.resize(3, 0);
00084
00085
00086 compressionFormat encodingFormat = UNDEFINED;
00087 if (config_.format == "jpeg")
00088 encodingFormat = JPEG;
00089 if (config_.format == "png")
00090 encodingFormat = PNG;
00091
00092
00093 int bitDepth = enc::bitDepth(message.encoding);
00094 int numChannels = enc::numChannels(message.encoding);
00095
00096 switch (encodingFormat)
00097 {
00098
00099 case JPEG:
00100 {
00101 params[0] = CV_IMWRITE_JPEG_QUALITY;
00102 params[1] = config_.jpeg_quality;
00103
00104
00105 compressed.format += "; jpeg compressed ";
00106
00107
00108 if ((bitDepth == 8) || (bitDepth == 16))
00109 {
00110
00111 std::string targetFormat;
00112 if (enc::isColor(message.encoding))
00113 {
00114
00115 targetFormat = "bgr8";
00116 compressed.format += targetFormat;
00117 }
00118
00119
00120 cv_bridge::CvImagePtr cv_ptr;
00121 try
00122 {
00123 cv_ptr = cv_bridge::toCvCopy(message, targetFormat);
00124
00125
00126 if (cv::imencode(".jpg", cv_ptr->image, compressed.data, params))
00127 {
00128
00129 float cRatio = (float)(cv_ptr->image.rows * cv_ptr->image.cols * cv_ptr->image.elemSize())
00130 / (float)compressed.data.size();
00131 ROS_DEBUG("Compressed Image Transport - Codec: jpg, Compression Ratio: 1:%.2f (%lu bytes)", cRatio, compressed.data.size());
00132 }
00133 else
00134 {
00135 ROS_ERROR("cv::imencode (jpeg) failed on input image");
00136 }
00137 }
00138 catch (cv_bridge::Exception& e)
00139 {
00140 ROS_ERROR("%s", e.what());
00141 }
00142 catch (cv::Exception& e)
00143 {
00144 ROS_ERROR("%s", e.what());
00145 }
00146
00147
00148 publish_fn(compressed);
00149 }
00150 else
00151 ROS_ERROR("Compressed Image Transport - JPEG compression requires 8/16-bit color format (input format is: %s)", message.encoding.c_str());
00152
00153 break;
00154 }
00155
00156 case PNG:
00157 {
00158 params[0] = CV_IMWRITE_PNG_COMPRESSION;
00159 params[1] = config_.png_level;
00160
00161
00162 compressed.format += "; png compressed ";
00163
00164
00165 if ((bitDepth == 8) || (bitDepth == 16))
00166 {
00167
00168
00169 stringstream targetFormat;
00170 if (enc::isColor(message.encoding))
00171 {
00172
00173 targetFormat << "bgr" << bitDepth;
00174 compressed.format += targetFormat.str();
00175 }
00176
00177
00178 cv_bridge::CvImagePtr cv_ptr;
00179 try
00180 {
00181 cv_ptr = cv_bridge::toCvCopy(message, targetFormat.str());
00182
00183
00184 if (cv::imencode(".png", cv_ptr->image, compressed.data, params))
00185 {
00186
00187 float cRatio = (float)(cv_ptr->image.rows * cv_ptr->image.cols * cv_ptr->image.elemSize())
00188 / (float)compressed.data.size();
00189 ROS_DEBUG("Compressed Image Transport - Codec: png, Compression Ratio: 1:%.2f (%lu bytes)", cRatio, compressed.data.size());
00190 }
00191 else
00192 {
00193 ROS_ERROR("cv::imencode (png) failed on input image");
00194 }
00195 }
00196 catch (cv_bridge::Exception& e)
00197 {
00198 ROS_ERROR("%s", e.what());
00199 return;
00200 }
00201 catch (cv::Exception& e)
00202 {
00203 ROS_ERROR("%s", e.what());
00204 return;
00205 }
00206
00207
00208 publish_fn(compressed);
00209 }
00210 else
00211 ROS_ERROR("Compressed Image Transport - PNG compression requires 8/16-bit encoded color format (input format is: %s)", message.encoding.c_str());
00212 break;
00213 }
00214
00215 default:
00216 ROS_ERROR("Unknown compression type '%s', valid options are 'jpeg' and 'png'", config_.format.c_str());
00217 break;
00218 }
00219
00220 }
00221
00222 }