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