Huffman Decompress

Huffman coding is a data compression algorithm. It is based on the idea that frequently-appearing letters should have shorter bit representations and less common letters should have longer representations.

For Huffman Compress algorithm click here.



									private const int MAX_TREE_NODES = 511;

public class BitStream
{
	public byte[] BytePointer;
	public uint BitPosition;
	public uint Index;
}

public struct Symbol
{
	public int Sym;
	public uint Count;
	public uint Code;
	public uint Bits;
}

public class DecodeNode
{
	public DecodeNode ChildA;
	public DecodeNode ChildB;
	public int Symbol;
}

private static void initBitstream(ref BitStream stream, byte[] buffer)
{
	stream.BytePointer = buffer;
	stream.BitPosition = 0;
}

private static uint readBit(ref BitStream stream)
{
	byte[] buffer = stream.BytePointer;
	uint bit = stream.BitPosition;

	uint x = (uint)(Convert.ToBoolean((buffer[stream.Index] & (1 << (int)(7 - bit)))) ? 1 : 0);
	bit = (bit + 1) & 7;

	if (!Convert.ToBoolean(bit))
	{
		++stream.Index;
	}

	stream.BitPosition = bit;

	return x;
}

private static uint read8Bits(ref BitStream stream)
{
	byte[] buffer = stream.BytePointer;
	uint bit = stream.BitPosition;
	uint x = (uint)((buffer[stream.Index] << (int)bit) | (buffer[stream.Index + 1] >> (int)(8 - bit)));
	++stream.Index;

	return x;
}

private static DecodeNode recoverTree(DecodeNode[] nodes, ref BitStream stream, ref uint nodenum)
{
	DecodeNode thisNode;

	thisNode = nodes[nodenum];
	nodenum = nodenum + 1;
	thisNode.Symbol = -1;
	thisNode.ChildA = null;
	thisNode.ChildB = null;

	if (Convert.ToBoolean(readBit(ref stream)))
	{
		thisNode.Symbol = (int)read8Bits(ref stream);
		return thisNode;
	}

	thisNode.ChildA = recoverTree(nodes, ref stream, ref nodenum);
	thisNode.ChildB = recoverTree(nodes, ref stream, ref nodenum);

	return thisNode;
}

public static void Decompress(byte[] input, byte[] output, uint inputSize, uint outputSize)
{
	DecodeNode[] nodes = new DecodeNode[MAX_TREE_NODES];

	for (int counter = 0; counter < nodes.Length; ++counter)
	{
		nodes[counter] = new DecodeNode();
	}

	DecodeNode root, node;
	BitStream stream = new BitStream();
	uint i, nodeCount;
	byte[] buffer;

	if (inputSize < 1)
		return;

	initBitstream(ref stream, input);
	nodeCount = 0;
	root = recoverTree(nodes, ref stream, ref nodeCount);
	buffer = output;

	for (i = 0; i < outputSize; ++i)
	{
		node = root;

		while (node.Symbol < 0)
		{
			if (Convert.ToBoolean(readBit(ref stream)))
				node = node.ChildB;
			else
				node = node.ChildA;
		}

		buffer[i] = (byte)node.Symbol;
	}
}
								


Example

									byte[] decompressedData = new byte[originalDataSize];

Decompress(compressedData, decompressedData, (uint)compressedDataSize, originalDataSize);