• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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