📄 coding.c
字号:
default: printf("decoder error!!! ");exit(1);
}
return(character);
}
BIT_FILE *OpenOutputBitFile(char *name )
{
BIT_FILE *bit_file;
bit_file = (BIT_FILE *) calloc( 1, sizeof( BIT_FILE ) );
if ( bit_file == NULL )
return( bit_file );
bit_file->file = fopen( name, "wb" );
bit_file->rack = 0;
bit_file->mask = 0x80;
bit_file->pacifier_counter = 0;
return( bit_file );
}
void CloseOutputBitFile(BIT_FILE *bit_file )
{
if ( bit_file->mask != 0x80 )
if ( putc( bit_file->rack, bit_file->file ) != bit_file->rack )
{
printf( "Fatal error in CloseBitFile!\n" );
exit(1);
}
fclose( bit_file->file );
free( (char *) bit_file );
}
void OutputBit(BIT_FILE *bit_file, int bit)
{
if ( bit )
bit_file->rack |= bit_file->mask;
bit_file->mask >>= 1;
if ( bit_file->mask == 0 ) {
if ( putc( bit_file->rack, bit_file->file ) != bit_file->rack )
{
printf( "Fatal error in OutputBit!\n" );
exit(1);
}
else
if ( ( bit_file->pacifier_counter++ & PACIFIER_COUNT ) == 0 )
;
/* putc( '.', stdout ); */
bit_file->rack = 0;
bit_file->mask = 0x80;
}
}
/*
* Everything from here down define the arithmetic coder section
* of the program.
*/
/*
* This routine must be called to initialize the encoding process.
* The high register is initialized to all 1s, and it is assumed that
* it has an infinite string of 1s to be shifted into the lower bit
* positions when needed.
*/
void initialize_arithmetic_encoder()
{
low = 0;
high = 0xffff;
underflow_bits = 0;
}
/*
* At the end of the encoding process, there are still significant
* bits left in the high and low registers. We output two bits,
* plus as many underflow bits as are necessary.
*/
void flush_arithmetic_encoder(BIT_FILE *stream )
{
OutputBit( stream, low & 0x4000 );
underflow_bits++;
while ( underflow_bits-- > 0 )
OutputBit( stream, ~low & 0x4000 );
/* OutputBits( stream, 0L, 16 ); */
}
/*
* This routine is called to encode a symbol. The symbol is passed
* in the SYMBOL structure as a low count, a high count, and a range,
* instead of the more conventional probability ranges. The encoding
* process takes two steps. First, the values of high and low are
* updated to take into account the range restriction created by the
* new symbol. Then, as many bits as possible are shifted out to
* the output stream. Finally, high and low are stable again and
* the routine returns. The return value is the output bits by this call.
*/
int encode_symbol(BIT_FILE *stream, SYMBOL *s)
{
long range;
int output_bits;
/*
* These three lines rescale high and low for the new symbol.
*/
range = (long) ( high-low ) + 1;
high = low + (unsigned short int)
(( range * s->high_count ) / s->scale - 1 );
low = low + (unsigned short int)
(( range * s->low_count ) / s->scale );
/*
* This loop turns out new bits until high and low are far enough
* apart to have stabilized.
*/
output_bits=0;
for ( ; ; ) {
/*
* If this test passes, it means that the MSDigits match, and can
* be sent to the output stream.
*/
if ( ( high & 0x8000 ) == ( low & 0x8000 ) ) {
OutputBit( stream, high & 0x8000 );
output_bits++;
while ( underflow_bits > 0 ) {
OutputBit( stream, ~high & 0x8000 );
output_bits++;
underflow_bits--;
}
}
/*
* If this test passes, the numbers are in danger of underflow, because
* the MSDigits don't match, and the 2nd digits are just one apart.
*/
else if ( ( low & 0x4000 ) && !( high & 0x4000 )) {
underflow_bits += 1;
low &= 0x3fff;
high |= 0x4000;
} else
return(output_bits);
low <<= 1;
high <<= 1;
high |= 1;
}
}
/******************************************************************
* following routines are related to decoding of arithmatic codec. *
*******************************************************************/
BIT_FILE *OpenInputBitFile(char *name)
{
BIT_FILE *bit_file;
bit_file = (BIT_FILE *) calloc( 1, sizeof( BIT_FILE ) );
if ( bit_file == NULL )
return( bit_file );
bit_file->file = fopen( name, "rb" );
bit_file->rack = 0;
bit_file->mask = 0x80;
bit_file->pacifier_counter = 0;
return( bit_file );
}
void CloseInputBitFile(BIT_FILE *bit_file)
{
fclose( bit_file->file );
free( (char *) bit_file );
}
int InputBit(BIT_FILE *bit_file)
{
int value;
if ( bit_file->mask == 0x80 ) {
bit_file->rack = getc( bit_file->file );
if ( bit_file->rack == EOF )
{
/* printf( "Fatal error in InputBit!\n" );
exit(1); */
}
if ( ( bit_file->pacifier_counter++ & PACIFIER_COUNT ) == 0 )
;
/* putc( '.', stdout ); */
}
value = bit_file->rack & bit_file->mask;
bit_file->mask >>= 1;
if ( bit_file->mask == 0 )
bit_file->mask = 0x80;
return( value ? 1 : 0 );
}
/*
* When decoding, this routine is called to figure out which symbol
* is presently waiting to be decoded. This routine expects to get
* the current model scale in the s->scale parameter, and it returns
* a count that corresponds to the present floating point code:
*
* code = count / s->scale
*/
short int get_current_count( SYMBOL *s )
{
long range;
short int count;
range = (long) ( high - low ) + 1;
count = (short int)
((((long) ( code - low ) + 1 ) * s->scale-1 ) / range );
return( count );
}
/*
* During decompression, we have to search through the table until
* we find the symbol that straddles the "count" parameter. When
* it is found, it is returned. The reason for also setting the
* high count and low count is so that symbol can be properly removed
* from the arithmetic coded input.
*/
int convert_symbol_to_int(short int count, SYMBOL *s, short int *totals, int num_codeword)
{
int c;
for ( c = num_codeword ; count < *(totals+c) ; c-- )
;
s->high_count = totals[ c + 1 ];
s->low_count = totals[ c ];
return( c );
}
/*
* This routine is called to initialize the state of the arithmetic
* decoder. This involves initializing the high and low registers
* to their conventional starting values, plus reading the first
* 16 bits from the input stream into the code value.
*/
int initialize_arithmetic_decoder( BIT_FILE *stream )
{
int i;
int input_bits;
code = 0;
input_bits=0;
for ( i = 0 ; i < 16 ; i++ ) {
code <<= 1;
code += InputBit( stream );
input_bits++;
}
low = 0;
high = 0xffff;
return(input_bits);
}
/*
* Just figuring out what the present symbol is doesn't remove
* it from the input bit stream. After the character has been
* decoded, this routine has to be called to remove it from the
* input stream.
*/
int remove_symbol_from_stream( BIT_FILE *stream,SYMBOL *s)
{
long range;
int input_bits;
/*
* First, the range is expanded to account for the symbol removal.
*/
range = (long)( high - low ) + 1;
high = low + (unsigned short int)
(( range * s->high_count ) / s->scale - 1 );
low = low + (unsigned short int)
(( range * s->low_count ) / s->scale );
/*
* Next, any possible bits are shipped out.
*/
input_bits=0;
for ( ; ; ) {
/*
* If the MSDigits match, the bits will be shifted out.
*/
if ( ( high & 0x8000 ) == ( low & 0x8000 ) ) {
}
/*
* Else, if underflow is threatening, shift out the 2nd MSDigit.
*/
else if ((low & 0x4000) == 0x4000 && (high & 0x4000) == 0 ) {
code ^= 0x4000;
low &= 0x3fff;
high |= 0x4000;
} else
/*
* Otherwise, nothing can be shifted out, so I return.
*/
return(input_bits);
low <<= 1;
high <<= 1;
high |= 1;
code <<= 1;
code += InputBit( stream );
input_bits++;
}
}
/*********************************************************************
arith_encode is the combination routine that will be easy to
use. The only thing you need to do is to get
the distribution of random variable X before calling this routine.
The discrete distribution array "esti_prob[]", the number of symbols
in the array "num_codeword" and current encoding value "cur_index"
must be transferred to this routine.
The return value is the output bits by this call
**********************************************************************/
int arith_encode(BIT_FILE *OutBitp, unsigned short int *esti_prob,
int num_codeword, int cur_index)
{
unsigned short int cur_start, cur_end, cur_counts, total_range;
SYMBOL cs;
int k;
cur_start=0;
cur_end=0;
total_range=0;
for(k=0; k < num_codeword; k++)
{
cur_counts=*(esti_prob+k);
cur_start=cur_end;
cur_end+=cur_counts;
if(k==cur_index)
{
cs.low_count=cur_start;
cs.high_count=cur_end;
}
total_range+=cur_counts;
}
cs.scale=total_range;
return(encode_symbol(OutBitp, &cs));
}
/*********************************************************************
arith_decode is the combination routine that will be easy to
use. The only thing you need to do is to get
the distribution of random variable X before calling this routine.
The following parameters should be transferred to this routine:
The discrete distribution array "esti_prob[]",
the number of symbols in the array "num_codeword",
a working variable "cs" and a working array
"totals[]" which is of the same size as "esti_prob[]".
The return value is the decoded value.
**********************************************************************/
int arith_decode(BIT_FILE *InBitp, SYMBOL *cs, unsigned short int *esti_prob,
int num_codeword, short int *totals)
{
unsigned short int temp_counts, total_range;
short int cur_count;
int recover_index, k;
total_range=0;
*totals=0;
for(k=0; k < num_codeword; k++)
{
temp_counts=*(esti_prob+k);
total_range+=temp_counts;
*(totals+k+1)=*(totals+k)+temp_counts;
}
cs->scale=total_range;
cur_count=get_current_count(cs);
recover_index=convert_symbol_to_int(cur_count, cs, totals, num_codeword);
remove_symbol_from_stream(InBitp, cs);
return(recover_index);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -