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 // Intel License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
21 //
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
25 //
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "_highgui.h"
43 #include "bitstrm.h"
44
45 #define BS_DEF_BLOCK_SIZE (1<<15)
46
47 const ulong bs_bit_mask[] = {
48 0,
49 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
50 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
51 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
52 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
53 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
54 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
55 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
56 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
57 };
58
bsBSwapBlock(uchar * start,uchar * end)59 void bsBSwapBlock( uchar *start, uchar *end )
60 {
61 ulong* data = (ulong*)start;
62 int i, size = (int)(end - start+3)/4;
63
64 for( i = 0; i < size; i++ )
65 {
66 ulong temp = data[i];
67 temp = BSWAP( temp );
68 data[i] = temp;
69 }
70 }
71
bsIsBigEndian(void)72 bool bsIsBigEndian( void )
73 {
74 return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
75 }
76
77 ///////////////////////// RBaseStream ////////////////////////////
78
IsOpened()79 bool RBaseStream::IsOpened()
80 {
81 return m_is_opened;
82 }
83
Allocate()84 void RBaseStream::Allocate()
85 {
86 if( !m_start )
87 {
88 m_start = new uchar[m_block_size + m_unGetsize];
89 m_start+= m_unGetsize;
90 }
91 m_end = m_start + m_block_size;
92 m_current = m_end;
93 }
94
95
RBaseStream()96 RBaseStream::RBaseStream()
97 {
98 m_start = m_end = m_current = 0;
99 m_file = 0;
100 m_block_size = BS_DEF_BLOCK_SIZE;
101 m_unGetsize = 4; // 32 bits
102 m_is_opened = false;
103 m_jmp_set = false;
104 }
105
106
~RBaseStream()107 RBaseStream::~RBaseStream()
108 {
109 Close(); // Close files
110 Release(); // free buffers
111 }
112
113
ReadBlock()114 void RBaseStream::ReadBlock()
115 {
116 size_t readed;
117 assert( m_file != 0 );
118
119 // copy unget buffer
120 if( m_start )
121 {
122 memcpy( m_start - m_unGetsize, m_end - m_unGetsize, m_unGetsize );
123 }
124
125 SetPos( GetPos() ); // normalize position
126
127 fseek( m_file, m_block_pos, SEEK_SET );
128 readed = fread( m_start, 1, m_block_size, m_file );
129 m_end = m_start + readed;
130 m_current -= m_block_size;
131 m_block_pos += m_block_size;
132
133 if( readed == 0 || m_current >= m_end )
134 {
135 if( m_jmp_set )
136 longjmp( m_jmp_buf, RBS_THROW_EOS );
137 }
138 }
139
140
Open(const char * filename)141 bool RBaseStream::Open( const char* filename )
142 {
143 Close();
144 Allocate();
145
146 m_file = fopen( filename, "rb" );
147
148 if( m_file )
149 {
150 m_is_opened = true;
151 SetPos(0);
152 }
153 return m_file != 0;
154 }
155
Close()156 void RBaseStream::Close()
157 {
158 if( m_file )
159 {
160 fclose( m_file );
161 m_file = 0;
162 }
163 m_is_opened = false;
164 }
165
166
Release()167 void RBaseStream::Release()
168 {
169 if( m_start )
170 {
171 delete[] (m_start - m_unGetsize);
172 }
173 m_start = m_end = m_current = 0;
174 }
175
176
SetBlockSize(int block_size,int unGetsize)177 void RBaseStream::SetBlockSize( int block_size, int unGetsize )
178 {
179 assert( unGetsize >= 0 && block_size > 0 &&
180 (block_size & (block_size-1)) == 0 );
181
182 if( m_start && block_size == m_block_size && unGetsize == m_unGetsize ) return;
183 Release();
184 m_block_size = block_size;
185 m_unGetsize = unGetsize;
186 Allocate();
187 }
188
189
SetPos(int pos)190 void RBaseStream::SetPos( int pos )
191 {
192 int offset = pos & (m_block_size - 1);
193 int block_pos = pos - offset;
194
195 assert( IsOpened() && pos >= 0 );
196
197 if( m_current < m_end && block_pos == m_block_pos - m_block_size )
198 {
199 m_current = m_start + offset;
200 }
201 else
202 {
203 m_block_pos = block_pos;
204 m_current = m_start + m_block_size + offset;
205 }
206 }
207
208
GetPos()209 int RBaseStream::GetPos()
210 {
211 assert( IsOpened() );
212 return m_block_pos - m_block_size + (int)(m_current - m_start);
213 }
214
Skip(int bytes)215 void RBaseStream::Skip( int bytes )
216 {
217 assert( bytes >= 0 );
218 m_current += bytes;
219 }
220
JmpBuf()221 jmp_buf& RBaseStream::JmpBuf()
222 {
223 m_jmp_set = true;
224 return m_jmp_buf;
225 }
226
227 ///////////////////////// RLByteStream ////////////////////////////
228
~RLByteStream()229 RLByteStream::~RLByteStream()
230 {
231 }
232
GetByte()233 int RLByteStream::GetByte()
234 {
235 uchar *current = m_current;
236 int val;
237
238 if( current >= m_end )
239 {
240 ReadBlock();
241 current = m_current;
242 }
243
244 val = *((uchar*)current);
245 m_current = current + 1;
246 return val;
247 }
248
249
GetBytes(void * buffer,int count,int * readed)250 void RLByteStream::GetBytes( void* buffer, int count, int* readed )
251 {
252 uchar* data = (uchar*)buffer;
253 assert( count >= 0 );
254
255 if( readed) *readed = 0;
256
257 while( count > 0 )
258 {
259 int l;
260
261 for(;;)
262 {
263 l = (int)(m_end - m_current);
264 if( l > count ) l = count;
265 if( l > 0 ) break;
266 ReadBlock();
267 }
268 memcpy( data, m_current, l );
269 m_current += l;
270 data += l;
271 count -= l;
272 if( readed ) *readed += l;
273 }
274 }
275
276
277 //////////// RLByteStream & RMByteStream <Get[d]word>s ////////////////
278
~RMByteStream()279 RMByteStream::~RMByteStream()
280 {
281 }
282
283
GetWord()284 int RLByteStream::GetWord()
285 {
286 uchar *current = m_current;
287 int val;
288
289 if( current+1 < m_end )
290 {
291 val = current[0] + (current[1] << 8);
292 m_current = current + 2;
293 }
294 else
295 {
296 val = GetByte();
297 val|= GetByte() << 8;
298 }
299 return val;
300 }
301
302
GetDWord()303 int RLByteStream::GetDWord()
304 {
305 uchar *current = m_current;
306 int val;
307
308 if( current+3 < m_end )
309 {
310 val = current[0] + (current[1] << 8) +
311 (current[2] << 16) + (current[3] << 24);
312 m_current = current + 4;
313 }
314 else
315 {
316 val = GetByte();
317 val |= GetByte() << 8;
318 val |= GetByte() << 16;
319 val |= GetByte() << 24;
320 }
321 return val;
322 }
323
324
GetWord()325 int RMByteStream::GetWord()
326 {
327 uchar *current = m_current;
328 int val;
329
330 if( current+1 < m_end )
331 {
332 val = (current[0] << 8) + current[1];
333 m_current = current + 2;
334 }
335 else
336 {
337 val = GetByte() << 8;
338 val|= GetByte();
339 }
340 return val;
341 }
342
343
GetDWord()344 int RMByteStream::GetDWord()
345 {
346 uchar *current = m_current;
347 int val;
348
349 if( current+3 < m_end )
350 {
351 val = (current[0] << 24) + (current[1] << 16) +
352 (current[2] << 8) + current[3];
353 m_current = current + 4;
354 }
355 else
356 {
357 val = GetByte() << 24;
358 val |= GetByte() << 16;
359 val |= GetByte() << 8;
360 val |= GetByte();
361 }
362 return val;
363 }
364
365
366 ///////////////////////// RLBitStream ////////////////////////////
367
~RLBitStream()368 RLBitStream::~RLBitStream()
369 {
370 }
371
372
ReadBlock()373 void RLBitStream::ReadBlock()
374 {
375 RBaseStream::ReadBlock();
376 if( bsIsBigEndian() )
377 bsBSwapBlock( m_start, m_end );
378 }
379
380
SetPos(int pos)381 void RLBitStream::SetPos( int pos )
382 {
383 RBaseStream::SetPos(pos);
384 int offset = (int)(m_current - m_end);
385 m_current = m_end + (offset & -4);
386 m_bit_idx = (offset&3)*8;
387 }
388
389
GetPos()390 int RLBitStream::GetPos()
391 {
392 return RBaseStream::GetPos() + (m_bit_idx >> 3);
393 }
394
395
Get(int bits)396 int RLBitStream::Get( int bits )
397 {
398 int bit_idx = m_bit_idx;
399 int new_bit_idx = bit_idx + bits;
400 int mask = new_bit_idx >= 32 ? -1 : 0;
401 ulong* current = (ulong*)m_current;
402
403 assert( (unsigned)bits < 32 );
404
405 if( (m_current = (uchar*)(current - mask)) >= m_end )
406 {
407 ReadBlock();
408 current = ((ulong*)m_current) + mask;
409 }
410 m_bit_idx = new_bit_idx & 31;
411 return ((current[0] >> bit_idx) |
412 ((current[1] <<-bit_idx) & mask)) & bs_bit_mask[bits];
413 }
414
Show(int bits)415 int RLBitStream::Show( int bits )
416 {
417 int bit_idx = m_bit_idx;
418 int new_bit_idx = bit_idx + bits;
419 int mask = new_bit_idx >= 32 ? -1 : 0;
420 ulong* current = (ulong*)m_current;
421
422 assert( (unsigned)bits < 32 );
423
424 if( (uchar*)(current - mask) >= m_end )
425 {
426 ReadBlock();
427 current = ((ulong*)m_current) + mask;
428 m_current = (uchar*)current;
429 }
430 return ((current[0] >> bit_idx) |
431 ((current[1] <<-bit_idx) & mask)) & bs_bit_mask[bits];
432 }
433
434
Move(int shift)435 void RLBitStream::Move( int shift )
436 {
437 int new_bit_idx = m_bit_idx + shift;
438 m_current += (new_bit_idx >> 5) << 2;
439 m_bit_idx = new_bit_idx & 31;
440 }
441
442
GetHuff(const short * table)443 int RLBitStream::GetHuff( const short* table )
444 {
445 int val;
446 int code_bits;
447
448 for(;;)
449 {
450 int table_bits = table[0];
451 val = table[Show(table_bits) + 2];
452 code_bits = val & 15;
453 val >>= 4;
454
455 if( code_bits != 0 ) break;
456 table += val*2;
457 Move( table_bits );
458 }
459
460 Move( code_bits );
461 if( val == RBS_HUFF_FORB )
462 {
463 if( m_jmp_set )
464 longjmp( m_jmp_buf, RBS_THROW_FORB );
465 }
466
467 return val;
468 }
469
Skip(int bytes)470 void RLBitStream::Skip( int bytes )
471 {
472 Move( bytes*8 );
473 }
474
475 ///////////////////////// RMBitStream ////////////////////////////
476
477
~RMBitStream()478 RMBitStream::~RMBitStream()
479 {
480 }
481
482
ReadBlock()483 void RMBitStream::ReadBlock()
484 {
485 RBaseStream::ReadBlock();
486 if( !bsIsBigEndian() )
487 bsBSwapBlock( m_start, m_end );
488 }
489
490
SetPos(int pos)491 void RMBitStream::SetPos( int pos )
492 {
493 RBaseStream::SetPos(pos);
494 int offset = (int)(m_current - m_end);
495 m_current = m_end + ((offset - 1) & -4);
496 m_bit_idx = (32 - (offset&3)*8) & 31;
497 }
498
499
GetPos()500 int RMBitStream::GetPos()
501 {
502 return RBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
503 }
504
505
Get(int bits)506 int RMBitStream::Get( int bits )
507 {
508 int bit_idx = m_bit_idx - bits;
509 int mask = bit_idx >> 31;
510 ulong* current = ((ulong*)m_current) - mask;
511
512 assert( (unsigned)bits < 32 );
513
514 if( (m_current = (uchar*)current) >= m_end )
515 {
516 ReadBlock();
517 current = (ulong*)m_current;
518 }
519 m_bit_idx = bit_idx &= 31;
520 return (((current[-1] << -bit_idx) & mask)|
521 (current[0] >> bit_idx)) & bs_bit_mask[bits];
522 }
523
524
Show(int bits)525 int RMBitStream::Show( int bits )
526 {
527 int bit_idx = m_bit_idx - bits;
528 int mask = bit_idx >> 31;
529 ulong* current = ((ulong*)m_current) - mask;
530
531 assert( (unsigned)bits < 32 );
532
533 if( ((uchar*)current) >= m_end )
534 {
535 m_current = (uchar*)current;
536 ReadBlock();
537 current = (ulong*)m_current;
538 m_current -= 4;
539 }
540 return (((current[-1]<<-bit_idx) & mask)|
541 (current[0] >> bit_idx)) & bs_bit_mask[bits];
542 }
543
544
GetHuff(const short * table)545 int RMBitStream::GetHuff( const short* table )
546 {
547 int val;
548 int code_bits;
549
550 for(;;)
551 {
552 int table_bits = table[0];
553 val = table[Show(table_bits) + 1];
554 code_bits = val & 15;
555 val >>= 4;
556
557 if( code_bits != 0 ) break;
558 table += val;
559 Move( table_bits );
560 }
561
562 Move( code_bits );
563 if( val == RBS_HUFF_FORB )
564 {
565 if( m_jmp_set )
566 longjmp( m_jmp_buf, RBS_THROW_FORB );
567 }
568
569 return val;
570 }
571
572
Move(int shift)573 void RMBitStream::Move( int shift )
574 {
575 int new_bit_idx = m_bit_idx - shift;
576 m_current -= (new_bit_idx >> 5)<<2;
577 m_bit_idx = new_bit_idx & 31;
578 }
579
580
Skip(int bytes)581 void RMBitStream::Skip( int bytes )
582 {
583 Move( bytes*8 );
584 }
585
586
587 static const int huff_val_shift = 20, huff_code_mask = (1 << huff_val_shift) - 1;
588
bsCreateDecodeHuffmanTable(const int * src,short * table,int max_size)589 bool bsCreateDecodeHuffmanTable( const int* src, short* table, int max_size )
590 {
591 const int forbidden_entry = (RBS_HUFF_FORB << 4)|1;
592 int first_bits = src[0];
593 struct
594 {
595 int bits;
596 int offset;
597 }
598 sub_tables[1 << 11];
599 int size = (1 << first_bits) + 1;
600 int i, k;
601
602 /* calc bit depths of sub tables */
603 memset( sub_tables, 0, ((size_t)1 << first_bits)*sizeof(sub_tables[0]) );
604 for( i = 1, k = 1; src[k] >= 0; i++ )
605 {
606 int code_count = src[k++];
607 int sb = i - first_bits;
608
609 if( sb <= 0 )
610 k += code_count;
611 else
612 for( code_count += k; k < code_count; k++ )
613 {
614 int code = src[k] & huff_code_mask;
615 sub_tables[code >> sb].bits = sb;
616 }
617 }
618
619 /* calc offsets of sub tables and whole size of table */
620 for( i = 0; i < (1 << first_bits); i++ )
621 {
622 int b = sub_tables[i].bits;
623 if( b > 0 )
624 {
625 b = 1 << b;
626 sub_tables[i].offset = size;
627 size += b + 1;
628 }
629 }
630
631 if( size > max_size )
632 {
633 assert(0);
634 return false;
635 }
636
637 /* fill first table and subtables with forbidden values */
638 for( i = 0; i < size; i++ )
639 {
640 table[i] = (short)forbidden_entry;
641 }
642
643 /* write header of first table */
644 table[0] = (short)first_bits;
645
646 /* fill first table and sub tables */
647 for( i = 1, k = 1; src[k] >= 0; i++ )
648 {
649 int code_count = src[k++];
650 for( code_count += k; k < code_count; k++ )
651 {
652 int table_bits= first_bits;
653 int code_bits = i;
654 int code = src[k] & huff_code_mask;
655 int val = src[k] >>huff_val_shift;
656 int j, offset = 0;
657
658 if( code_bits > table_bits )
659 {
660 int idx = code >> (code_bits -= table_bits);
661 code &= (1 << code_bits) - 1;
662 offset = sub_tables[idx].offset;
663 table_bits= sub_tables[idx].bits;
664 /* write header of subtable */
665 table[offset] = (short)table_bits;
666 /* write jump to subtable */
667 table[idx + 1]= (short)(offset << 4);
668 }
669
670 table_bits -= code_bits;
671 assert( table_bits >= 0 );
672 val = (val << 4) | code_bits;
673 offset += (code << table_bits) + 1;
674
675 for( j = 0; j < (1 << table_bits); j++ )
676 {
677 assert( table[offset + j] == forbidden_entry );
678 table[ offset + j ] = (short)val;
679 }
680 }
681 }
682 return true;
683 }
684
685
bsCreateSourceHuffmanTable(const uchar * src,int * dst,int max_bits,int first_bits)686 int* bsCreateSourceHuffmanTable( const uchar* src, int* dst,
687 int max_bits, int first_bits )
688 {
689 int i, val_idx, code = 0;
690 int* table = dst;
691 *dst++ = first_bits;
692 for( i = 1, val_idx = max_bits; i <= max_bits; i++ )
693 {
694 int code_count = src[i - 1];
695 dst[0] = code_count;
696 code <<= 1;
697 for( int k = 0; k < code_count; k++ )
698 {
699 dst[k + 1] = (src[val_idx + k] << huff_val_shift)|(code + k);
700 }
701 code += code_count;
702 dst += code_count + 1;
703 val_idx += code_count;
704 }
705 dst[0] = -1;
706 return table;
707 }
708
709
710 /////////////////////////// WBaseStream /////////////////////////////////
711
712 // WBaseStream - base class for output streams
WBaseStream()713 WBaseStream::WBaseStream()
714 {
715 m_start = m_end = m_current = 0;
716 m_file = 0;
717 m_block_size = BS_DEF_BLOCK_SIZE;
718 m_is_opened = false;
719 }
720
721
~WBaseStream()722 WBaseStream::~WBaseStream()
723 {
724 Close(); // Close files
725 Release(); // free buffers
726 }
727
728
IsOpened()729 bool WBaseStream::IsOpened()
730 {
731 return m_is_opened;
732 }
733
734
Allocate()735 void WBaseStream::Allocate()
736 {
737 if( !m_start )
738 m_start = new uchar[m_block_size];
739
740 m_end = m_start + m_block_size;
741 m_current = m_start;
742 }
743
744
WriteBlock()745 void WBaseStream::WriteBlock()
746 {
747 int size = (int)(m_current - m_start);
748 assert( m_file != 0 );
749
750 //fseek( m_file, m_block_pos, SEEK_SET );
751 fwrite( m_start, 1, size, m_file );
752 m_current = m_start;
753
754 /*if( written < size ) throw RBS_THROW_EOS;*/
755
756 m_block_pos += size;
757 }
758
759
Open(const char * filename)760 bool WBaseStream::Open( const char* filename )
761 {
762 Close();
763 Allocate();
764
765 m_file = fopen( filename, "wb" );
766
767 if( m_file )
768 {
769 m_is_opened = true;
770 m_block_pos = 0;
771 m_current = m_start;
772 }
773 return m_file != 0;
774 }
775
776
Close()777 void WBaseStream::Close()
778 {
779 if( m_file )
780 {
781 WriteBlock();
782 fclose( m_file );
783 m_file = 0;
784 }
785 m_is_opened = false;
786 }
787
788
Release()789 void WBaseStream::Release()
790 {
791 if( m_start )
792 {
793 delete[] m_start;
794 }
795 m_start = m_end = m_current = 0;
796 }
797
798
SetBlockSize(int block_size)799 void WBaseStream::SetBlockSize( int block_size )
800 {
801 assert( block_size > 0 && (block_size & (block_size-1)) == 0 );
802
803 if( m_start && block_size == m_block_size ) return;
804 Release();
805 m_block_size = block_size;
806 Allocate();
807 }
808
809
GetPos()810 int WBaseStream::GetPos()
811 {
812 assert( IsOpened() );
813 return m_block_pos + (int)(m_current - m_start);
814 }
815
816
817 ///////////////////////////// WLByteStream ///////////////////////////////////
818
~WLByteStream()819 WLByteStream::~WLByteStream()
820 {
821 }
822
PutByte(int val)823 void WLByteStream::PutByte( int val )
824 {
825 *m_current++ = (uchar)val;
826 if( m_current >= m_end )
827 WriteBlock();
828 }
829
830
PutBytes(const void * buffer,int count)831 void WLByteStream::PutBytes( const void* buffer, int count )
832 {
833 uchar* data = (uchar*)buffer;
834
835 assert( data && m_current && count >= 0 );
836
837 while( count )
838 {
839 int l = (int)(m_end - m_current);
840
841 if( l > count )
842 l = count;
843
844 if( l > 0 )
845 {
846 memcpy( m_current, data, l );
847 m_current += l;
848 data += l;
849 count -= l;
850 }
851 if( m_current == m_end )
852 WriteBlock();
853 }
854 }
855
856
PutWord(int val)857 void WLByteStream::PutWord( int val )
858 {
859 uchar *current = m_current;
860
861 if( current+1 < m_end )
862 {
863 current[0] = (uchar)val;
864 current[1] = (uchar)(val >> 8);
865 m_current = current + 2;
866 if( m_current == m_end )
867 WriteBlock();
868 }
869 else
870 {
871 PutByte(val);
872 PutByte(val >> 8);
873 }
874 }
875
876
PutDWord(int val)877 void WLByteStream::PutDWord( int val )
878 {
879 uchar *current = m_current;
880
881 if( current+3 < m_end )
882 {
883 current[0] = (uchar)val;
884 current[1] = (uchar)(val >> 8);
885 current[2] = (uchar)(val >> 16);
886 current[3] = (uchar)(val >> 24);
887 m_current = current + 4;
888 if( m_current == m_end )
889 WriteBlock();
890 }
891 else
892 {
893 PutByte(val);
894 PutByte(val >> 8);
895 PutByte(val >> 16);
896 PutByte(val >> 24);
897 }
898 }
899
900
901 ///////////////////////////// WMByteStream ///////////////////////////////////
902
~WMByteStream()903 WMByteStream::~WMByteStream()
904 {
905 }
906
907
PutWord(int val)908 void WMByteStream::PutWord( int val )
909 {
910 uchar *current = m_current;
911
912 if( current+1 < m_end )
913 {
914 current[0] = (uchar)(val >> 8);
915 current[1] = (uchar)val;
916 m_current = current + 2;
917 if( m_current == m_end )
918 WriteBlock();
919 }
920 else
921 {
922 PutByte(val >> 8);
923 PutByte(val);
924 }
925 }
926
927
PutDWord(int val)928 void WMByteStream::PutDWord( int val )
929 {
930 uchar *current = m_current;
931
932 if( current+3 < m_end )
933 {
934 current[0] = (uchar)(val >> 24);
935 current[1] = (uchar)(val >> 16);
936 current[2] = (uchar)(val >> 8);
937 current[3] = (uchar)val;
938 m_current = current + 4;
939 if( m_current == m_end )
940 WriteBlock();
941 }
942 else
943 {
944 PutByte(val >> 24);
945 PutByte(val >> 16);
946 PutByte(val >> 8);
947 PutByte(val);
948 }
949 }
950
951
952
953 ///////////////////////////// WMBitStream ///////////////////////////////////
954
WMBitStream()955 WMBitStream::WMBitStream()
956 {
957 m_pad_val = 0;
958 ResetBuffer();
959 }
960
961
~WMBitStream()962 WMBitStream::~WMBitStream()
963 {
964 }
965
966
Open(const char * filename)967 bool WMBitStream::Open( const char* filename )
968 {
969 ResetBuffer();
970 return WBaseStream::Open( filename );
971 }
972
973
ResetBuffer()974 void WMBitStream::ResetBuffer()
975 {
976 m_val = 0;
977 m_bit_idx = 32;
978 m_current = m_start;
979 }
980
Flush()981 void WMBitStream::Flush()
982 {
983 if( m_bit_idx < 32 )
984 {
985 Put( m_pad_val, m_bit_idx & 7 );
986 *((ulong*&)m_current)++ = m_val;
987 }
988 }
989
990
Close()991 void WMBitStream::Close()
992 {
993 if( m_is_opened )
994 {
995 Flush();
996 WBaseStream::Close();
997 }
998 }
999
1000
WriteBlock()1001 void WMBitStream::WriteBlock()
1002 {
1003 if( !bsIsBigEndian() )
1004 bsBSwapBlock( m_start, m_current );
1005 WBaseStream::WriteBlock();
1006 }
1007
1008
GetPos()1009 int WMBitStream::GetPos()
1010 {
1011 return WBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
1012 }
1013
1014
Put(int val,int bits)1015 void WMBitStream::Put( int val, int bits )
1016 {
1017 int bit_idx = m_bit_idx - bits;
1018 ulong curval = m_val;
1019
1020 assert( 0 <= bits && bits < 32 );
1021
1022 val &= bs_bit_mask[bits];
1023
1024 if( bit_idx >= 0 )
1025 {
1026 curval |= val << bit_idx;
1027 }
1028 else
1029 {
1030 *((ulong*&)m_current)++ = curval | ((unsigned)val >> -bit_idx);
1031 if( m_current >= m_end )
1032 {
1033 WriteBlock();
1034 }
1035 bit_idx += 32;
1036 curval = val << bit_idx;
1037 }
1038
1039 m_val = curval;
1040 m_bit_idx = bit_idx;
1041 }
1042
1043
PutHuff(int val,const ulong * table)1044 void WMBitStream::PutHuff( int val, const ulong* table )
1045 {
1046 int min_val = (int)table[0];
1047 val -= min_val;
1048
1049 assert( (unsigned)val < table[1] );
1050
1051 ulong code = table[val + 2];
1052 assert( code != 0 );
1053
1054 Put( code >> 8, code & 255 );
1055 }
1056
1057
bsCreateEncodeHuffmanTable(const int * src,ulong * table,int max_size)1058 bool bsCreateEncodeHuffmanTable( const int* src, ulong* table, int max_size )
1059 {
1060 int i, k;
1061 int min_val = INT_MAX, max_val = INT_MIN;
1062 int size;
1063
1064 /* calc min and max values in the table */
1065 for( i = 1, k = 1; src[k] >= 0; i++ )
1066 {
1067 int code_count = src[k++];
1068
1069 for( code_count += k; k < code_count; k++ )
1070 {
1071 int val = src[k] >> huff_val_shift;
1072 if( val < min_val )
1073 min_val = val;
1074 if( val > max_val )
1075 max_val = val;
1076 }
1077 }
1078
1079 size = max_val - min_val + 3;
1080
1081 if( size > max_size )
1082 {
1083 assert(0);
1084 return false;
1085 }
1086
1087 memset( table, 0, size*sizeof(table[0]));
1088
1089 table[0] = min_val;
1090 table[1] = size - 2;
1091
1092 for( i = 1, k = 1; src[k] >= 0; i++ )
1093 {
1094 int code_count = src[k++];
1095
1096 for( code_count += k; k < code_count; k++ )
1097 {
1098 int val = src[k] >> huff_val_shift;
1099 int code = src[k] & huff_code_mask;
1100
1101 table[val - min_val + 2] = (code << 8) | i;
1102 }
1103 }
1104 return true;
1105 }
1106
1107