/// <summary> /// Builds Tree. /// </summary> /// <param name="input"> /// input byte array to build tree. /// </param> /// <param name="treeNodes"></param> /// <returns></returns> public PrefixCodeNode PrefixCodeTreeRebuild(byte[] input, ref PrefixCodeNode[] treeNodes) { PrefixCodeNode root = new PrefixCodeNode(); PrefixCodeSymbol[] symbolInfo = new PrefixCodeSymbol[512]; UInt32 i; UInt32 j; UInt32 mask; UInt32 bits; for (i = 0; i < 1024; i++) { treeNodes[i].symbol = 0; treeNodes[i].leaf = false; treeNodes[i].Child[0] = null; treeNodes[i].Child[1] = null; } for (i = 0; i < 256; i++) { symbolInfo[2 * i].symbol = (UInt16)(2 * i); symbolInfo[2 * i].length = (UInt16)(input[i] & 15); symbolInfo[2 * i + 1].symbol = (UInt16)(2 * i + 1); symbolInfo[2 * i + 1].length = (UInt16)(input[i] >> 4); } SortSymbols(ref symbolInfo); i = 0; while ((i < 512) && (symbolInfo[i].length == 0)) { i++; } mask = 0; bits = 1; root = treeNodes[0]; root.leaf = false; j = 1; for (; i < 512; i++) { treeNodes[j].symbol = symbolInfo[i].symbol; treeNodes[j].leaf = true; mask = mask << (int)(symbolInfo[i].length - bits); bits = symbolInfo[i].length; j = PrefixCodeTreeAddLeaf(ref treeNodes, j, mask, bits); mask++; } return(root); }
/// <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> /// Adds leaf to the tree. /// </summary> /// <param name="treeNodes"> /// PrefixCodeNode node /// </param> /// <param name="leafIndex"> /// Index of leaf. /// </param> /// <param name="mask"></param> /// <param name="bits"></param> /// <returns></returns> public UInt32 PrefixCodeTreeAddLeaf(ref PrefixCodeNode[] treeNodes, UInt32 leafIndex, UInt32 mask, UInt32 bits) { PrefixCodeNode node = treeNodes[0]; UInt32 i = leafIndex + 1; UInt32 childIndex; while (bits > 1) { bits--; childIndex = (mask >> (int)bits) & 1; if (node.Child[childIndex] == null) { node.Child[childIndex] = treeNodes[i]; treeNodes[i].leaf = false; i++; } node = node.Child[childIndex]; } node.Child[mask & 1] = treeNodes[leafIndex]; return(i); }
/// <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; }