static void GetHistogram(ref byte[] pBufIn, int lenIn, out HistogramNode[] pHN, out int lenOut) { int i; HistogramNode[] pHFull = new HistogramNode[256]; for (i = 0; i < 256; i++) { pHFull[i] = new HistogramNode(Convert.ToByte(i)); } for (i = 0; i < lenIn; i++) { pHFull[pBufIn[i]].Inc(); } lenOut = pHFull.Count(x => x.Frequency > 0); pHN = new HistogramNode[lenOut]; for (i = 0; i < lenOut; i++) { pHN[i] = new HistogramNode(); } int index = -1; for (i = 0; i < 256; i++) { if (pHFull[i].Frequency > 0) { index++; pHN[index].Value = pHFull[i].Value; pHN[index].Frequency = pHFull[i].Frequency; } } }
static void DecodeArray(ref byte[] pBufIn, out byte[] pBufOut) { int lenIn = pBufIn.Length; int lenOut = 0; int offset = 1; // 0 === check for compressed or uncompressed === if (pBufIn[0] == 0) { lenOut = BitConverter.ToInt32(pBufIn, offset); offset += sizeof(int); pBufOut = new byte[lenOut]; Array.Copy(pBufIn, offset, pBufOut, 0, lenOut); return; } // ============================================== // 1 === Get Huffman table === int i; int nHaffmanTableSize = BitConverter.ToInt32(pBufIn, offset); offset += sizeof(int); if (nHaffmanTableSize == 1) { int uncompressed = BitConverter.ToInt32(pBufIn, offset); offset += sizeof(int); byte Value = pBufIn[offset]; lenOut = uncompressed; pBufOut = new byte[lenOut]; for (i = 0; i < lenOut; i++) { pBufOut[i] = Value; } return; } // === extract histogram === HistogramNode[] pHN = new HistogramNode[nHaffmanTableSize]; for (i = 0; i < nHaffmanTableSize; i++) { pHN[i] = new HistogramNode(); offset = pHN[i].FromArray(ref pBufIn, offset); } // ========================= // 2 === create zero level of tree === List <CHNode> arCHZeroLevel = new List <CHNode>(); int lHOut = nHaffmanTableSize; for (i = 0; i < lHOut; i++) { arCHZeroLevel.Add(new CHNode(pHN[i].Value, pHN[i].Frequency)); } // =================================== // 3 === create tree === List <CHNode> arCHTree = new List <CHNode>(arCHZeroLevel); int lCur = lHOut; int nTreeSize; CHNode pRoot = null; while (lCur > 1) { int index1 = 0; int index2 = 0; CHNode emptyNode = null; CHNode pHaffman = null; int min = 0xFFFFFFF; nTreeSize = arCHTree.Count; for (i = 0; i < nTreeSize; i++) { pHaffman = arCHTree[i]; if (pHaffman.Mark) { continue; } if (pHaffman.Weight < min) { index1 = i; min = pHaffman.Weight; } } min = 0xFFFFFFF; for (i = 0; i < nTreeSize; i++) { pHaffman = arCHTree[i]; if (pHaffman.Mark) { continue; } if (i == index1) { continue; } if (pHaffman.Weight < min) { index2 = i; min = pHaffman.Weight; } } CHNode p1 = arCHTree[index1]; CHNode p2 = arCHTree[index2]; CHNode pNewNode = new CHNode(); pNewNode.Weight = p1.Weight + p2.Weight; pNewNode.SetLeft(ref p1); pNewNode.SetRight(ref p2); pNewNode.SetRoot(ref emptyNode); pRoot = pNewNode; arCHTree.Add(pNewNode); p1.SetRoot(ref pNewNode); p1.SetLeftType(); p1.Mark = true; p2.SetRoot(ref pNewNode); p2.SetRightType(); p2.Mark = true; lCur--; } // === end: tree from encode ==== // 2 == get output size === lenOut = BitConverter.ToInt32(pBufIn, offset); offset += sizeof(int); pBufOut = new byte[lenOut]; Array.Clear(pBufOut, 0, lenOut); // ======================== // 3 === decoding === int offsetOut = 0; int nBits = 8; byte Digit; CHNode pHaffman1; while (offsetOut < lenOut) { pHaffman1 = pRoot; while (true) { Digit = Convert.ToByte(pBufIn[offset] & (1 << (nBits - 1))); Digit = Convert.ToByte(Digit >> (nBits - 1)); nBits--; // === fast search huffman table index === pHaffman1 = (Digit == 0) ? pHaffman1.GetLeft() : pHaffman1.GetRight(); // ======================================= if (nBits == 0) { offset++; nBits = 8; } if (pHaffman1.GetRight() == null) { break; } } if (pHaffman1.GetRight() == null) { pBufOut[offsetOut++] = pHaffman1.Value; } else { break; } } }