コード例 #1
0
ファイル: Deflate.cs プロジェクト: Celderon/oxyplot
        /// <summary>
        /// For handling dynamic Huffman codes.
        /// </summary>
        /// <returns>A sequence of <see cref="CodeTree" /> items.</returns>
        private CodeTree[] DecodeHuffmanCodes()
        {
            var numLitLenCodes = this.ReadInt(5) + 257; // hlit  + 257
            var numDistCodes = this.ReadInt(5) + 1; // hdist +   1

            var numCodeLenCodes = this.ReadInt(4) + 4; // hclen +   4
            var codeLenCodeLen = new int[19];
            codeLenCodeLen[16] = this.ReadInt(3);
            codeLenCodeLen[17] = this.ReadInt(3);
            codeLenCodeLen[18] = this.ReadInt(3);
            codeLenCodeLen[0] = this.ReadInt(3);
            for (var i = 0; i < numCodeLenCodes - 4; i++)
            {
                if (i % 2 == 0)
                {
                    codeLenCodeLen[8 + (i / 2)] = this.ReadInt(3);
                }
                else
                {
                    codeLenCodeLen[7 - (i / 2)] = this.ReadInt(3);
                }
            }

            var codeLenCode = new CanonicalCode(codeLenCodeLen).ToCodeTree();

            var codeLens = new int[numLitLenCodes + numDistCodes];
            var runVal = -1;
            var runLen = 0;
            for (var i = 0; i < codeLens.Length; i++)
            {
                if (runLen > 0)
                {
                    codeLens[i] = runVal;
                    runLen--;
                }
                else
                {
                    var sym = this.DecodeSymbol(codeLenCode);
                    if (sym < 16)
                    {
                        codeLens[i] = sym;
                        runVal = sym;
                    }
                    else
                    {
                        if (sym == 16)
                        {
                            if (runVal == -1)
                            {
                                throw new FormatException("No code length value to copy");
                            }

                            runLen = this.ReadInt(2) + 3;
                        }
                        else if (sym == 17)
                        {
                            runVal = 0;
                            runLen = this.ReadInt(3) + 3;
                        }
                        else if (sym == 18)
                        {
                            runVal = 0;
                            runLen = this.ReadInt(7) + 11;
                        }
                        else
                        {
                            throw new Exception();
                        }

                        i--;
                    }
                }
            }

            if (runLen > 0)
            {
                throw new FormatException("Run exceeds number of codes");
            }

            // Create code trees
            var litLenCodeLen = Arrays.CopyOf(codeLens, numLitLenCodes);
            var litLenCode = new CanonicalCode(litLenCodeLen).ToCodeTree();

            var distCodeLen = Arrays.CopyOfRange(codeLens, numLitLenCodes, codeLens.Length);
            CodeTree distCode;
            if (distCodeLen.Length == 1 && distCodeLen[0] == 0)
            {
                distCode = null; // Empty distance code; the block shall be all literal symbols
            }
            else
            {
                distCode = new CanonicalCode(distCodeLen).ToCodeTree();
            }

            return new[] { litLenCode, distCode };
        }
コード例 #2
0
        /// <summary>
        /// For handling dynamic Huffman codes.
        /// </summary>
        /// <returns>A sequence of <see cref="CodeTree" /> items.</returns>
        private CodeTree[] DecodeHuffmanCodes()
        {
            var numLitLenCodes = this.ReadInt(5) + 257; // hlit  + 257
            var numDistCodes   = this.ReadInt(5) + 1;   // hdist +   1

            var numCodeLenCodes = this.ReadInt(4) + 4;  // hclen +   4
            var codeLenCodeLen  = new int[19];

            codeLenCodeLen[16] = this.ReadInt(3);
            codeLenCodeLen[17] = this.ReadInt(3);
            codeLenCodeLen[18] = this.ReadInt(3);
            codeLenCodeLen[0]  = this.ReadInt(3);
            for (var i = 0; i < numCodeLenCodes - 4; i++)
            {
                if (i % 2 == 0)
                {
                    codeLenCodeLen[8 + (i / 2)] = this.ReadInt(3);
                }
                else
                {
                    codeLenCodeLen[7 - (i / 2)] = this.ReadInt(3);
                }
            }

            var codeLenCode = new CanonicalCode(codeLenCodeLen).ToCodeTree();

            var codeLens = new int[numLitLenCodes + numDistCodes];
            var runVal   = -1;
            var runLen   = 0;

            for (var i = 0; i < codeLens.Length; i++)
            {
                if (runLen > 0)
                {
                    codeLens[i] = runVal;
                    runLen--;
                }
                else
                {
                    var sym = this.DecodeSymbol(codeLenCode);
                    if (sym < 16)
                    {
                        codeLens[i] = sym;
                        runVal      = sym;
                    }
                    else
                    {
                        if (sym == 16)
                        {
                            if (runVal == -1)
                            {
                                throw new FormatException("No code length value to copy");
                            }

                            runLen = this.ReadInt(2) + 3;
                        }
                        else if (sym == 17)
                        {
                            runVal = 0;
                            runLen = this.ReadInt(3) + 3;
                        }
                        else if (sym == 18)
                        {
                            runVal = 0;
                            runLen = this.ReadInt(7) + 11;
                        }
                        else
                        {
                            throw new Exception();
                        }

                        i--;
                    }
                }
            }

            if (runLen > 0)
            {
                throw new FormatException("Run exceeds number of codes");
            }

            // Create code trees
            var litLenCodeLen = Arrays.CopyOf(codeLens, numLitLenCodes);
            var litLenCode    = new CanonicalCode(litLenCodeLen).ToCodeTree();

            var      distCodeLen = Arrays.CopyOfRange(codeLens, numLitLenCodes, codeLens.Length);
            CodeTree distCode;

            if (distCodeLen.Length == 1 && distCodeLen[0] == 0)
            {
                distCode = null; // Empty distance code; the block shall be all literal symbols
            }
            else
            {
                distCode = new CanonicalCode(distCodeLen).ToCodeTree();
            }

            return(new[] { litLenCode, distCode });
        }