Home | History | Annotate | Download | only in highgui
      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 
     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 
     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 
     79 bool  RBaseStream::IsOpened()
     80 {
     81     return m_is_opened;
     82 }
     83 
     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 
     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 
    107 RBaseStream::~RBaseStream()
    108 {
    109     Close();    // Close files
    110     Release();  // free  buffers
    111 }
    112 
    113 
    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 
    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 
    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 
    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 
    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 
    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 
    209 int  RBaseStream::GetPos()
    210 {
    211     assert( IsOpened() );
    212     return m_block_pos - m_block_size + (int)(m_current - m_start);
    213 }
    214 
    215 void  RBaseStream::Skip( int bytes )
    216 {
    217     assert( bytes >= 0 );
    218     m_current += bytes;
    219 }
    220 
    221 jmp_buf& RBaseStream::JmpBuf()
    222 {
    223     m_jmp_set = true;
    224     return m_jmp_buf;
    225 }
    226 
    227 /////////////////////////  RLByteStream ////////////////////////////
    228 
    229 RLByteStream::~RLByteStream()
    230 {
    231 }
    232 
    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 
    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 
    279 RMByteStream::~RMByteStream()
    280 {
    281 }
    282 
    283 
    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 
    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 
    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 
    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 
    368 RLBitStream::~RLBitStream()
    369 {
    370 }
    371 
    372 
    373 void  RLBitStream::ReadBlock()
    374 {
    375     RBaseStream::ReadBlock();
    376     if( bsIsBigEndian() )
    377         bsBSwapBlock( m_start, m_end );
    378 }
    379 
    380 
    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 
    390 int  RLBitStream::GetPos()
    391 {
    392     return RBaseStream::GetPos() + (m_bit_idx >> 3);
    393 }
    394 
    395 
    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 
    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 
    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 
    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 
    470 void  RLBitStream::Skip( int bytes )
    471 {
    472     Move( bytes*8 );
    473 }
    474 
    475 /////////////////////////  RMBitStream ////////////////////////////
    476 
    477 
    478 RMBitStream::~RMBitStream()
    479 {
    480 }
    481 
    482 
    483 void  RMBitStream::ReadBlock()
    484 {
    485     RBaseStream::ReadBlock();
    486     if( !bsIsBigEndian() )
    487         bsBSwapBlock( m_start, m_end );
    488 }
    489 
    490 
    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 
    500 int  RMBitStream::GetPos()
    501 {
    502     return RBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
    503 }
    504 
    505 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    722 WBaseStream::~WBaseStream()
    723 {
    724     Close();    // Close files
    725     Release();  // free  buffers
    726 }
    727 
    728 
    729 bool  WBaseStream::IsOpened()
    730 {
    731     return m_is_opened;
    732 }
    733 
    734 
    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 
    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 
    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 
    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 
    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 
    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 
    810 int  WBaseStream::GetPos()
    811 {
    812     assert( IsOpened() );
    813     return m_block_pos + (int)(m_current - m_start);
    814 }
    815 
    816 
    817 ///////////////////////////// WLByteStream ///////////////////////////////////
    818 
    819 WLByteStream::~WLByteStream()
    820 {
    821 }
    822 
    823 void WLByteStream::PutByte( int val )
    824 {
    825     *m_current++ = (uchar)val;
    826     if( m_current >= m_end )
    827         WriteBlock();
    828 }
    829 
    830 
    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 
    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 
    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 
    903 WMByteStream::~WMByteStream()
    904 {
    905 }
    906 
    907 
    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 
    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 
    955 WMBitStream::WMBitStream()
    956 {
    957     m_pad_val = 0;
    958     ResetBuffer();
    959 }
    960 
    961 
    962 WMBitStream::~WMBitStream()
    963 {
    964 }
    965 
    966 
    967 bool  WMBitStream::Open( const char* filename )
    968 {
    969     ResetBuffer();
    970     return WBaseStream::Open( filename );
    971 }
    972 
    973 
    974 void  WMBitStream::ResetBuffer()
    975 {
    976     m_val = 0;
    977     m_bit_idx = 32;
    978     m_current = m_start;
    979 }
    980 
    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 
    991 void  WMBitStream::Close()
    992 {
    993     if( m_is_opened )
    994     {
    995         Flush();
    996         WBaseStream::Close();
    997     }
    998 }
    999 
   1000 
   1001 void  WMBitStream::WriteBlock()
   1002 {
   1003     if( !bsIsBigEndian() )
   1004         bsBSwapBlock( m_start, m_current );
   1005     WBaseStream::WriteBlock();
   1006 }
   1007 
   1008 
   1009 int  WMBitStream::GetPos()
   1010 {
   1011     return WBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
   1012 }
   1013 
   1014 
   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 
   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 
   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