Exemplo n.º 1
0
        public void Encode(Stream input, Stream output, IEnumerable <Match> matches, IHuffmanTreeBuilder treeBuilder)
        {
            var block = new Block();

            var matchArray   = matches.ToArray();
            var rawValueTree = CreateRawValueTree(input, matchArray, treeBuilder);

            block.rawValueDictionary = rawValueTree.GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            block.countIndexes = GetCountIndexes(matchArray, input.Length);
            var countIndexValueTree = CreateIndexValueTree(block, treeBuilder);

            block.countIndexDictionary = countIndexValueTree.GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            block.dispIndexes = GetDispIndexes(matchArray);
            var dispIndexTree = CreateDisplacementIndexTree(block, treeBuilder);

            block.dispIndexDictionary = dispIndexTree.GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            using var bw = new BitWriter(output, BitOrder.LeastSignificantBitFirst, 1, ByteOrder.LittleEndian);

            // Without obfuscation
            bw.WriteByte(0x02);

            WriteTreeNode(bw, rawValueTree, 8);
            WriteTreeNode(bw, countIndexValueTree, 6);
            WriteTreeNode(bw, dispIndexTree, 5);

            var countPosition        = 0;
            var displacementPosition = 0;

            foreach (var match in matchArray)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, bw, block, (int)(match.Position - input.Position), ref countPosition);
                }

                // Compress match
                CompressMatchData(input, bw, block, match, ref countPosition, ref displacementPosition);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, bw, block, (int)(input.Length - input.Position), ref countPosition);
            }

            // Write final 0 index
            foreach (var bit in block.countIndexDictionary[block.countIndexes.Last()])
            {
                bw.WriteBit(bit - '0');
            }
        }
Exemplo n.º 2
0
        public void Dispose()
        {
            _countIndexes         = null;
            _dispIndexes          = null;
            _rawValueDictionary   = null;
            _countIndexDictionary = null;
            _dispIndexDictionary  = null;

            _treeBuilder = null;
            _matchParser?.Dispose();
            _matchParser = null;
        }
Exemplo n.º 3
0
        public void Encode(Stream input, Stream output, IHuffmanTreeBuilder treeBuilder)
        {
            if (input.Length > 0xFFFFFF)
            {
                throw new InvalidOperationException("Data to compress is too long.");
            }

            var compressionHeader = new[] { (byte)(0x20 + _bitDepth), (byte)input.Length, (byte)((input.Length >> 8) & 0xFF), (byte)((input.Length >> 16) & 0xFF) };

            output.Write(compressionHeader, 0, 4);

            _encoder.Encode(input, output, treeBuilder);
        }
Exemplo n.º 4
0
        public void Encode(Stream input, Stream output, IHuffmanTreeBuilder treeBuilder)
        {
            if (input.Length > 0x1FFFFFFF)
            {
                throw new InvalidOperationException("Data to compress is too long.");
            }

            var huffmanMode       = _bitDepth == 4 ? 2 : 3;
            var compressionHeader = new[] {
                (byte)((byte)(input.Length << 3) | huffmanMode),
                (byte)(input.Length >> 5),
                (byte)(input.Length >> 13),
                (byte)(input.Length >> 21)
            };

            output.Write(compressionHeader, 0, 4);

            _encoder.Encode(input, output, treeBuilder);
        }
Exemplo n.º 5
0
 public NintendoHuffmanEncoder(int bitDepth, ByteOrder byteOrder, IHuffmanTreeBuilder treeBuilder)
 {
     _bitDepth    = bitDepth;
     _treeBuilder = treeBuilder;
     _byteOrder   = byteOrder;
 }
Exemplo n.º 6
0
 private HuffmanTreeNode CreateDisplacementIndexTree(Block block, IHuffmanTreeBuilder treeBuilder)
 {
     return(treeBuilder.Build(block.dispIndexes, 8, NibbleOrder.LowNibbleFirst));
 }
