/*

I am sorry for the late reply to your queries , this is only for educational purpose please

*/
#include stdlib.h
#include memory.h
#include string.h
#includefcthl.h

#ifdef unix //works with unix applications too
#define __cdecl
#else
#include io.h
#endif
// i used this code for java implementation but did not used in my assignment
// link bit-level I/O

void arc_put1 (unsigned bit);
unsigned arc_get1 ();

// This code is adapted from Professor Vitter's
// article, Design and Analysis of Dynamic Huffman Codes,
// which appeared in JACM October 1987

// A design trade-off has been made to simplify the
// code: a node's block is determined dynamically,
// and the implicit tree structure is maintained,
// e.g. explicit node numbers are also implicit.

// Dynamic huffman table weight ranking
// is maintained per Professor Vitter's
// invariant (*) for algorithm FGK:

// leaves preceed internal nodes of the
// same weight in a non-decreasing ranking
// of weights using implicit node numbers:

// 1) leaves slide over internal nodes, internal nodes
// swap over groups of leaves, leaves are swapped
// into group leader position, but two internal
// nodes never change positions relative
// to one another.

// 2) weights are incremented by 2:
// leaves always have even weight values;
// internal nodes always have odd values.

// 3) even node numbers are always right children;
// odd numbers are left children in the tree.

// node 2 * HuffSize - 1 is always the tree root;
// node HuffEsc is the escape node;

// the tree is initialized by creating an
// escape node as the root.

// each new leaf symbol is paired with a new escape
// node into the previous escape node in the tree,
// until the last symbol which takes over the
// tree position of the escape node, and
// HuffEsc is left at zero.

// overall table size: 2 * HuffSize

// huff_init(alphabet_size, potential symbols used)
// huff_encode(next_symbol)
// next_symbol = huff_decode()

// huff_scale(by_bits) -- scale weights and rebalance tree

typedef struct {
unsigned up, // next node up the tree
down, // pair of down nodes
symbol, // node symbol value
weight; // node weight
} HTable;

typedef struct {
unsigned esc, // the current tree height
root, // the root of the tree
size, // the alphabet size
*map; // mapping for symbols to nodes
HTable table[1]; // the coding table starts here
} HCoder;

// initialize an adaptive coder
// for alphabet size, and count
// of nodes to be used

HCoder *huff_init (unsigned size, unsigned root)
{
HCoder *huff;

// default: all alphabet symbols are used

if( !root || root > size )
root = size;

// create the initial escape node
// at the tree root

if( root <<= 1 ) root--; huff = malloc (root * sizeof(HTable) + sizeof(HCoder)); memset (huff->table + 1, 0, root * sizeof(HTable));
memset (huff, 0, sizeof(HCoder));

if( huff->size = size )
huff->map = calloc (size, sizeof(unsigned));

huff->esc = huff->root = root;
return huff;
}

// split escape node to incorporate new symbol

unsigned huff_split (HCoder *huff, unsigned symbol)
{
unsigned pair, node;

// is the tree already full???

if( pair = huff->esc )
huff->esc--;
else
return 0;

// if this is the last symbol, it moves into
// the escape node's old position, and
// huff->esc is set to zero.

// otherwise, the escape node is promoted to
// parent a new escape node and the new symbol.

if( node = huff->esc ) {
huff->table[pair].down = node;
huff->table[pair].weight = 1;
huff->table[node].up = pair;
huff->esc--;
} else
pair = 0, node = 1;

// initialize the new symbol node

huff->table[node].symbol = symbol;
huff->table[node].weight = 0;
huff->table[node].down = 0;
huff->map[symbol] = node;

// initialize a new escape node.

huff->table[huff->esc].weight = 0;
huff->table[huff->esc].down = 0;
huff->table[huff->esc].up = pair;
return node;
}

// swap leaf to group leader position
// return symbol's new node

unsigned huff_leader (HCoder *huff, unsigned node)
{
unsigned weight = huff->table[node].weight;
unsigned leader = node, prev, symbol;

while( weight == huff->table[leader + 1].weight )
leader++;

if( leader == node )
return node;

// swap the leaf nodes

symbol = huff->table[node].symbol;
prev = huff->table[leader].symbol;

huff->table[leader].symbol = symbol;
huff->table[node].symbol = prev;
huff->map[symbol] = leader;
huff->map[prev] = node;
return leader;
}

// slide internal node up over all leaves of equal weight;
// or exchange leaf with next smaller weight internal node

// return node's new position

