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 #include "rtabmap/core/Compression.h"
00029 #include <rtabmap/utilite/ULogger.h>
00030 #include <rtabmap/utilite/UConversion.h>
00031 #include <opencv2/opencv.hpp>
00032
00033 #include <zlib.h>
00034
00035 namespace rtabmap {
00036
00037
00038 CompressionThread::CompressionThread(const cv::Mat & mat, const std::string & format) :
00039 uncompressedData_(mat),
00040 format_(format),
00041 image_(!format.empty()),
00042 compressMode_(true)
00043 {
00044 UASSERT(format.empty() || format.compare(".png") == 0 || format.compare(".jpg") == 0);
00045 }
00046
00047 CompressionThread::CompressionThread(const cv::Mat & bytes, bool isImage) :
00048 compressedData_(bytes),
00049 image_(isImage),
00050 compressMode_(false)
00051 {}
00052 void CompressionThread::mainLoop()
00053 {
00054 if(compressMode_)
00055 {
00056 if(!uncompressedData_.empty())
00057 {
00058 if(image_)
00059 {
00060 compressedData_ = compressImage2(uncompressedData_, format_);
00061 }
00062 else
00063 {
00064 compressedData_ = compressData2(uncompressedData_);
00065 }
00066 }
00067 }
00068 else
00069 {
00070 if(!compressedData_.empty())
00071 {
00072 if(image_)
00073 {
00074 uncompressedData_ = uncompressImage(compressedData_);
00075 }
00076 else
00077 {
00078 uncompressedData_ = uncompressData(compressedData_);
00079 }
00080 }
00081 }
00082 this->kill();
00083 }
00084
00085
00086 std::vector<unsigned char> compressImage(const cv::Mat & image, const std::string & format)
00087 {
00088 std::vector<unsigned char> bytes;
00089 if(!image.empty())
00090 {
00091 if(image.type() == CV_32FC1)
00092 {
00093
00094 cv::Mat bgra(image.size(), CV_8UC4, image.data);
00095 cv::imencode(format, bgra, bytes);
00096 }
00097 else
00098 {
00099 cv::imencode(format, image, bytes);
00100 }
00101 }
00102 return bytes;
00103 }
00104
00105
00106 cv::Mat compressImage2(const cv::Mat & image, const std::string & format)
00107 {
00108 std::vector<unsigned char> bytes = compressImage(image, format);
00109 if(bytes.size())
00110 {
00111 return cv::Mat(1, (int)bytes.size(), CV_8UC1, bytes.data()).clone();
00112 }
00113 return cv::Mat();
00114 }
00115
00116 cv::Mat uncompressImage(const cv::Mat & bytes)
00117 {
00118 cv::Mat image;
00119 if(!bytes.empty())
00120 {
00121 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
00122 image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
00123 #else
00124 image = cv::imdecode(bytes, -1);
00125 #endif
00126 if(image.type() == CV_8UC4)
00127 {
00128 image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
00129 }
00130 }
00131 return image;
00132 }
00133
00134 cv::Mat uncompressImage(const std::vector<unsigned char> & bytes)
00135 {
00136 cv::Mat image;
00137 if(bytes.size())
00138 {
00139 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
00140 image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
00141 #else
00142 image = cv::imdecode(bytes, -1);
00143 #endif
00144 if(image.type() == CV_8UC4)
00145 {
00146 image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
00147 }
00148 }
00149 return image;
00150 }
00151
00152 std::vector<unsigned char> compressData(const cv::Mat & data)
00153 {
00154 std::vector<unsigned char> bytes;
00155 if(!data.empty())
00156 {
00157 uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
00158 uLong destLen = compressBound(sourceLen);
00159 bytes.resize(destLen);
00160 int errCode = compress(
00161 (Bytef *)bytes.data(),
00162 &destLen,
00163 (const Bytef *)data.data,
00164 sourceLen);
00165
00166 bytes.resize(destLen+3*sizeof(int));
00167 *((int*)&bytes[destLen]) = data.rows;
00168 *((int*)&bytes[destLen+sizeof(int)]) = data.cols;
00169 *((int*)&bytes[destLen+2*sizeof(int)]) = data.type();
00170
00171 if(errCode == Z_MEM_ERROR)
00172 {
00173 UERROR("Z_MEM_ERROR : Insufficient memory.");
00174 }
00175 else if(errCode == Z_BUF_ERROR)
00176 {
00177 UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
00178 }
00179 }
00180 return bytes;
00181 }
00182
00183 cv::Mat compressData2(const cv::Mat & data)
00184 {
00185 cv::Mat bytes;
00186 if(!data.empty())
00187 {
00188 uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
00189 uLong destLen = compressBound(sourceLen);
00190 bytes = cv::Mat(1, destLen+3*sizeof(int), CV_8UC1);
00191 int errCode = compress(
00192 (Bytef *)bytes.data,
00193 &destLen,
00194 (const Bytef *)data.data,
00195 sourceLen);
00196 bytes = cv::Mat(bytes, cv::Rect(0,0, destLen+3*sizeof(int), 1));
00197 *((int*)&bytes.data[destLen]) = data.rows;
00198 *((int*)&bytes.data[destLen+sizeof(int)]) = data.cols;
00199 *((int*)&bytes.data[destLen+2*sizeof(int)]) = data.type();
00200
00201 if(errCode == Z_MEM_ERROR)
00202 {
00203 UERROR("Z_MEM_ERROR : Insufficient memory.");
00204 }
00205 else if(errCode == Z_BUF_ERROR)
00206 {
00207 UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
00208 }
00209 }
00210 return bytes;
00211 }
00212
00213 cv::Mat uncompressData(const cv::Mat & bytes)
00214 {
00215 UASSERT(bytes.empty() || bytes.type() == CV_8UC1);
00216 return uncompressData(bytes.data, bytes.cols*bytes.rows);
00217 }
00218
00219 cv::Mat uncompressData(const std::vector<unsigned char> & bytes)
00220 {
00221 return uncompressData(bytes.data(), (unsigned long)bytes.size());
00222 }
00223
00224 cv::Mat uncompressData(const unsigned char * bytes, unsigned long size)
00225 {
00226 cv::Mat data;
00227 if(bytes && size>=3*sizeof(int))
00228 {
00229
00230 int height = *((int*)&bytes[size-3*sizeof(int)]);
00231 int width = *((int*)&bytes[size-2*sizeof(int)]);
00232 int type = *((int*)&bytes[size-1*sizeof(int)]);
00233
00234 data = cv::Mat(height, width, type);
00235 uLongf totalUncompressed = uLongf(data.total())*uLongf(data.elemSize());
00236
00237 int errCode = uncompress(
00238 (Bytef*)data.data,
00239 &totalUncompressed,
00240 (const Bytef*)bytes,
00241 uLong(size));
00242
00243 if(errCode == Z_MEM_ERROR)
00244 {
00245 UERROR("Z_MEM_ERROR : Insufficient memory.");
00246 }
00247 else if(errCode == Z_BUF_ERROR)
00248 {
00249 UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
00250 }
00251 else if(errCode == Z_DATA_ERROR)
00252 {
00253 UERROR("Z_DATA_ERROR : The compressed data (referenced by source) was corrupted.");
00254 }
00255 }
00256 return data;
00257 }
00258
00259 }