Exemplo n.º 7
0
 private HuffmanTreeNode CreateIndexValueTree(Block block, IHuffmanTreeBuilder treeBuilder)
 {
     return(treeBuilder.Build(block.countIndexes, 8, NibbleOrder.LowNibbleFirst));
 }
Exemplo n.º 8
0
        private HuffmanTreeNode CreateRawValueTree(Stream input, Match[] matches, IHuffmanTreeBuilder treeBuilder)
        {
            var huffmanInput = RemoveMatchesFromInput(input.ToArray(), matches);

            return(treeBuilder.Build(huffmanInput, 8, NibbleOrder.LowNibbleFirst));
        }
Exemplo n.º 9
0
 public TaikoLz81Encoder(IMatchParser matchParser, IHuffmanTreeBuilder treeBuilder)
 {
     _matchParser = matchParser;
     _treeBuilder = treeBuilder;
 }
Exemplo n.º 10
0
 public HuffmanHeaderlessEncoder(int bitDepth, NibbleOrder nibbleOrder, IHuffmanTreeBuilder treeBuilder)
 {
     _bitDepth    = bitDepth;
     _treeBuilder = treeBuilder;
     _nibbleOrder = nibbleOrder;
 }
Exemplo n.º 11
0
 public HuffmanEncoder(int bitDepth, IHuffmanTreeBuilder treeBuilder, NibbleOrder nibbleOrder = NibbleOrder.LowNibbleFirst)
 {
     _bitDepth = bitDepth;
     _encoder  = new HuffmanHeaderlessEncoder(bitDepth, nibbleOrder, treeBuilder);
 }
Exemplo n.º 12
0
        public void Encode(Stream input, Stream output, IHuffmanTreeBuilder treeBuilder)
        {
            var rootNode = treeBuilder.Build(input.ToArray(), _bitDepth, _nibbleOrder);

            // For a more even distribution of the children over the branches, we'll label the tree nodes
            var labelList = LabelTreeNodes(rootNode);

            // Create huffman bit codes
            var bitCodes = labelList[0].GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            using var bw = new BinaryWriterX(output, true);

            // Write header
            bw.Write((byte)labelList.Count);

            // Write Huffman tree
            foreach (var node in labelList.Take(1).Concat(labelList.SelectMany(node => node.Children)))
            {
                if (node.Children != null)
                {
                    node.Code |= node.Children.Select((child, i) => child.IsLeaf ? (byte)(0x80 >> i) : 0).Sum();
                }
                bw.Write((byte)node.Code);
            }

            // Write bits to stream
            using var bitWriter = new BitWriter(bw.BaseStream, BitOrder.MostSignificantBitFirst, 4, ByteOrder.LittleEndian);
            switch (_bitDepth)
            {
            case 4:
                while (input.Position < input.Length)
                {
                    var value = input.ReadByte();
                    if (_nibbleOrder == NibbleOrder.LowNibbleFirst)
                    {
                        foreach (var bit in bitCodes[value % 16])
                        {
                            bitWriter.WriteBit(bit - '0');
                        }
                        foreach (var bit in bitCodes[value / 16])
                        {
                            bitWriter.WriteBit(bit - '0');
                        }
                    }
                    else
                    {
                        foreach (var bit in bitCodes[value / 16])
                        {
                            bitWriter.WriteBit(bit - '0');
                        }
                        foreach (var bit in bitCodes[value % 16])
                        {
                            bitWriter.WriteBit(bit - '0');
                        }
                    }
                }
                break;

            case 8:
                while (input.Position < input.Length)
                {
                    var value = input.ReadByte();
                    foreach (var bit in bitCodes[value])
                    {
                        bitWriter.WriteBit(bit - '0');
                    }
                }
                break;
            }

            bitWriter.Flush();
        }
Exemplo n.º 13
0
 public void Dispose()
 {
     _treeBuilder = null;
     _matchParser?.Dispose();
     _matchParser = null;
 }