?? bitstrm.cpp
字號:
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <assert.h>
#include <string.h>
#include <limits.h>
#include "../include/bitstrm.h"
#define BS_DEF_BLOCK_SIZE (1<<15)
const ulong bs_bit_mask[] = {
0,
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
};
void bsBSwapBlock( uchar *start, uchar *end )
{
ulong* data = (ulong*)start;
int i, size = (end - start+3)/4;
for( i = 0; i < size; i++ )
{
ulong temp = data[i];
temp = BSWAP( temp );
data[i] = temp;
}
}
///////////////////////// RBaseStream ////////////////////////////
bool RBaseStream::IsOpened()
{
return m_is_opened;
}
void RBaseStream::Allocate()
{
if( !m_start )
{
m_start = new uchar[m_block_size + m_unGetsize];
m_start+= m_unGetsize;
}
m_end = m_start + m_block_size;
m_current = m_end;
}
RBaseStream::RBaseStream()
{
m_start = m_end = m_current = 0;
m_file = 0;
m_block_size = BS_DEF_BLOCK_SIZE;
m_unGetsize = 4; // 32 bits
m_is_opened = false;
}
RBaseStream::~RBaseStream()
{
Close(); // Close files
Release(); // free buffers
}
void RBaseStream::ReadBlock()
{
int readed;
assert( m_file != 0 );
// copy unget buffer
if( m_start )
{
memcpy( m_start - m_unGetsize, m_end - m_unGetsize, m_unGetsize );
}
SetPos( GetPos() ); // normalize position
fseek( m_file, m_block_pos, SEEK_SET );
readed = fread( m_start, 1, m_block_size, m_file );
m_end = m_start + readed;
m_current -= m_block_size;
m_block_pos += m_block_size;
if( readed == 0 || m_current >= m_end ) throw RBS_THROW_EOS;
}
bool RBaseStream::Open( const char* filename )
{
Close();
Allocate();
m_file = fopen( filename, "rb" );
if( m_file )
{
m_is_opened = true;
SetPos(0);
}
return m_file != 0;
}
void RBaseStream::Close()
{
if( m_file )
{
fclose( m_file );
m_file = 0;
}
m_is_opened = false;
}
void RBaseStream::Release()
{
if( m_start )
{
delete (m_start - m_unGetsize);
}
m_start = m_end = m_current = 0;
}
void RBaseStream::SetBlockSize( int block_size, int unGetsize )
{
assert( unGetsize >= 0 && block_size > 0 &&
(block_size & (block_size-1)) == 0 );
if( m_start && block_size == m_block_size && unGetsize == m_unGetsize ) return;
Release();
m_block_size = block_size;
m_unGetsize = unGetsize;
Allocate();
}
void RBaseStream::SetPos( int pos )
{
int offset = pos & (m_block_size - 1);
int block_pos = pos - offset;
assert( IsOpened() && pos >= 0 );
if( m_current < m_end && block_pos == m_block_pos - m_block_size )
{
m_current = m_start + offset;
}
else
{
m_block_pos = block_pos;
m_current = m_start + m_block_size + offset;
}
}
int RBaseStream::GetPos()
{
assert( IsOpened() );
return m_block_pos - m_block_size + (m_current - m_start);
}
void RBaseStream::Skip( int bytes )
{
assert( bytes >= 0 );
m_current += bytes;
}
///////////////////////// RLByteStream ////////////////////////////
RLByteStream::~RLByteStream()
{
}
int RLByteStream::GetByte()
{
uchar *current = m_current;
int val;
if( current >= m_end )
{
ReadBlock();
current = m_current;
}
val = *((uchar*)current);
m_current = current + 1;
return val;
}
void RLByteStream::GetBytes( void* buffer, int count, int* readed )
{
uchar* data = (uchar*)buffer;
assert( count >= 0 );
if( readed) *readed = 0;
while( count > 0 )
{
int l;
for(;;)
{
l = m_end - m_current;
if( l > count ) l = count;
if( l > 0 ) break;
ReadBlock();
}
memcpy( data, m_current, l );
m_current += l;
data += l;
count -= l;
if( readed ) *readed += l;
}
}
//////////// RLByteStream & RMByteStream <Get[d]word>s ////////////////
RMByteStream::~RMByteStream()
{
}
int RLByteStream::GetWord()
{
uchar *current = m_current;
int val;
if( current+1 < m_end )
{
val = current[0] + (current[1] << 8);
m_current = current + 2;
}
else
{
val = GetByte();
val|= GetByte() << 8;
}
return val;
}
int RLByteStream::GetDWord()
{
uchar *current = m_current;
int val;
if( current+3 < m_end )
{
val = current[0] + (current[1] << 8) +
(current[2] << 16) + (current[3] << 24);
m_current = current + 4;
}
else
{
val = GetByte();
val |= GetByte() << 8;
val |= GetByte() << 16;
val |= GetByte() << 24;
}
return val;
}
int RMByteStream::GetWord()
{
uchar *current = m_current;
int val;
if( current+1 < m_end )
{
val = (current[0] << 8) + current[1];
m_current = current + 2;
}
else
{
val = GetByte() << 8;
val|= GetByte();
}
return val;
}
int RMByteStream::GetDWord()
{
uchar *current = m_current;
int val;
if( current+3 < m_end )
{
val = (current[0] << 24) + (current[1] << 16) +
(current[2] << 8) + current[3];
m_current = current + 4;
}
else
{
val = GetByte() << 24;
val |= GetByte() << 16;
val |= GetByte() << 8;
val |= GetByte();
}
return val;
}
///////////////////////// RLBitStream ////////////////////////////
RLBitStream::~RLBitStream()
{
}
void RLBitStream::ReadBlock()
{
RBaseStream::ReadBlock();
#ifdef BIG_ENDIAN
bsBSwapBlock( m_start, m_end );
#endif
}
void RLBitStream::SetPos( int pos )
{
RBaseStream::SetPos(pos);
int offset = m_current - m_end;
m_current = m_end + (offset & -4);
m_bit_idx = (offset&3)*8;
}
int RLBitStream::GetPos()
{
return RBaseStream::GetPos() + (m_bit_idx >> 3);
}
int RLBitStream::Get( int bits )
{
int bit_idx = m_bit_idx;
int new_bit_idx = bit_idx + bits;
int mask = new_bit_idx >= 32 ? -1 : 0;
ulong* current = (ulong*)m_current;
assert( (unsigned)bits < 32 );
if( (m_current = (uchar*)(current - mask)) >= m_end )
{
ReadBlock();
current = ((ulong*)m_current) + mask;
}
m_bit_idx = new_bit_idx & 31;
return ((current[0] >> bit_idx) |
((current[1] <<-bit_idx) & mask)) & bs_bit_mask[bits];
}
int RLBitStream::Show( int bits )
{
int bit_idx = m_bit_idx;
int new_bit_idx = bit_idx + bits;
int mask = new_bit_idx >= 32 ? -1 : 0;
ulong* current = (ulong*)m_current;
assert( (unsigned)bits < 32 );
if( (uchar*)(current - mask) >= m_end )
{
ReadBlock();
current = ((ulong*)m_current) + mask;
m_current = (uchar*)current;
}
return ((current[0] >> bit_idx) |
((current[1] <<-bit_idx) & mask)) & bs_bit_mask[bits];
}
void RLBitStream::Move( int shift )
{
int new_bit_idx = m_bit_idx + shift;
m_current += (new_bit_idx >> 5) << 2;
m_bit_idx = new_bit_idx & 31;
}
int RLBitStream::GetHuff( const short* table )
{
int val;
int code_bits;
for(;;)
{
int table_bits = table[0];
val = table[Show(table_bits) + 2];
code_bits = val & 15;
val >>= 4;
if( code_bits != 0 ) break;
table += val*2;
Move( table_bits );
}
Move( code_bits );
if( val == RBS_HUFF_FORB ) throw RBS_THROW_FORB;
return val;
}
void RLBitStream::Skip( int bytes )
{
Move( bytes*8 );
}
///////////////////////// RMBitStream ////////////////////////////
RMBitStream::~RMBitStream()
{
}
void RMBitStream::ReadBlock()
{
RBaseStream::ReadBlock();
#ifdef LITTLE_ENDIAN
bsBSwapBlock( m_start, m_end );
#endif
}
void RMBitStream::SetPos( int pos )
{
RBaseStream::SetPos(pos);
int offset = m_current - m_end;
m_current = m_end + ((offset - 1) & -4);
m_bit_idx = (32 - (offset&3)*8) & 31;
}
int RMBitStream::GetPos()
{
return RBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
}
int RMBitStream::Get( int bits )
{
int bit_idx = m_bit_idx - bits;
int mask = bit_idx >> 31;
ulong* current = ((ulong*)m_current) - mask;
assert( (unsigned)bits < 32 );
if( (m_current = (uchar*)current) >= m_end )
{
ReadBlock();
current = (ulong*)m_current;
}
m_bit_idx = bit_idx &= 31;
return (((current[-1] << -bit_idx) & mask)|
(current[0] >> bit_idx)) & bs_bit_mask[bits];
}
int RMBitStream::Show( int bits )
{
int bit_idx = m_bit_idx - bits;
int mask = bit_idx >> 31;
ulong* current = ((ulong*)m_current) - mask;
assert( (unsigned)bits < 32 );
if( ((uchar*)current) >= m_end )
{
m_current = (uchar*)current;
ReadBlock();
current = (ulong*)m_current;
m_current -= 4;
}
return (((current[-1]<<-bit_idx) & mask)|
(current[0] >> bit_idx)) & bs_bit_mask[bits];
}
int RMBitStream::GetHuff( const short* table )
{
int val;
int code_bits;
for(;;)
{
int table_bits = table[0];
val = table[Show(table_bits) + 1];
code_bits = val & 15;
val >>= 4;
if( code_bits != 0 ) break;
table += val;
Move( table_bits );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -