static DecompressorHuffmanTree() { try { byte[] lengths; int index; lengths = new byte[288]; index = 0; while (index < 144) { lengths[index++] = 8; } while (index < 256) { lengths[index++] = 9; } while (index < 280) { lengths[index++] = 7; } while (index < 288) { lengths[index++] = 8; } m_LengthTree = new DecompressorHuffmanTree(lengths); lengths = new byte[32]; index = 0; while (index < 32) { lengths[index++] = 5; } m_DistanceTree = new DecompressorHuffmanTree(lengths); } catch (Exception ex) { throw new Exception("DecompressorHuffmanTree: fixed trees generation failed", ex); } }
protected void DecodeDynHeader(out DecompressorHuffmanTree lengthTree, out DecompressorHuffmanTree distanceTree) { byte[] arrDecoderCodeLengths; byte[] arrResultingCodeLengths; byte bLastSymbol = 0; int iLengthsCount = ReadBits(5); int iDistancesCount = ReadBits(5); int iCodeLengthsCount = ReadBits(4); if (iLengthsCount < 0 || iDistancesCount < 0 || iCodeLengthsCount < 0) throw new FormatException("Wrong dynamic huffman codes."); iLengthsCount += 257; iDistancesCount += 1; int iResultingCodeLengthsCount = iLengthsCount + iDistancesCount; arrResultingCodeLengths = new byte[iResultingCodeLengthsCount]; arrDecoderCodeLengths = new byte[19]; iCodeLengthsCount += 4; int iCurrentCode = 0; while (iCurrentCode < iCodeLengthsCount) { int len = ReadBits(3); if (len < 0) throw new FormatException("Wrong dynamic huffman codes."); arrDecoderCodeLengths[BitUtils.DEF_HUFFMAN_DYNTREE_CODELENGTHS_ORDER[iCurrentCode++]] = (byte)len; } DecompressorHuffmanTree treeInternalDecoder = new DecompressorHuffmanTree(arrDecoderCodeLengths); iCurrentCode = 0; for (; ; ) { int symbol; bool bNeedBreak = false; while (((symbol = treeInternalDecoder.UnpackSymbol(this)) & ~15) == 0) { arrResultingCodeLengths[iCurrentCode++] = bLastSymbol = (byte)symbol; if (iCurrentCode == iResultingCodeLengthsCount) { bNeedBreak = true; break; } } if (bNeedBreak) break; if (symbol < 0) throw new FormatException("Wrong dynamic huffman codes."); if (symbol >= 17) { bLastSymbol = 0; } else if (iCurrentCode == 0) { throw new FormatException("Wrong dynamic huffman codes."); } int m_iRepSymbol = symbol - 16; int bits = DEF_HUFFMAN_DYNTREE_REPEAT_BITS[m_iRepSymbol]; int count = ReadBits(bits); if (count < 0) throw new FormatException("Wrong dynamic huffman codes."); count += DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS[m_iRepSymbol]; if (iCurrentCode + count > iResultingCodeLengthsCount) throw new FormatException("Wrong dynamic huffman codes."); while (count-- > 0) { arrResultingCodeLengths[iCurrentCode++] = bLastSymbol; } if (iCurrentCode == iResultingCodeLengthsCount) break; } byte[] tempArray = new byte[iLengthsCount]; Array.Copy(arrResultingCodeLengths, 0, tempArray, 0, iLengthsCount); lengthTree = new DecompressorHuffmanTree(tempArray); tempArray = new byte[iDistancesCount]; Array.Copy(arrResultingCodeLengths, iLengthsCount, tempArray, 0, iDistancesCount); distanceTree = new DecompressorHuffmanTree(tempArray); }
protected bool DecodeBlockHeader() { if (!m_bCanReadNextBlock) { return false; } int bFinalBlock = ReadBits(1); if (bFinalBlock == -1) { return false; } int blockType = ReadBits(2); if (blockType == -1) { return false; } m_bCanReadNextBlock = (bFinalBlock == 0); switch (blockType) { case 0: m_bReadingUncompressed = true; SkipToBoundary(); int length = ReadInt16Inverted(); int lengthComplement = ReadInt16Inverted(); if (length != (lengthComplement ^ 0xffff)) throw new FormatException("Wrong block length."); if (length > UInt16.MaxValue) throw new FormatException("Uncompressed block length can not be more than 65535."); m_UncompressedDataLength = length; m_CurrentLengthTree = null; m_CurrentDistanceTree = null; break; case 1: m_bReadingUncompressed = false; m_UncompressedDataLength = -1; m_CurrentLengthTree = DecompressorHuffmanTree.LengthTree; m_CurrentDistanceTree = DecompressorHuffmanTree.DistanceTree; break; case 2: m_bReadingUncompressed = false; m_UncompressedDataLength = -1; DecodeDynHeader(out m_CurrentLengthTree, out m_CurrentDistanceTree); break; default: throw new FormatException("Wrong block type."); } return true; }