home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
h
/
hpack78s.zip
/
lza
/
pack.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-22
|
4KB
|
159 lines
/****************************************************************************
* *
* HPACK Multi-System Archiver *
* =========================== *
* *
* HPACK Arithmetic Encoder *
* PACKF.C Updated 06/11/91 *
* *
* This program is protected by copyright and as such any use or copying of *
* this code for your own purposes directly or indirectly is highly uncool *
* and if you do so there will be....trubble. *
* And remember: We know where your kids go to school. *
* *
* Copyright 1990, 1991 Peter C.Gutmann. All rights reserved *
* *
****************************************************************************/
#ifdef __MAC__
#include "defs.h"
#include "fastio.h"
#else
#include "defs.h"
#include "io/fastio.h"
#endif /* __MAC__ */
/* Count of no.bytes output */
extern long outByteCount;
/****************************************************************************
* *
* Bit Output Routines *
* *
****************************************************************************/
/* The bit buffer */
static BYTE outBuffer; /* Bit buffer for output */
static int outBitsToGo; /* Number of bits free in buffer */
/* Output a bit */
static void outBit( const int bit )
{
/* Put bit in buffer */
outBuffer <<= 1;
outBuffer |= bit;
/* Output buffer if it is now full */
if( !--outBitsToGo )
{
fputByte( outBuffer );
outByteCount++;
outBitsToGo = 8;
}
}
/****************************************************************************
* *
* Arithmetic Coding Routines *
* *
****************************************************************************/
/* The current state of the encoding */
WORD low, high; /* Ends of the current code region */
int bitsToFollow; /* No.opposing bits to output after the next bit */
/* Initialise variables used in the arithmetic coding */
void startEncode( void )
{
low = 0;
high = 0xFFFF; /* Full code range */
bitsToFollow = 0; /* No bits to follow next */
/* Set the bit buffer to empty */
outBitsToGo = 8;
}
/* Encode a symbol */
void encode( const int cumFreq0, \
const int cumFreqLower, const int cumFreqUpper )
{
BYTE highBit;
LONG range = ( LONG ) ( high - low ) + 1L; /* Size of curr.code region */
/* Narrow the code region to that allotted to this symbol */
high = low + ( WORD ) ( ( range * cumFreqLower ) / cumFreq0 - 1 );
low += ( WORD ) ( ( range * cumFreqUpper ) / cumFreq0 );
while( TRUE )
{
if( ( high & 0x8000 ) == ( low & 0x8000 ) )
{
highBit = ( high & 0x8000 ) ? 1 : 0;
outBuffer <<= 1;
outBuffer |= highBit;
if( !--outBitsToGo )
{
fputByte( outBuffer );
outByteCount++;
outBitsToGo = 8;
}
while( bitsToFollow )
{
outBuffer <<= 1;
outBuffer |= !highBit;
if( !--outBitsToGo )
{
fputByte( outBuffer );
outByteCount++;
outBitsToGo = 8;
}
bitsToFollow--;
}
}
else
if( ( low & 0x4000 ) && !( high & 0x4000 ) )
{
/* Output an opposite bit later if in middle half */
bitsToFollow++;
low &= 0x3FFF;
high |= 0x4000;
}
else
break;
/* Now scale up code range */
low <<= 1; /* low = 2 * low */
high <<= 1; /* 2 * high + 1 */
high++;
}
}
/* Finish encoding the stream by outputting two bits that select the quarter
that the current code range contains */
void endEncode( void )
{
BYTE bit = ( low & 0x4000 ) ? 0 : 1, padding;
static BYTE padBits[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
bitsToFollow++;
outBit( bit );
while( bitsToFollow-- )
outBit( !bit );
/* Flush out the last bits, padding with ones or zeroes depending on
the value of the last bit */
if( outBitsToGo < 8 )
{
padding = ( outBuffer & 1 ) ? padBits[ outBitsToGo ] : 0;
fputByte( ( outBuffer << outBitsToGo ) | padding );
outByteCount++;
}
}