public uint NextSymbol() { if (_symbolsToNextSelector == 0) { _symbolsToNextSelector = 50; _activeTree = _trees[_selectors[_nextSelector]]; _nextSelector++; } _symbolsToNextSelector--; return _activeTree.NextSymbol(_bitstream); }
private void Initialize(int maxSymbols) { int numTrees = (int)_bitstream.Read(3); if (numTrees < 2 || numTrees > 6) { throw new InvalidDataException("Invalid number of tables"); } int numSelectors = (int)_bitstream.Read(15); if (numSelectors < 1) { throw new InvalidDataException("Invalid number of selectors"); } _selectors = new byte[numSelectors]; MoveToFront mtf = new MoveToFront(numTrees, true); for (int i = 0; i < numSelectors; ++i) { _selectors[i] = mtf.GetAndMove(CountSetBits(numTrees)); } _trees = new HuffmanTree[numTrees]; for (int t = 0; t < numTrees; ++t) { uint[] lengths = new uint[maxSymbols]; uint len = _bitstream.Read(5); for (int i = 0; i < maxSymbols; ++i) { if (len < 1 || len > 20) { throw new InvalidDataException("Invalid length constructing Huffman tree"); } while (_bitstream.Read(1) != 0) { len = (_bitstream.Read(1) == 0) ? len + 1 : len - 1; if (len < 1 || len > 20) { throw new InvalidDataException("Invalid length constructing Huffman tree"); } } lengths[i] = len; } _trees[t] = new HuffmanTree(lengths); } _symbolsToNextSelector = 0; _nextSelector = 0; }
private void ReadLengths(HuffmanTree preTree, uint[] lengths, int offset, int count) { int i = 0; while (i < count) { uint value = preTree.NextSymbol(_bitStream); if (value == 17) { uint numZeros = 4 + _bitStream.Read(4); for (uint j = 0; j < numZeros; ++j) { lengths[offset + i] = 0; ++i; } } else if (value == 18) { uint numZeros = 20 + _bitStream.Read(5); for (uint j = 0; j < numZeros; ++j) { lengths[offset + i] = 0; ++i; } } else if (value == 19) { uint same = _bitStream.Read(1); value = preTree.NextSymbol(_bitStream); if (value > 16) { throw new InvalidDataException("Invalid table encoding"); } uint symbol = (17 + lengths[offset + i] - value) % 17; for (uint j = 0; j < 4 + same; ++j) { lengths[offset + i] = symbol; ++i; } } else { lengths[offset + i] = (17 + lengths[offset + i] - value) % 17; ++i; } } }
private HuffmanTree ReadDynamicHuffmanTree(int count, HuffmanTree preTree, HuffmanTree oldTree) { uint[] lengths; if (oldTree == null) { lengths = new uint[256 + (8 * _numPositionSlots)]; } else { lengths = oldTree.Lengths; } ReadLengths(preTree, lengths, 0, count); return new HuffmanTree(lengths); }
private void ReadLengthTree() { HuffmanTree preTree = ReadFixedHuffmanTree(20, 4); _lengthTree = ReadDynamicHuffmanTree(249, preTree, _lengthTree); }
private void ReadMainTree() { uint[] lengths; if (_mainTree == null) { lengths = new uint[256 + (8 * _numPositionSlots)]; } else { lengths = _mainTree.Lengths; } HuffmanTree preTree = ReadFixedHuffmanTree(20, 4); ReadLengths(preTree, lengths, 0, 256); preTree = ReadFixedHuffmanTree(20, 4); ReadLengths(preTree, lengths, 256, 8 * _numPositionSlots); _mainTree = new HuffmanTree(lengths); }
private void DecodeCompressedBlock(BlockType blockType, int blockSize) { if (blockType == BlockType.AlignedOffset) { _alignedOffsetTree = ReadFixedHuffmanTree(8, 3); } ReadMainTree(); ReadLengthTree(); uint numRead = 0; while (numRead < (uint)blockSize) { uint symbol = _mainTree.NextSymbol(_bitStream); if (symbol < 256) { _buffer[_bufferCount + numRead++] = (byte)symbol; } else { uint lengthHeader = (symbol - 256) & 7; uint matchLength = lengthHeader + 2 + ((lengthHeader == 7) ? _lengthTree.NextSymbol(_bitStream) : 0); uint positionSlot = (symbol - 256) >> 3; uint matchOffset; if (positionSlot == 0) { matchOffset = _repeatedOffsets[0]; } else if (positionSlot == 1) { matchOffset = _repeatedOffsets[1]; _repeatedOffsets[1] = _repeatedOffsets[0]; _repeatedOffsets[0] = matchOffset; } else if (positionSlot == 2) { matchOffset = _repeatedOffsets[2]; _repeatedOffsets[2] = _repeatedOffsets[0]; _repeatedOffsets[0] = matchOffset; } else { int extra = (int)s_extraBits[positionSlot]; uint formattedOffset; if (blockType == BlockType.AlignedOffset) { uint verbatimBits = 0; uint alignedBits = 0; if (extra >= 3) { verbatimBits = _bitStream.Read(extra - 3) << 3; alignedBits = _alignedOffsetTree.NextSymbol(_bitStream); } else if (extra > 0) { verbatimBits = _bitStream.Read(extra); } formattedOffset = s_positionSlots[positionSlot] + verbatimBits + alignedBits; } else { uint verbatimBits = (extra > 0) ? _bitStream.Read(extra) : 0; formattedOffset = s_positionSlots[positionSlot] + verbatimBits; } matchOffset = formattedOffset - 2; _repeatedOffsets[2] = _repeatedOffsets[1]; _repeatedOffsets[1] = _repeatedOffsets[0]; _repeatedOffsets[0] = matchOffset; } int destOffset = _bufferCount + (int)numRead; int srcOffset = destOffset - (int)matchOffset; for (int i = 0; i < matchLength; ++i) { _buffer[destOffset + i] = _buffer[srcOffset + i]; } numRead += matchLength; } } }