func TestGenerateTreesLowest(t *testing.T) { _, reduced := symbols.Get([]byte("banana")) data := []uint16{'\x03', '\x00', '\x03', '\x00', '\x01', '\x04'} freqs := rle2.GetFrequencies(reduced, data) trees, selections := GenerateTrees(freqs, data) if len(trees) < 2 { t.Error("Not enough huffman trees generated") } if len(trees) > 6 { t.Error("Too many huffman trees generated") } if len(selections) != 1 { t.Error("The wrong number of huffman tree selections was returned") } }
func TestTreeCodeLength(t *testing.T) { _, reduced := symbols.Get([]byte("banana")) data := []uint16{'\x03', '\x00', '\x03', '\x00', '\x01', '\x04'} freqs := rle2.GetFrequencies(reduced, data) lowestlen := 0 tree := NewTree(freqs) for i, code := range tree.Codes { if i == 0 || code.Len < lowestlen { lowestlen = code.Len } } if lowestlen != tree.Codes['\x03'].Len { t.Error("The lowest code-length isn't the most used symbol") } }
func TestGenerateTreesMultipleSelections(t *testing.T) { _, reduced := symbols.Get([]byte("banana")) data := []uint16{'\x03', '\x00', '\x03', '\x00', '\x01', '\x04'} base := data for len(data) <= 200 { data = append(data, base...) } freqs := rle2.GetFrequencies(reduced, data) trees, selections := GenerateTrees(freqs, data) if len(trees) < 2 { t.Error("Not enough huffman trees generated") } if len(trees) > 6 { t.Error("Too many huffman trees generated") } if len(selections) != 5 { t.Error("The wrong number of huffman tree selections was returned") } }
// WriteBlock compresses the content buffered and writes // a block to the bit writer given. func (b *block) WriteBlock(bw *bits.Writer) error { rleData := b.runs.Encode() syms, reducedSyms := symbols.Get(rleData) // BWT step. bwtData := make([]byte, len(rleData)) bwtidx := bwt.Transform(bwtData, rleData) // MTF step. mtfData := bwtData mtf.Transform(reducedSyms, mtfData, bwtData) // RLE2 step. rle2Data := rle2.Encode(reducedSyms, mtfData) freqs := rle2.GetFrequencies(reducedSyms, rle2Data) // Setup the huffman trees required to encode rle2Data. trees, selections := huffman.GenerateTrees(freqs, rle2Data) // Get the MTF encoded huffman tree selections. treeSelectionSymbols := make(symbols.ReducedSet, len(trees)) for i := range trees { treeSelectionSymbols[i] = byte(i) } treeSelectionBytes := make([]byte, len(selections)) for i, selection := range selections { treeSelectionBytes[i] = byte(selection) } mtf.Transform(treeSelectionSymbols, treeSelectionBytes, treeSelectionBytes) // Write the block header. bw.WriteBits(48, blockMagic) bw.WriteBits(32, uint64(b.crc)) bw.WriteBits(1, 0) // Write the contents that build the decoding steps. bw.WriteBits(24, uint64(bwtidx)) b.writeSymbolBitmaps(bw, syms) bw.WriteBits(3, uint64(len(trees))) bw.WriteBits(15, uint64(len(selections))) b.writeTreeSelections(bw, treeSelectionBytes) b.writeTreeCodes(bw, trees) // Write the encoded contents, using the huffman trees generated // switching them out every 50 symbols. encoded := 0 idx := 0 tree := trees[selections[idx]] for _, b := range rle2Data { if encoded == huffman.TreeSelectionLimit { encoded = 0 idx++ tree = trees[selections[idx]] } code := tree.Codes[b] bw.WriteBits(uint(code.Len), code.Bits) encoded++ } return bw.Err() }