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 try
00055 {
00056 if(compressMode_)
00057 {
00058 if(!uncompressedData_.empty())
00059 {
00060 if(image_)
00061 {
00062 compressedData_ = compressImage2(uncompressedData_, format_);
00063 }
00064 else
00065 {
00066 compressedData_ = compressData2(uncompressedData_);
00067 }
00068 }
00069 }
00070 else
00071 {
00072 if(!compressedData_.empty())
00073 {
00074 if(image_)
00075 {
00076 uncompressedData_ = uncompressImage(compressedData_);
00077 }
00078 else
00079 {
00080 uncompressedData_ = uncompressData(compressedData_);
00081 }
00082 }
00083 }
00084 }
00085 catch (cv::Exception & e) {
00086 UERROR("Exception while compressing/uncompressing data: %s", e.what());
00087 if(compressMode_)
00088 {
00089 compressedData_ = cv::Mat();
00090 }
00091 else
00092 {
00093 uncompressedData_ = cv::Mat();
00094 }
00095 }
00096 this->kill();
00097 }
00098
00099
00100 std::vector<unsigned char> compressImage(const cv::Mat & image, const std::string & format)
00101 {
00102 std::vector<unsigned char> bytes;
00103 if(!image.empty())
00104 {
00105 if(image.type() == CV_32FC1)
00106 {
00107
00108 cv::Mat bgra(image.size(), CV_8UC4, image.data);
00109 cv::imencode(format, bgra, bytes);
00110 }
00111 else
00112 {
00113 cv::imencode(format, image, bytes);
00114 }
00115 }
00116 return bytes;
00117 }
00118
00119
00120 cv::Mat compressImage2(const cv::Mat & image, const std::string & format)
00121 {
00122 std::vector<unsigned char> bytes = compressImage(image, format);
00123 if(bytes.size())
00124 {
00125 return cv::Mat(1, (int)bytes.size(), CV_8UC1, bytes.data()).clone();
00126 }
00127 return cv::Mat();
00128 }
00129
00130 cv::Mat uncompressImage(const cv::Mat & bytes)
00131 {
00132 cv::Mat image;
00133 if(!bytes.empty())
00134 {
00135 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
00136 image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
00137 #else
00138 image = cv::imdecode(bytes, -1);
00139 #endif
00140 if(image.type() == CV_8UC4)
00141 {
00142
00143
00144 cv::Mat depth(image.size(), CV_32FC1);
00145 memcpy(depth.data, image.data, image.total()*image.elemSize());
00146 image = depth;
00147 }
00148 }
00149 return image;
00150 }
00151
00152 cv::Mat uncompressImage(const std::vector<unsigned char> & bytes)
00153 {
00154 cv::Mat image;
00155 if(bytes.size())
00156 {
00157 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
00158 image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
00159 #else
00160 image = cv::imdecode(bytes, -1);
00161 #endif
00162 if(image.type() == CV_8UC4)
00163 {
00164 image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
00165 }
00166 }
00167 return image;
00168 }
00169
00170 std::vector<unsigned char> compressData(const cv::Mat & data)
00171 {
00172 std::vector<unsigned char> bytes;
00173 if(!data.empty())
00174 {
00175 uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
00176 uLong destLen = compressBound(sourceLen);
00177 bytes.resize(destLen);
00178 int errCode = compress(
00179 (Bytef *)bytes.data(),
00180 &destLen,
00181 (const Bytef *)data.data,
00182 sourceLen);
00183
00184 bytes.resize(destLen+3*sizeof(int));
00185 *((int*)&bytes[destLen]) = data.rows;
00186 *((int*)&bytes[destLen+sizeof(int)]) = data.cols;
00187 *((int*)&bytes[destLen+2*sizeof(int)]) = data.type();
00188
00189 if(errCode == Z_MEM_ERROR)
00190 {
00191 UERROR("Z_MEM_ERROR : Insufficient memory.");
00192 }
00193 else if(errCode == Z_BUF_ERROR)
00194 {
00195 UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
00196 }
00197 }
00198 return bytes;
00199 }
00200
00201 cv::Mat compressData2(const cv::Mat & data)
00202 {
00203 cv::Mat bytes;
00204 if(!data.empty())
00205 {
00206 uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
00207 uLong destLen = compressBound(sourceLen);
00208 bytes = cv::Mat(1, destLen+3*sizeof(int), CV_8UC1);
00209 int errCode = compress(
00210 (Bytef *)bytes.data,
00211 &destLen,
00212 (const Bytef *)data.data,
00213 sourceLen);
00214 bytes = cv::Mat(bytes, cv::Rect(0,0, destLen+3*sizeof(int), 1));
00215 *((int*)&bytes.data[destLen]) = data.rows;
00216 *((int*)&bytes.data[destLen+sizeof(int)]) = data.cols;
00217 *((int*)&bytes.data[destLen+2*sizeof(int)]) = data.type();
00218
00219 if(errCode == Z_MEM_ERROR)
00220 {
00221 UERROR("Z_MEM_ERROR : Insufficient memory.");
00222 }
00223 else if(errCode == Z_BUF_ERROR)
00224 {
00225 UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
00226 }
00227 }
00228 return bytes;
00229 }
00230
00231 cv::Mat uncompressData(const cv::Mat & bytes)
00232 {
00233 UASSERT(bytes.empty() || bytes.type() == CV_8UC1);
00234 return uncompressData(bytes.data, bytes.cols*bytes.rows);
00235 }
00236
00237 cv::Mat uncompressData(const std::vector<unsigned char> & bytes)
00238 {
00239 return uncompressData(bytes.data(), (unsigned long)bytes.size());
00240 }
00241
00242 cv::Mat uncompressData(const unsigned char * bytes, unsigned long size)
00243 {
00244 cv::Mat data;
00245 if(bytes && size>=3*sizeof(int))
00246 {
00247
00248 int height = *((int*)&bytes[size-3*sizeof(int)]);
00249 int width = *((int*)&bytes[size-2*sizeof(int)]);
00250 int type = *((int*)&bytes[size-1*sizeof(int)]);
00251
00252 data = cv::Mat(height, width, type);
00253 uLongf totalUncompressed = uLongf(data.total())*uLongf(data.elemSize());
00254
00255 int errCode = uncompress(
00256 (Bytef*)data.data,
00257 &totalUncompressed,
00258 (const Bytef*)bytes,
00259 uLong(size));
00260
00261 if(errCode == Z_MEM_ERROR)
00262 {
00263 UERROR("Z_MEM_ERROR : Insufficient memory.");
00264 }
00265 else if(errCode == Z_BUF_ERROR)
00266 {
00267 UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
00268 }
00269 else if(errCode == Z_DATA_ERROR)
00270 {
00271 UERROR("Z_DATA_ERROR : The compressed data (referenced by source) was corrupted.");
00272 }
00273 }
00274 return data;
00275 }
00276
00277 cv::Mat compressString(const std::string & str)
00278 {
00279
00280 return compressData2(cv::Mat(1, str.size()+1, CV_8SC1, (void *)str.data()));
00281 }
00282
00283 std::string uncompressString(const cv::Mat & bytes)
00284 {
00285 cv::Mat strMat = uncompressData(bytes);
00286 if(!strMat.empty())
00287 {
00288 UASSERT(strMat.type() == CV_8SC1 && strMat.rows == 1);
00289 return (const char*)strMat.data;
00290 }
00291 return "";
00292 }
00293
00294 }