Exemplo n.º 1
0
        /// <summary>
        /// Decodes a successive approximation refinement block, as specified in section G.1.2.
        /// </summary>
        /// <param name="bp">The <see cref="InputProcessor"/> instance</param>
        /// <param name="h">The Huffman tree</param>
        /// <param name="delta">The low transform offset</param>
        private void Refine(ref InputProcessor bp, ref HuffmanTree h, int delta)
        {
            Block8x8F *b = this.pointers.Block;

            // Refining a DC component is trivial.
            if (this.zigStart == 0)
            {
                if (this.zigEnd != 0)
                {
                    throw new ImageFormatException("Invalid state for zig DC component");
                }

                bool             bit;
                DecoderErrorCode errorCode = bp.DecodeBitUnsafe(out bit);
                if (!bp.CheckEOFEnsureNoError(errorCode))
                {
                    return;
                }

                if (bit)
                {
                    int stuff = (int)Block8x8F.GetScalarAt(b, 0);

                    // int stuff = (int)b[0];
                    stuff |= delta;

                    // b[0] = stuff;
                    Block8x8F.SetScalarAt(b, 0, stuff);
                }

                return;
            }

            // Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3.
            int zig = this.zigStart;

            if (this.eobRun == 0)
            {
                for (; zig <= this.zigEnd; zig++)
                {
                    bool done = false;
                    int  z    = 0;

                    int val;
                    DecoderErrorCode errorCode = bp.DecodeHuffmanUnsafe(ref h, out val);
                    if (!bp.CheckEOF(errorCode))
                    {
                        return;
                    }

                    int val0 = val >> 4;
                    int val1 = val & 0x0f;

                    switch (val1)
                    {
                    case 0:
                        if (val0 != 0x0f)
                        {
                            this.eobRun = 1 << val0;
                            if (val0 != 0)
                            {
                                errorCode = this.DecodeEobRun(val0, ref bp);
                                if (!bp.CheckEOFEnsureNoError(errorCode))
                                {
                                    return;
                                }
                            }

                            done = true;
                        }

                        break;

                    case 1:
                        z = delta;

                        bool bit;
                        errorCode = bp.DecodeBitUnsafe(out bit);
                        if (!bp.CheckEOFEnsureNoError(errorCode))
                        {
                            return;
                        }

                        if (!bit)
                        {
                            z = -z;
                        }

                        break;

                    default:
                        throw new ImageFormatException("Unexpected Huffman code");
                    }

                    if (done)
                    {
                        break;
                    }

                    zig = this.RefineNonZeroes(ref bp, zig, val0, delta);
                    if (bp.UnexpectedEndOfStreamReached)
                    {
                        return;
                    }

                    if (zig > this.zigEnd)
                    {
                        throw new ImageFormatException($"Too many coefficients {zig} > {this.zigEnd}");
                    }

                    if (z != 0)
                    {
                        // b[Unzig[zig]] = z;
                        Block8x8F.SetScalarAt(b, this.pointers.Unzig[zig], z);
                    }
                }
            }

            if (this.eobRun > 0)
            {
                this.eobRun--;
                this.RefineNonZeroes(ref bp, zig, -1, delta);
            }
        }
        /// <summary>
        /// Extracts the next Huffman-coded value from the bit-stream into result, decoded according to the given value.
        /// </summary>
        /// <param name="huffmanTree">The huffman value</param>
        /// <param name="result">The decoded <see cref="byte" /></param>
        /// <returns>The <see cref="DecoderErrorCode"/></returns>
        public DecoderErrorCode DecodeHuffmanUnsafe(ref HuffmanTree huffmanTree, out int result)
        {
            result = 0;

            if (huffmanTree.Length == 0)
            {
                DecoderThrowHelper.ThrowImageFormatException.UninitializedHuffmanTable();
            }

            if (this.Bits.UnreadBits < 8)
            {
                DecoderErrorCode errorCode = this.Bits.Ensure8BitsUnsafe(ref this);

                if (errorCode == DecoderErrorCode.NoError)
                {
                    int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - HuffmanTree.LutSizeLog2)) & 0xFF;
                    int v        = huffmanTree.Lut[lutIndex];

                    if (v != 0)
                    {
                        int n = (v & 0xFF) - 1;
                        this.Bits.UnreadBits -= n;
                        this.Bits.Mask      >>= n;
                        result = v >> 8;
                        return(errorCode);
                    }
                }
                else
                {
                    this.UnreadByteStuffedByte();
                    return(errorCode);
                }
            }

            int code = 0;

            for (int i = 0; i < HuffmanTree.MaxCodeLength; i++)
            {
                if (this.Bits.UnreadBits == 0)
                {
                    this.Bits.EnsureNBits(1, ref this);
                }

                if ((this.Bits.Accumulator & this.Bits.Mask) != 0)
                {
                    code |= 1;
                }

                this.Bits.UnreadBits--;
                this.Bits.Mask >>= 1;

                if (code <= huffmanTree.MaxCodes[i])
                {
                    result = huffmanTree.GetValue(code, i);
                    return(DecoderErrorCode.NoError);
                }

                code <<= 1;
            }

            // Unrecoverable error, throwing:
            DecoderThrowHelper.ThrowImageFormatException.BadHuffmanCode();

            // DUMMY RETURN! C# doesn't know we have thrown an exception!
            return(DecoderErrorCode.NoError);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Decodes a successive approximation refinement block, as specified in section G.1.2.
        /// </summary>
        /// <param name="decoder">The decoder instance</param>
        /// <param name="h">The Huffman tree</param>
        /// <param name="delta">The low transform offset</param>
        private void Refine(JpegDecoderCore decoder, ref HuffmanTree h, int delta)
        {
            Block8x8F *b = this.pointers.Block;

            // Refining a DC component is trivial.
            if (this.zigStart == 0)
            {
                if (this.zigEnd != 0)
                {
                    throw new ImageFormatException("Invalid state for zig DC component");
                }

                bool bit = decoder.DecodeBit();
                if (bit)
                {
                    int stuff = (int)Block8x8F.GetScalarAt(b, 0);

                    // int stuff = (int)b[0];
                    stuff |= delta;

                    // b[0] = stuff;
                    Block8x8F.SetScalarAt(b, 0, stuff);
                }

                return;
            }

            // Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3.
            int zig = this.zigStart;

            if (this.eobRun == 0)
            {
                for (; zig <= this.zigEnd; zig++)
                {
                    bool done = false;
                    int  z    = 0;
                    byte val  = decoder.DecodeHuffman(ref h);
                    int  val0 = val >> 4;
                    int  val1 = val & 0x0f;

                    switch (val1)
                    {
                    case 0:
                        if (val0 != 0x0f)
                        {
                            this.eobRun = (ushort)(1 << val0);
                            if (val0 != 0)
                            {
                                this.eobRun |= (ushort)decoder.DecodeBits(val0);
                            }

                            done = true;
                        }

                        break;

                    case 1:
                        z = delta;
                        bool bit = decoder.DecodeBit();
                        if (!bit)
                        {
                            z = -z;
                        }

                        break;

                    default:
                        throw new ImageFormatException("Unexpected Huffman code");
                    }

                    if (done)
                    {
                        break;
                    }

                    zig = this.RefineNonZeroes(decoder, zig, val0, delta);
                    if (zig > this.zigEnd)
                    {
                        throw new ImageFormatException($"Too many coefficients {zig} > {this.zigEnd}");
                    }

                    if (z != 0)
                    {
                        // b[Unzig[zig]] = z;
                        Block8x8F.SetScalarAt(b, this.pointers.Unzig[zig], z);
                    }
                }
            }

            if (this.eobRun > 0)
            {
                this.eobRun--;
                this.RefineNonZeroes(decoder, zig, -1, delta);
            }
        }