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