/// <summary> /// BitStringLookup function. /// </summary> /// <param name="bstr"> /// BITSTRING to look up. /// </param> /// <param name="n"></param> /// <returns></returns> public UInt32 BitStringLookup(ref BITSTRING bstr, UInt32 n) { if (n == 0) { return(0); } else { return(bstr.mask >> (int)(32 - n)); } }
/// <summary> /// Initializes BitString /// </summary> /// <param name="bstr"> /// BITSTRING to initialize. /// </param> /// <param name="source"> /// Source array /// </param> /// <param name="index"> /// Index value /// </param> public void BitStringInit(ref BITSTRING bstr, byte[] source, UInt32 index) { bstr.mask = BitConverter.ToUInt16(source, (int)index); bstr.mask = bstr.mask << 16; index = index + 2; bstr.mask = bstr.mask + BitConverter.ToUInt16(source, (int)index); index = index + 2; bstr.bits = 32; bstr.source = source; bstr.index = index; }
/// <summary> /// BitStringSkip function /// </summary> /// <param name="bstr"></param> /// <param name="n"></param> public void BitStringSkip(ref BITSTRING bstr, UInt32 n) { bstr.mask = bstr.mask << (int)n; bstr.bits = bstr.bits - (Int32)n; if (bstr.bits < 16) { bstr.mask = bstr.mask + (UInt32)(BitConverter.ToUInt16(bstr.source, (int)bstr.index) << (int)(16 - bstr.bits)); bstr.index = bstr.index + 2; bstr.bits = bstr.bits + 16; } }
/// <summary> /// PrefixCodeTreeDecodeSymbol method decodes the symbols. /// </summary> /// <param name="bstr"></param> /// <param name="root"> /// Used to traverse the tree. /// </param> /// <returns></returns> public UInt32 PrefixCodeTreeDecodeSymbol(ref BITSTRING bstr, PrefixCodeNode root) { UInt32 bit; PrefixCodeNode node = root; do { bit = BitStringLookup(ref bstr, 1); BitStringSkip(ref bstr, 1); node = node.Child[bit]; } while (node.leaf == false); return(node.symbol); }
/// <summary> /// This method is called to decompress the compressed data /// </summary> /// <param name="input"> /// Compressed Byte Array /// </param> /// <param name="outputSize"> /// Uncompressed Output Size /// </param> /// <param name="outputBuffer"> /// Decompressed output buffer. /// </param> public void Decompress(byte[] input, UInt32 outputSize, out byte[] outputBuffer) { byte[] output = new byte[outputSize]; UInt32 i = 0; UInt32 stopIndex = i + outputSize; UInt32 symbol; UInt32 length; Int32 offset; PrefixCodeNode root = new PrefixCodeNode(); PrefixCodeNode[] prefixCodeTreeNodes = new PrefixCodeNode[1024]; for (int count = 0; count < 1024; count++) { prefixCodeTreeNodes[count] = new PrefixCodeNode(); } BITSTRING bstr = new BITSTRING(); root = PrefixCodeTreeRebuild(input, ref prefixCodeTreeNodes); BitStringInit(ref bstr, input, 256); while (i < stopIndex) { symbol = PrefixCodeTreeDecodeSymbol(ref bstr, root); if (symbol < 256) { output[i] = (byte)symbol; i++; } else { symbol = symbol - 256; length = symbol & 15; symbol = symbol >> 4; offset = (int)((1 << (int)symbol) + BitStringLookup(ref bstr, symbol)); offset = (-1) * offset; if (length == 15) { length = bstr.source[bstr.index] + (UInt32)15; bstr.index = bstr.index + 1; if (length == 270) { length = BitConverter.ToUInt16(bstr.source, (int)bstr.index); bstr.index = bstr.index + 2; } } BitStringSkip(ref bstr, symbol); length = length + 3; do { output[i] = output[i + offset]; i++; length--; } while (length != 0); } } outputBuffer = output; }