Compression.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of the Universite de Sherbrooke nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
31 #include <opencv2/opencv.hpp>
32 
33 #include <zlib.h>
34 
35 namespace rtabmap {
36 
37 // format : ".png" ".jpg" "" (empty is general)
38 CompressionThread::CompressionThread(const cv::Mat & mat, const std::string & format) :
39  uncompressedData_(mat),
40  format_(format),
41  image_(!format.empty()),
42  compressMode_(true)
43 {
44  UASSERT(format.empty() || format.compare(".png") == 0 || format.compare(".jpg") == 0);
45 }
46 // assume image
47 CompressionThread::CompressionThread(const cv::Mat & bytes, bool isImage) :
48  compressedData_(bytes),
49  image_(isImage),
50  compressMode_(false)
51 {}
53 {
54  try
55  {
56  if(compressMode_)
57  {
58  if(!uncompressedData_.empty())
59  {
60  if(image_)
61  {
63  }
64  else
65  {
67  }
68  }
69  }
70  else // uncompress
71  {
72  if(!compressedData_.empty())
73  {
74  if(image_)
75  {
77  }
78  else
79  {
81  }
82  }
83  }
84  }
85  catch (cv::Exception & e) {
86  UERROR("Exception while compressing/uncompressing data: %s", e.what());
87  if(compressMode_)
88  {
89  compressedData_ = cv::Mat();
90  }
91  else
92  {
93  uncompressedData_ = cv::Mat();
94  }
95  }
96  this->kill();
97 }
98 
99 // ".png" or ".jpg"
100 std::vector<unsigned char> compressImage(const cv::Mat & image, const std::string & format)
101 {
102  std::vector<unsigned char> bytes;
103  if(!image.empty())
104  {
105  if(image.type() == CV_32FC1)
106  {
107  //save in 8bits-4channel
108  cv::Mat bgra(image.size(), CV_8UC4, image.data);
109  cv::imencode(format, bgra, bytes);
110  }
111  else
112  {
113  cv::imencode(format, image, bytes);
114  }
115  }
116  return bytes;
117 }
118 
119 // ".png" or ".jpg"
120 cv::Mat compressImage2(const cv::Mat & image, const std::string & format)
121 {
122  std::vector<unsigned char> bytes = compressImage(image, format);
123  if(bytes.size())
124  {
125  return cv::Mat(1, (int)bytes.size(), CV_8UC1, bytes.data()).clone();
126  }
127  return cv::Mat();
128 }
129 
130 cv::Mat uncompressImage(const cv::Mat & bytes)
131 {
132  cv::Mat image;
133  if(!bytes.empty())
134  {
135 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
136  image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
137 #else
138  image = cv::imdecode(bytes, -1);
139 #endif
140  if(image.type() == CV_8UC4)
141  {
142  // Using clone() or copyTo() caused a memory leak !?!?
143  // image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
144  cv::Mat depth(image.size(), CV_32FC1);
145  memcpy(depth.data, image.data, image.total()*image.elemSize());
146  image = depth;
147  }
148  }
149  return image;
150 }
151 
152 cv::Mat uncompressImage(const std::vector<unsigned char> & bytes)
153 {
154  cv::Mat image;
155  if(bytes.size())
156  {
157 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
158  image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
159 #else
160  image = cv::imdecode(bytes, -1);
161 #endif
162  if(image.type() == CV_8UC4)
163  {
164  image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
165  }
166  }
167  return image;
168 }
169 
170 std::vector<unsigned char> compressData(const cv::Mat & data)
171 {
172  std::vector<unsigned char> bytes;
173  if(!data.empty())
174  {
175  uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
176  uLong destLen = compressBound(sourceLen);
177  bytes.resize(destLen);
178  int errCode = compress(
179  (Bytef *)bytes.data(),
180  &destLen,
181  (const Bytef *)data.data,
182  sourceLen);
183 
184  bytes.resize(destLen+3*sizeof(int));
185  *((int*)&bytes[destLen]) = data.rows;
186  *((int*)&bytes[destLen+sizeof(int)]) = data.cols;
187  *((int*)&bytes[destLen+2*sizeof(int)]) = data.type();
188 
189  if(errCode == Z_MEM_ERROR)
190  {
191  UERROR("Z_MEM_ERROR : Insufficient memory.");
192  }
193  else if(errCode == Z_BUF_ERROR)
194  {
195  UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
196  }
197  }
198  return bytes;
199 }
200 
201 cv::Mat compressData2(const cv::Mat & data)
202 {
203  cv::Mat bytes;
204  if(!data.empty())
205  {
206  uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
207  uLong destLen = compressBound(sourceLen);
208  bytes = cv::Mat(1, destLen+3*sizeof(int), CV_8UC1);
209  int errCode = compress(
210  (Bytef *)bytes.data,
211  &destLen,
212  (const Bytef *)data.data,
213  sourceLen);
214  bytes = cv::Mat(bytes, cv::Rect(0,0, destLen+3*sizeof(int), 1));
215  *((int*)&bytes.data[destLen]) = data.rows;
216  *((int*)&bytes.data[destLen+sizeof(int)]) = data.cols;
217  *((int*)&bytes.data[destLen+2*sizeof(int)]) = data.type();
218 
219  if(errCode == Z_MEM_ERROR)
220  {
221  UERROR("Z_MEM_ERROR : Insufficient memory.");
222  }
223  else if(errCode == Z_BUF_ERROR)
224  {
225  UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
226  }
227  }
228  return bytes;
229 }
230 
231 cv::Mat uncompressData(const cv::Mat & bytes)
232 {
233  UASSERT(bytes.empty() || bytes.type() == CV_8UC1);
234  return uncompressData(bytes.data, bytes.cols*bytes.rows);
235 }
236 
237 cv::Mat uncompressData(const std::vector<unsigned char> & bytes)
238 {
239  return uncompressData(bytes.data(), (unsigned long)bytes.size());
240 }
241 
242 cv::Mat uncompressData(const unsigned char * bytes, unsigned long size)
243 {
244  cv::Mat data;
245  if(bytes && size>=3*sizeof(int))
246  {
247  //last 3 int elements are matrix size and type
248  int height = *((int*)&bytes[size-3*sizeof(int)]);
249  int width = *((int*)&bytes[size-2*sizeof(int)]);
250  int type = *((int*)&bytes[size-1*sizeof(int)]);
251 
252  data = cv::Mat(height, width, type);
253  uLongf totalUncompressed = uLongf(data.total())*uLongf(data.elemSize());
254 
255  int errCode = uncompress(
256  (Bytef*)data.data,
257  &totalUncompressed,
258  (const Bytef*)bytes,
259  uLong(size));
260 
261  if(errCode == Z_MEM_ERROR)
262  {
263  UERROR("Z_MEM_ERROR : Insufficient memory.");
264  }
265  else if(errCode == Z_BUF_ERROR)
266  {
267  UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
268  }
269  else if(errCode == Z_DATA_ERROR)
270  {
271  UERROR("Z_DATA_ERROR : The compressed data (referenced by source) was corrupted.");
272  }
273  }
274  return data;
275 }
276 
277 cv::Mat compressString(const std::string & str)
278 {
279  // +1 to include null character
280  return compressData2(cv::Mat(1, str.size()+1, CV_8SC1, (void *)str.data()));
281 }
282 
283 std::string uncompressString(const cv::Mat & bytes)
284 {
285  cv::Mat strMat = uncompressData(bytes);
286  if(!strMat.empty())
287  {
288  UASSERT(strMat.type() == CV_8SC1 && strMat.rows == 1);
289  return (const char*)strMat.data;
290  }
291  return "";
292 }
293 
294 } /* namespace rtabmap */
int
int
Compression.h
rtabmap::uncompressImage
cv::Mat RTABMAP_CORE_EXPORT uncompressImage(const cv::Mat &bytes)
Definition: Compression.cpp:130
bytes
format
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
size
Index size
rtabmap::CompressionThread::mainLoop
virtual void mainLoop()
Definition: Compression.cpp:52
rtabmap::CompressionThread::compressMode_
bool compressMode_
Definition: Compression.h:70
type
rtabmap::compressImage
std::vector< unsigned char > RTABMAP_CORE_EXPORT compressImage(const cv::Mat &image, const std::string &format=".png")
Definition: Compression.cpp:100
true
#define true
Definition: ConvertUTF.c:57
rtabmap::compressData
std::vector< unsigned char > RTABMAP_CORE_EXPORT compressData(const cv::Mat &data)
Definition: Compression.cpp:170
data
int data[]
UConversion.h
Some conversion functions.
UThread::kill
void kill()
Definition: UThread.cpp:48
UASSERT
#define UASSERT(condition)
rtabmap::CompressionThread::uncompressedData_
cv::Mat uncompressedData_
Definition: Compression.h:67
str
rtabmap::compressData2
cv::Mat RTABMAP_CORE_EXPORT compressData2(const cv::Mat &data)
Definition: Compression.cpp:201
rtabmap::CompressionThread::compressedData_
cv::Mat compressedData_
Definition: Compression.h:66
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
ULogger.h
ULogger class and convenient macros.
empty
rtabmap::compressString
cv::Mat RTABMAP_CORE_EXPORT compressString(const std::string &str)
Definition: Compression.cpp:277
rtabmap::CompressionThread::CompressionThread
CompressionThread(const cv::Mat &mat, const std::string &format="")
Definition: Compression.cpp:38
false
#define false
Definition: ConvertUTF.c:56
rtabmap::CompressionThread::format_
std::string format_
Definition: Compression.h:68
rtabmap
Definition: CameraARCore.cpp:35
UERROR
#define UERROR(...)
rtabmap::compressImage2
cv::Mat RTABMAP_CORE_EXPORT compressImage2(const cv::Mat &image, const std::string &format=".png")
Definition: Compression.cpp:120
rtabmap::uncompressString
std::string RTABMAP_CORE_EXPORT uncompressString(const cv::Mat &bytes)
Definition: Compression.cpp:283
rtabmap::CompressionThread::image_
bool image_
Definition: Compression.h:69
mat
else mat
rtabmap::uncompressData
cv::Mat RTABMAP_CORE_EXPORT uncompressData(const cv::Mat &bytes)
Definition: Compression.cpp:231


rtabmap
Author(s): Mathieu Labbe
autogenerated on Mon Jul 1 2024 02:42:26