Beispiel #1
0
        // Huffman Tree Encoding:
        // - Max 14-bit symbol length = One nibble transmitted per symbol
        // - 0 means no code
        // - 15 is our RLE start symbol
        // - An RLE run would go as 3 nibbles: <Symbol> <RLE Command: 15> <Length of run>
        // - The lengh of run is transmitted as a nibble.
        // - This takes a minimum of 2 nibbles so 3 is the shortest run worth encoding.
        // - Therefore the range of the length of the run symbol is 3..18.

        // We don't try to do tree elision. The entire chunking thing is entirely an encoder-side
        // concept. We can emit a New Tree command whenever we want, so a more serious encoder could take
        // much greater efforts to be fancier with when to emit a new huffman tree.

        void EncodeHuffTree(HuffmanEncoder huffman)
        {
            int lastEmittedLength = -1;

            for (int i = 0; i < NUM_SYMBOLS;)
            {
                if (i < NUM_SYMBOLS - 4 &&
                    huffman.Symbols[i].Length == lastEmittedLength &&
                    huffman.Symbols[i + 1].Length == lastEmittedLength &&
                    huffman.Symbols[i + 2].Length == lastEmittedLength)
                {
                    Output.WriteBits(15, 4);  // Emit an RLE token
                    int runLength = 3;        // Determine run length
                    for (; runLength < 18 && i + runLength < NUM_SYMBOLS; runLength++)
                    {
                        if (huffman.Symbols[i + runLength].Length != lastEmittedLength)
                        {
                            break;
                        }
                    }
                    Output.WriteBits(runLength - 3, 4);
                    i += runLength;
                }
                else
                {
                    int length = huffman.Symbols[i].Length;
                    lastEmittedLength = length;
                    Output.WriteBits(length, 4);
                    i++;
                }
            }
        }
Beispiel #2
0
        void EncodeChunk()
        {
            var huff = new HuffmanEncoder(SymbolFreqs, 14);

            EncodeHuffTree(huff);
            for (int i = 0; i < ChunkOffset; i++)
            {
                int symbol = ChunkBuffer[i];
                var sym    = huff.Symbols[symbol];
                Output.WriteBits(sym.Code, sym.Length);
                if (symbol >= SYM_MATCH)
                {
                    var match = MatchEncodes.Dequeue();
                    Output.WriteBits(match.Distance, match.DistanceBits);
                    EncodeMatchLength(match.Length);
                }
            }
        }