unsigned huff_slide (HCoder *huff, unsigned node)
{
unsigned next = node;
HTable swap[1];

*swap = huff->table[next++];

// if we're sliding an internal node, find the
// highest possible leaf to exchange with

if( swap->weight & 1 )
while( swap->weight > huff->table[next + 1].weight )
next++;

// swap the two nodes

huff->table[node] = huff->table[next];
huff->table[next] = *swap;

huff->table[next].up = huff->table[node].up;
huff->table[node].up = swap->up;

// repair the symbol map and tree structure

if( swap->weight & 1 ) {
huff->table[swap->down].up = next;
huff->table[swap->down - 1].up = next;
huff->map[huff->table[node].symbol] = node;
} else {
huff->table[huff->table[node].down - 1].up = node;
huff->table[huff->table[node].down].up = node;
huff->map[swap->symbol] = next;
}

return next;
}

// increment symbol weight and re balance the tree.

void huff_increment (HCoder *huff, unsigned node)
{
unsigned up;

// obviate swapping a parent with its child:
// increment the leaf and proceed
// directly to its parent.

// otherwise, promote leaf to group leader position in the tree

if( huff->table[node].up == node + 1 )
huff->table[node].weight += 2, node++;
else
node = huff_leader (huff, node);

// increase the weight of each node and slide
// over any smaller weights ahead of it
// until reaching the root

// internal nodes work upwards from
// their initial positions; while
// symbol nodes slide over first,
// then work up from their final
// positions.

while( huff->table[node].weight += 2, up = huff->table[node].up ) {
while( huff->table[node].weight > huff->table[node + 1].weight )
node = huff_slide (huff, node);

if( huff->table[node].weight & 1 )
node = up;
else
node = huff->table[node].up;
}
}

// scale all weights and rebalance the tree

// zero weight nodes are removed from the tree
// by sliding them out the left of the rank list

void huff_scale (HCoder *huff, unsigned bits)
{
unsigned node = huff->esc, weight, prev;

// work up the tree from the escape node
// scaling weights by the value of bits

while( ++node <= huff->root ) {
// recompute the weight of internal nodes;
// slide down and out any unused ones

if( huff->table[node].weight & 1 ) {
if( weight = huff->table[huff->table[node].down].weight & ~1 )
weight += huff->table[huff->table[node].down - 1].weight | 1;

// remove zero weight leaves by incrementing HuffEsc
// and removing them from the symbol map. take care

} else if( !(weight = huff->table[node].weight >> bits & ~1) )
if( huff->map[huff->table[node].symbol] = 0, huff->esc++ )
huff->esc++;

// slide the scaled node back down over any
// previous nodes with larger weights

huff->table[node].weight = weight;
prev = node;

while( weight <>table[--prev].weight )
huff_slide (huff, prev);
}

// prepare a new escape node

huff->table[huff->esc].down = 0;
}

// send the bits for an escaped symbol

void huff_sendid (HCoder *huff, unsigned symbol)
{
unsigned empty = 0, max;

// count the number of empty symbols
// before the symbol in the table

while( symbol-- )
if( !huff->map[symbol] )
empty++;

// send LSB of this count first, using
// as many bits as are required for
// the maximum possible count

if( max = huff->size - (huff->root - huff->esc) / 2 - 1 )
do arc_put1 (empty & 1), empty >>= 1;
while( max >>= 1 );
}

// encode the next symbol

void huff_encode (HCoder *huff, unsigned symbol)
{
unsigned emit = 1, bit;
unsigned up, idx, node;

if( symbol <>size )
node = huff->map[symbol];
else
return;

// for a new symbol, direct the receiver to the escape node
// but refuse input if table is already full.

if( !(idx = node) )
if( !(idx = huff->esc) )
return;

// accumulate the code bits by
// working up the tree from
// the node to the root

while( up = huff->table[idx].up )
emit <<= 1, emit |= idx & 1, idx = up; // send the code, root selector bit first while( bit = emit & 1, emit >>= 1 )
arc_put1 (bit);

// send identification and incorporate
// new symbols into the tree

if( !node )
huff_sendid(huff, symbol), node = huff_split(huff, symbol);

// adjust and re-balance the tree

huff_increment (huff, node);
}

// read the identification bits
// for an escaped symbol

