1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
8 //
9 //
10 // License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
22 //
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
26 //
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "precomp.hpp"
44 #include "bitstrm.hpp"
45
46 namespace cv
47 {
48
49 const int BS_DEF_BLOCK_SIZE = 1<<15;
50
bsIsBigEndian(void)51 bool bsIsBigEndian( void )
52 {
53 return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
54 }
55
56 ///////////////////////// RBaseStream ////////////////////////////
57
isOpened()58 bool RBaseStream::isOpened()
59 {
60 return m_is_opened;
61 }
62
allocate()63 void RBaseStream::allocate()
64 {
65 if( !m_allocated )
66 {
67 m_start = new uchar[m_block_size];
68 m_end = m_start + m_block_size;
69 m_current = m_end;
70 m_allocated = true;
71 }
72 }
73
74
RBaseStream()75 RBaseStream::RBaseStream()
76 {
77 m_start = m_end = m_current = 0;
78 m_file = 0;
79 m_block_size = BS_DEF_BLOCK_SIZE;
80 m_is_opened = false;
81 m_allocated = false;
82 }
83
84
~RBaseStream()85 RBaseStream::~RBaseStream()
86 {
87 close(); // Close files
88 release(); // free buffers
89 }
90
91
readBlock()92 void RBaseStream::readBlock()
93 {
94 setPos( getPos() ); // normalize position
95
96 if( m_file == 0 )
97 {
98 if( m_block_pos == 0 && m_current < m_end )
99 return;
100 throw RBS_THROW_EOS;
101 }
102
103 fseek( m_file, m_block_pos, SEEK_SET );
104 size_t readed = fread( m_start, 1, m_block_size, m_file );
105 m_end = m_start + readed;
106 m_current = m_start;
107
108 if( readed == 0 || m_current >= m_end )
109 throw RBS_THROW_EOS;
110 }
111
112
open(const String & filename)113 bool RBaseStream::open( const String& filename )
114 {
115 close();
116 allocate();
117
118 m_file = fopen( filename.c_str(), "rb" );
119 if( m_file )
120 {
121 m_is_opened = true;
122 setPos(0);
123 readBlock();
124 }
125 return m_file != 0;
126 }
127
open(const Mat & buf)128 bool RBaseStream::open( const Mat& buf )
129 {
130 close();
131 if( buf.empty() )
132 return false;
133 CV_Assert(buf.isContinuous());
134 m_start = buf.data;
135 m_end = m_start + buf.cols*buf.rows*buf.elemSize();
136 m_allocated = false;
137 m_is_opened = true;
138 setPos(0);
139
140 return true;
141 }
142
close()143 void RBaseStream::close()
144 {
145 if( m_file )
146 {
147 fclose( m_file );
148 m_file = 0;
149 }
150 m_is_opened = false;
151 if( !m_allocated )
152 m_start = m_end = m_current = 0;
153 }
154
155
release()156 void RBaseStream::release()
157 {
158 if( m_allocated )
159 delete[] m_start;
160 m_start = m_end = m_current = 0;
161 m_allocated = false;
162 }
163
164
setPos(int pos)165 void RBaseStream::setPos( int pos )
166 {
167 assert( isOpened() && pos >= 0 );
168
169 if( !m_file )
170 {
171 m_current = m_start + pos;
172 m_block_pos = 0;
173 return;
174 }
175
176 int offset = pos % m_block_size;
177 m_block_pos = pos - offset;
178 m_current = m_start + offset;
179 }
180
181
getPos()182 int RBaseStream::getPos()
183 {
184 assert( isOpened() );
185 return m_block_pos + (int)(m_current - m_start);
186 }
187
skip(int bytes)188 void RBaseStream::skip( int bytes )
189 {
190 assert( bytes >= 0 );
191 m_current += bytes;
192 }
193
194 ///////////////////////// RLByteStream ////////////////////////////
195
~RLByteStream()196 RLByteStream::~RLByteStream()
197 {
198 }
199
getByte()200 int RLByteStream::getByte()
201 {
202 uchar *current = m_current;
203 int val;
204
205 if( current >= m_end )
206 {
207 readBlock();
208 current = m_current;
209 }
210
211 val = *((uchar*)current);
212 m_current = current + 1;
213 return val;
214 }
215
216
getBytes(void * buffer,int count)217 int RLByteStream::getBytes( void* buffer, int count )
218 {
219 uchar* data = (uchar*)buffer;
220 int readed = 0;
221 assert( count >= 0 );
222
223 while( count > 0 )
224 {
225 int l;
226
227 for(;;)
228 {
229 l = (int)(m_end - m_current);
230 if( l > count ) l = count;
231 if( l > 0 ) break;
232 readBlock();
233 }
234 memcpy( data, m_current, l );
235 m_current += l;
236 data += l;
237 count -= l;
238 readed += l;
239 }
240 return readed;
241 }
242
243
244 //////////// RLByteStream & RMByteStream <Get[d]word>s ////////////////
245
~RMByteStream()246 RMByteStream::~RMByteStream()
247 {
248 }
249
250
getWord()251 int RLByteStream::getWord()
252 {
253 uchar *current = m_current;
254 int val;
255
256 if( current+1 < m_end )
257 {
258 val = current[0] + (current[1] << 8);
259 m_current = current + 2;
260 }
261 else
262 {
263 val = getByte();
264 val|= getByte() << 8;
265 }
266 return val;
267 }
268
269
getDWord()270 int RLByteStream::getDWord()
271 {
272 uchar *current = m_current;
273 int val;
274
275 if( current+3 < m_end )
276 {
277 val = current[0] + (current[1] << 8) +
278 (current[2] << 16) + (current[3] << 24);
279 m_current = current + 4;
280 }
281 else
282 {
283 val = getByte();
284 val |= getByte() << 8;
285 val |= getByte() << 16;
286 val |= getByte() << 24;
287 }
288 return val;
289 }
290
291
getWord()292 int RMByteStream::getWord()
293 {
294 uchar *current = m_current;
295 int val;
296
297 if( current+1 < m_end )
298 {
299 val = (current[0] << 8) + current[1];
300 m_current = current + 2;
301 }
302 else
303 {
304 val = getByte() << 8;
305 val|= getByte();
306 }
307 return val;
308 }
309
310
getDWord()311 int RMByteStream::getDWord()
312 {
313 uchar *current = m_current;
314 int val;
315
316 if( current+3 < m_end )
317 {
318 val = (current[0] << 24) + (current[1] << 16) +
319 (current[2] << 8) + current[3];
320 m_current = current + 4;
321 }
322 else
323 {
324 val = getByte() << 24;
325 val |= getByte() << 16;
326 val |= getByte() << 8;
327 val |= getByte();
328 }
329 return val;
330 }
331
332 /////////////////////////// WBaseStream /////////////////////////////////
333
334 // WBaseStream - base class for output streams
WBaseStream()335 WBaseStream::WBaseStream()
336 {
337 m_start = m_end = m_current = 0;
338 m_file = 0;
339 m_block_size = BS_DEF_BLOCK_SIZE;
340 m_is_opened = false;
341 m_buf = 0;
342 }
343
344
~WBaseStream()345 WBaseStream::~WBaseStream()
346 {
347 close();
348 release();
349 }
350
351
isOpened()352 bool WBaseStream::isOpened()
353 {
354 return m_is_opened;
355 }
356
357
allocate()358 void WBaseStream::allocate()
359 {
360 if( !m_start )
361 m_start = new uchar[m_block_size];
362
363 m_end = m_start + m_block_size;
364 m_current = m_start;
365 }
366
367
writeBlock()368 void WBaseStream::writeBlock()
369 {
370 int size = (int)(m_current - m_start);
371
372 assert( isOpened() );
373 if( size == 0 )
374 return;
375
376 if( m_buf )
377 {
378 size_t sz = m_buf->size();
379 m_buf->resize( sz + size );
380 memcpy( &(*m_buf)[sz], m_start, size );
381 }
382 else
383 {
384 fwrite( m_start, 1, size, m_file );
385 }
386 m_current = m_start;
387 m_block_pos += size;
388 }
389
390
open(const String & filename)391 bool WBaseStream::open( const String& filename )
392 {
393 close();
394 allocate();
395
396 m_file = fopen( filename.c_str(), "wb" );
397 if( m_file )
398 {
399 m_is_opened = true;
400 m_block_pos = 0;
401 m_current = m_start;
402 }
403 return m_file != 0;
404 }
405
open(std::vector<uchar> & buf)406 bool WBaseStream::open( std::vector<uchar>& buf )
407 {
408 close();
409 allocate();
410
411 m_buf = &buf;
412 m_is_opened = true;
413 m_block_pos = 0;
414 m_current = m_start;
415
416 return true;
417 }
418
close()419 void WBaseStream::close()
420 {
421 if( m_is_opened )
422 writeBlock();
423 if( m_file )
424 {
425 fclose( m_file );
426 m_file = 0;
427 }
428 m_buf = 0;
429 m_is_opened = false;
430 }
431
432
release()433 void WBaseStream::release()
434 {
435 if( m_start )
436 delete[] m_start;
437 m_start = m_end = m_current = 0;
438 }
439
440
getPos()441 int WBaseStream::getPos()
442 {
443 assert( isOpened() );
444 return m_block_pos + (int)(m_current - m_start);
445 }
446
447
448 ///////////////////////////// WLByteStream ///////////////////////////////////
449
~WLByteStream()450 WLByteStream::~WLByteStream()
451 {
452 }
453
putByte(int val)454 void WLByteStream::putByte( int val )
455 {
456 *m_current++ = (uchar)val;
457 if( m_current >= m_end )
458 writeBlock();
459 }
460
461
putBytes(const void * buffer,int count)462 void WLByteStream::putBytes( const void* buffer, int count )
463 {
464 uchar* data = (uchar*)buffer;
465
466 assert( data && m_current && count >= 0 );
467
468 while( count )
469 {
470 int l = (int)(m_end - m_current);
471
472 if( l > count )
473 l = count;
474
475 if( l > 0 )
476 {
477 memcpy( m_current, data, l );
478 m_current += l;
479 data += l;
480 count -= l;
481 }
482 if( m_current == m_end )
483 writeBlock();
484 }
485 }
486
487
putWord(int val)488 void WLByteStream::putWord( int val )
489 {
490 uchar *current = m_current;
491
492 if( current+1 < m_end )
493 {
494 current[0] = (uchar)val;
495 current[1] = (uchar)(val >> 8);
496 m_current = current + 2;
497 if( m_current == m_end )
498 writeBlock();
499 }
500 else
501 {
502 putByte(val);
503 putByte(val >> 8);
504 }
505 }
506
507
putDWord(int val)508 void WLByteStream::putDWord( int val )
509 {
510 uchar *current = m_current;
511
512 if( current+3 < m_end )
513 {
514 current[0] = (uchar)val;
515 current[1] = (uchar)(val >> 8);
516 current[2] = (uchar)(val >> 16);
517 current[3] = (uchar)(val >> 24);
518 m_current = current + 4;
519 if( m_current == m_end )
520 writeBlock();
521 }
522 else
523 {
524 putByte(val);
525 putByte(val >> 8);
526 putByte(val >> 16);
527 putByte(val >> 24);
528 }
529 }
530
531
532 ///////////////////////////// WMByteStream ///////////////////////////////////
533
~WMByteStream()534 WMByteStream::~WMByteStream()
535 {
536 }
537
538
putWord(int val)539 void WMByteStream::putWord( int val )
540 {
541 uchar *current = m_current;
542
543 if( current+1 < m_end )
544 {
545 current[0] = (uchar)(val >> 8);
546 current[1] = (uchar)val;
547 m_current = current + 2;
548 if( m_current == m_end )
549 writeBlock();
550 }
551 else
552 {
553 putByte(val >> 8);
554 putByte(val);
555 }
556 }
557
558
putDWord(int val)559 void WMByteStream::putDWord( int val )
560 {
561 uchar *current = m_current;
562
563 if( current+3 < m_end )
564 {
565 current[0] = (uchar)(val >> 24);
566 current[1] = (uchar)(val >> 16);
567 current[2] = (uchar)(val >> 8);
568 current[3] = (uchar)val;
569 m_current = current + 4;
570 if( m_current == m_end )
571 writeBlock();
572 }
573 else
574 {
575 putByte(val >> 24);
576 putByte(val >> 16);
577 putByte(val >> 8);
578 putByte(val);
579 }
580 }
581
582 }
583