Update to 2.0.0 tree from current Fremantle build
[opencv] / src / highgui / bitstrm.cpp
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 "_highgui.h"
44 #include "bitstrm.h"
45
46 namespace cv
47 {
48
49 const int BS_DEF_BLOCK_SIZE = 1<<15;
50
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
58 bool  RBaseStream::isOpened()
59
60     return m_is_opened;
61 }
62
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
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
85 RBaseStream::~RBaseStream()
86 {
87     close();    // Close files
88     release();  // free  buffers
89 }
90
91
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
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
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
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
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
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
182 int  RBaseStream::getPos()
183 {
184     assert( isOpened() );
185     return m_block_pos + (int)(m_current - m_start);
186 }
187
188 void  RBaseStream::skip( int bytes )
189 {
190     assert( bytes >= 0 );
191     m_current += bytes;
192 }
193
194 /////////////////////////  RLByteStream ////////////////////////////
195
196 RLByteStream::~RLByteStream()
197 {
198 }
199
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
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
246 RMByteStream::~RMByteStream()
247 {
248 }
249
250
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
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
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
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
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
345 WBaseStream::~WBaseStream()
346 {
347     close();
348     release();
349 }
350
351
352 bool  WBaseStream::isOpened()
353
354     return m_is_opened;
355 }
356
357
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
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
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
406 bool  WBaseStream::open( 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
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
433 void  WBaseStream::release()
434 {
435     if( m_start )
436         delete[] m_start;
437     m_start = m_end = m_current = 0;
438 }
439
440
441 int  WBaseStream::getPos()
442 {
443     assert( isOpened() );
444     return m_block_pos + (int)(m_current - m_start);
445 }
446
447
448 ///////////////////////////// WLByteStream /////////////////////////////////// 
449
450 WLByteStream::~WLByteStream()
451 {
452 }
453
454 void WLByteStream::putByte( int val )
455 {
456     *m_current++ = (uchar)val;
457     if( m_current >= m_end )
458         writeBlock();
459 }
460
461
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
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
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
534 WMByteStream::~WMByteStream()
535 {
536 }
537
538
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
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 }