unsigned huff_readid (HCoder *huff)
{
unsigned empty = 0, bit = 1, max, symbol;

// receive the symbol, LSB first, reading
// only the number of bits necessary to
// transmit the maximum possible symbol value

if( max = huff->size - (huff->root - huff->esc) / 2 - 1 )
do empty |= arc_get1 () ? bit : 0, bit <<= 1; while( max >>= 1 );

// the count is of unmapped symbols
// in the table before the new one

for( symbol = 0; symbol <>size; symbol++ )
if( !huff->map[symbol] )
if( !empty-- )
return symbol;

// oops! our count is too big, either due
// to a bit error, or a short node count
// given to huff_init.

return 0;
}

// decode the next symbol

unsigned huff_decode (HCoder *huff)
{
unsigned node = huff->root;
unsigned symbol, down;

// work down the tree from the root
// until reaching either a leaf
// or the escape node. A one
// bit means go left, a zero
// means go right.

while( down = huff->table[node].down )
if( arc_get1 () )
node = down - 1; // the left child preceeds the right child
else
node = down;

// sent to the escape node???
// refuse to add to a full tree

if( node == huff->esc )
if( huff->esc )
symbol = huff_readid (huff), node = huff_split (huff, symbol);
else
return 0;
else
symbol = huff->table[node].symbol;

// increment weights and rebalance
// the coding tree

huff_increment (huff, node);
return symbol;
}

#ifdef HUFFSTANDALONE

#include

FILE *In = stdin, *Out = stdout;
unsigned char ArcBit = 0;
int ArcChar = 0;

int main (int argc, char **argv)
{
int mode, size, symbol;
unsigned mask = ~0;
HCoder *huff;

if( argc > 1 )
mode = argv[1][0], argv[1]++;
else {
printf ("Usage: %s [cdtls]nn infile outfile\nnn -- alphabet size\ninfile -- source file\noutfile -- output file", argv[0]);
return 1;
}

if( argv[1][0] == 's' )
argv[1]++, mask = 8191;

if( argc > 3 )
if( !(Out = fopen (argv[3], "w")) )
return 1;

#ifndef unix
_setmode (_fileno (Out), _O_BINARY);
#endif

// literal text

if( mode == 'l' ) {
if( !(size = atoi (argv[1])) )
size = 256;

huff = huff_init (256, size);
putc (size >> 8, Out);
putc (size, Out);

size = strlen (argv[2]);
putc (size >> 16, Out);
putc (size >> 8, Out);
putc (size, Out);

while( symbol = *argv[2]++ )
huff_encode(huff, symbol);

while( ArcBit ) // flush last few bits
arc_put1 (0);

return 0;
}

// alphabet fill

if( mode == 't' ) {
if( !(size = atoi (argv[1])) )
size = 256;

huff = huff_init (256, size);
putc (size >> 8, Out);
putc (size, Out);

putc (size >> 16, Out);
putc (size >> 8, Out);
putc (size, Out);

for( symbol = 0; symbol <>
huff_encode(huff, symbol);

while( ArcBit ) // flush last few bits
arc_put1 (0);

return 0;
}

if( argc > 2 )
if( !(In = fopen (argv[2], "r")) )
return 1;

#ifndef unix
_setmode (_fileno (In), _O_BINARY);
#endif

// decompression

if( mode == 'd' ) {
size = getc(In) <<>
size |= getc(In);

huff = huff_init (256, size);

size = getc(In) <<>
size |= getc(In) <<>
size |= getc(In);

while( size )
if( symbol = huff_decode(huff), putc (symbol, Out), size-- & mask )
continue;
else
huff_scale(huff, 1);

return 0;
}

// compression

if( !(size = atoi (argv[1])) )
size = 256;

huff = huff_init (256, size);
putc (size >> 8, Out);
putc (size, Out);

fseek(In, 0, 2);
size = ftell(In);
fseek (In, 0, 0);

putc (size >> 16, Out);
putc (size >> 8, Out);
putc (size, Out);

while( size )
if( symbol = getc(In), huff_encode(huff, symbol), size-- & mask )
continue;
else
huff_scale(huff, 1);

while( ArcBit ) // flush last few bits
arc_put1 (0);

return 0;
}

void arc_put1 (unsigned bit)
{
ArcChar <<= 1; if( bit ) ArcChar |= 1; if( ++ArcBit <>
return;

putc (ArcChar, Out);
ArcChar = ArcBit = 0;
}

unsigned arc_get1 ()
{
if( !ArcBit )
ArcChar = getc (In), ArcBit = 8;

return ArcChar >> --ArcBit & 1;
}
#endif

If u didnt understand something please drop a line in a comments

Categories:

Leave a Reply

Thank you for taking time to comment.......