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 47const 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 59void 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 72bool bsIsBigEndian( void ) 73{ 74 return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0; 75} 76 77///////////////////////// RBaseStream //////////////////////////// 78 79bool RBaseStream::IsOpened() 80{ 81 return m_is_opened; 82} 83 84void 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 96RBaseStream::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 107RBaseStream::~RBaseStream() 108{ 109 Close(); // Close files 110 Release(); // free buffers 111} 112 113 114void 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 141bool 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 156void 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 167void 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 177void 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 190void 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 209int RBaseStream::GetPos() 210{ 211 assert( IsOpened() ); 212 return m_block_pos - m_block_size + (int)(m_current - m_start); 213} 214 215void RBaseStream::Skip( int bytes ) 216{ 217 assert( bytes >= 0 ); 218 m_current += bytes; 219} 220 221jmp_buf& RBaseStream::JmpBuf() 222{ 223 m_jmp_set = true; 224 return m_jmp_buf; 225} 226 227///////////////////////// RLByteStream //////////////////////////// 228 229RLByteStream::~RLByteStream() 230{ 231} 232 233int 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 250void 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 279RMByteStream::~RMByteStream() 280{ 281} 282 283 284int 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 303int 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 325int 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 344int 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 368RLBitStream::~RLBitStream() 369{ 370} 371 372 373void RLBitStream::ReadBlock() 374{ 375 RBaseStream::ReadBlock(); 376 if( bsIsBigEndian() ) 377 bsBSwapBlock( m_start, m_end ); 378} 379 380 381void 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 390int RLBitStream::GetPos() 391{ 392 return RBaseStream::GetPos() + (m_bit_idx >> 3); 393} 394 395 396int 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 415int 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 435void 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 443int 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 470void RLBitStream::Skip( int bytes ) 471{ 472 Move( bytes*8 ); 473} 474 475///////////////////////// RMBitStream //////////////////////////// 476 477 478RMBitStream::~RMBitStream() 479{ 480} 481 482 483void RMBitStream::ReadBlock() 484{ 485 RBaseStream::ReadBlock(); 486 if( !bsIsBigEndian() ) 487 bsBSwapBlock( m_start, m_end ); 488} 489 490 491void 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 500int RMBitStream::GetPos() 501{ 502 return RBaseStream::GetPos() + ((32 - m_bit_idx) >> 3); 503} 504 505 506int 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 525int 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 545int 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 573void 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 581void RMBitStream::Skip( int bytes ) 582{ 583 Move( bytes*8 ); 584} 585 586 587static const int huff_val_shift = 20, huff_code_mask = (1 << huff_val_shift) - 1; 588 589bool 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 686int* 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 713WBaseStream::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 722WBaseStream::~WBaseStream() 723{ 724 Close(); // Close files 725 Release(); // free buffers 726} 727 728 729bool WBaseStream::IsOpened() 730{ 731 return m_is_opened; 732} 733 734 735void 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 745void 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 760bool 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 777void 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 789void WBaseStream::Release() 790{ 791 if( m_start ) 792 { 793 delete[] m_start; 794 } 795 m_start = m_end = m_current = 0; 796} 797 798 799void 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 810int WBaseStream::GetPos() 811{ 812 assert( IsOpened() ); 813 return m_block_pos + (int)(m_current - m_start); 814} 815 816 817///////////////////////////// WLByteStream /////////////////////////////////// 818 819WLByteStream::~WLByteStream() 820{ 821} 822 823void WLByteStream::PutByte( int val ) 824{ 825 *m_current++ = (uchar)val; 826 if( m_current >= m_end ) 827 WriteBlock(); 828} 829 830 831void 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 857void 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 877void 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 903WMByteStream::~WMByteStream() 904{ 905} 906 907 908void 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 928void 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 955WMBitStream::WMBitStream() 956{ 957 m_pad_val = 0; 958 ResetBuffer(); 959} 960 961 962WMBitStream::~WMBitStream() 963{ 964} 965 966 967bool WMBitStream::Open( const char* filename ) 968{ 969 ResetBuffer(); 970 return WBaseStream::Open( filename ); 971} 972 973 974void WMBitStream::ResetBuffer() 975{ 976 m_val = 0; 977 m_bit_idx = 32; 978 m_current = m_start; 979} 980 981void 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 991void WMBitStream::Close() 992{ 993 if( m_is_opened ) 994 { 995 Flush(); 996 WBaseStream::Close(); 997 } 998} 999 1000 1001void WMBitStream::WriteBlock() 1002{ 1003 if( !bsIsBigEndian() ) 1004 bsBSwapBlock( m_start, m_current ); 1005 WBaseStream::WriteBlock(); 1006} 1007 1008 1009int WMBitStream::GetPos() 1010{ 1011 return WBaseStream::GetPos() + ((32 - m_bit_idx) >> 3); 1012} 1013 1014 1015void 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 1044void 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 1058bool 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