Exemple #1
0
        /// <summary>
        /// Receive extend
        /// </summary>
        /// <param name="t">Byte</param>
        /// <param name="inputProcessor">The <see cref="InputProcessor"/></param>
        /// <param name="x">Read bits value</param>
        /// <returns>The <see cref="DecoderErrorCode"/></returns>
        public DecoderErrorCode ReceiveExtendUnsafe(int t, ref InputProcessor inputProcessor, out int x)
        {
            if (this.UnreadBits < t)
            {
                DecoderErrorCode errorCode = this.EnsureNBitsUnsafe(t, ref inputProcessor);
                if (errorCode != DecoderErrorCode.NoError)
                {
                    x = int.MaxValue;
                    return(errorCode);
                }
            }

            this.UnreadBits -= t;
            this.Mask      >>= t;
            int s = 1 << t;

            x = (int)((this.Accumulator >> this.UnreadBits) & (s - 1));

            if (x < (s >> 1))
            {
                x += ((-1) << t) + 1;
            }

            return(DecoderErrorCode.NoError);
        }
Exemple #2
0
        public int ReceiveExtend(int t, ref InputProcessor inputProcessor)
        {
            int x;
            DecoderErrorCode errorCode = this.ReceiveExtendUnsafe(t, ref inputProcessor, out x);

            errorCode.EnsureNoError();
            return(x);
        }
Exemple #3
0
 /// <summary>
 /// Reads bytes from the byte buffer to ensure that bits.UnreadBits is at
 /// least n. For best performance (avoiding function calls inside hot loops),
 /// the caller is the one responsible for first checking that bits.UnreadBits &lt; n.
 /// This method does not throw. Returns <see cref="DecoderErrorCode"/> instead.
 /// </summary>
 /// <param name="n">The number of bits to ensure.</param>
 /// <param name="inputProcessor">The <see cref="InputProcessor"/></param>
 /// <returns>Error code</returns>
 public DecoderErrorCode EnsureNBitsUnsafe(int n, ref InputProcessor inputProcessor)
 {
     while (true)
     {
         DecoderErrorCode errorCode = this.EnsureBitsStepImpl(ref inputProcessor);
         if (errorCode != DecoderErrorCode.NoError || this.UnreadBits >= n)
         {
             return(errorCode);
         }
     }
 }
Exemple #4
0
        private DecoderErrorCode DecodeEobRun(int count, ref InputProcessor decoder)
        {
            int bitsResult;
            DecoderErrorCode errorCode = decoder.DecodeBitsUnsafe(count, out bitsResult);

            if (errorCode != DecoderErrorCode.NoError)
            {
                return(errorCode);
            }

            this.eobRun |= bitsResult;
            return(DecoderErrorCode.NoError);
        }
Exemple #5
0
        /// <summary>
        /// Refines non-zero entries of b in zig-zag order.
        /// If <paramref name="nz" /> >= 0, the first <paramref name="nz" /> zero entries are skipped over.
        /// </summary>
        /// <param name="bp">The <see cref="InputProcessor"/></param>
        /// <param name="zig">The zig-zag start index</param>
        /// <param name="nz">The non-zero entry</param>
        /// <param name="delta">The low transform offset</param>
        /// <returns>The <see cref="int" /></returns>
        private int RefineNonZeroes(ref InputProcessor bp, int zig, int nz, int delta)
        {
            var b = this.pointers.Block;

            for (; zig <= this.zigEnd; zig++)
            {
                int   u  = this.pointers.Unzig[zig];
                float bu = Block8x8F.GetScalarAt(b, u);

                // TODO: Are the equality comparsions OK with floating point values? Isn't an epsilon value necessary?
                if (bu == 0)
                {
                    if (nz == 0)
                    {
                        break;
                    }

                    nz--;
                    continue;
                }

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

                if (!bit)
                {
                    continue;
                }

                if (bu >= 0)
                {
                    // b[u] += delta;
                    Block8x8F.SetScalarAt(b, u, bu + delta);
                }
                else
                {
                    // b[u] -= delta;
                    Block8x8F.SetScalarAt(b, u, bu - delta);
                }
            }

            return(zig);
        }
Exemple #6
0
        private DecoderErrorCode EnsureBitsStepImpl(ref InputProcessor inputProcessor)
        {
            int c;
            DecoderErrorCode errorCode = inputProcessor.Bytes.ReadByteStuffedByteUnsafe(inputProcessor.InputStream, out c);

            if (errorCode != DecoderErrorCode.NoError)
            {
                return(errorCode);
            }

            this.Accumulator = (this.Accumulator << 8) | c;
            this.UnreadBits += 8;
            if (this.Mask == 0)
            {
                this.Mask = 1 << 7;
            }
            else
            {
                this.Mask <<= 8;
            }

            return(errorCode);
        }
Exemple #7
0
 /// <summary>
 /// Unrolled version of <see cref="EnsureNBitsUnsafe"/> for n==1
 /// </summary>
 /// <param name="inputProcessor">The <see cref="InputProcessor"/></param>
 /// <returns>A <see cref="DecoderErrorCode"/></returns>
 public DecoderErrorCode Ensure1BitUnsafe(ref InputProcessor inputProcessor)
 {
     return(this.EnsureBitsStepImpl(ref inputProcessor));
 }
Exemple #8
0
        public void EnsureNBits(int n, ref InputProcessor inputProcessor)
        {
            DecoderErrorCode errorCode = this.EnsureNBitsUnsafe(n, ref inputProcessor);

            errorCode.EnsureNoError();
        }
Exemple #9
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);
            }
        }
Exemple #10
0
        /// <summary>
        /// Internal part of the DHT processor, whatever does it mean
        /// </summary>
        /// <param name="inputProcessor">The decoder instance</param>
        /// <param name="defineHuffmanTablesData">The temporal buffer that holds the data that has been read from the Jpeg stream</param>
        /// <param name="remaining">Remaining bits</param>
        public void ProcessDefineHuffmanTablesMarkerLoop(
            ref InputProcessor inputProcessor,
            byte[] defineHuffmanTablesData,
            ref int remaining)
        {
            // Read nCodes and huffman.Valuess (and derive h.Length).
            // nCodes[i] is the number of codes with code length i.
            // h.Length is the total number of codes.
            this.Length = 0;

            int[] ncodes = new int[MaxCodeLength];
            for (int i = 0; i < ncodes.Length; i++)
            {
                ncodes[i]    = defineHuffmanTablesData[i + 1];
                this.Length += ncodes[i];
            }

            if (this.Length == 0)
            {
                throw new ImageFormatException("Huffman table has zero length");
            }

            if (this.Length > MaxNCodes)
            {
                throw new ImageFormatException("Huffman table has excessive length");
            }

            remaining -= this.Length + 17;
            if (remaining < 0)
            {
                throw new ImageFormatException("DHT has wrong length");
            }

            byte[] values = null;
            try
            {
                values = BytePool256.Rent(MaxNCodes);
                inputProcessor.ReadFull(values, 0, this.Length);

                for (int i = 0; i < values.Length; i++)
                {
                    this.Values[i] = values[i];
                }
            }
            finally
            {
                BytePool256.Return(values, true);
            }

            // Derive the look-up table.
            for (int i = 0; i < this.Lut.Length; i++)
            {
                this.Lut[i] = 0;
            }

            int x = 0, code = 0;

            for (int i = 0; i < LutSizeLog2; i++)
            {
                code <<= 1;

                for (int j = 0; j < ncodes[i]; j++)
                {
                    // The codeLength is 1+i, so shift code by 8-(1+i) to
                    // calculate the high bits for every 8-bit sequence
                    // whose codeLength's high bits matches code.
                    // The high 8 bits of lutValue are the encoded value.
                    // The low 8 bits are 1 plus the codeLength.
                    int base2    = code << (7 - i);
                    int lutValue = (this.Values[x] << 8) | (2 + i);

                    for (int k = 0; k < 1 << (7 - i); k++)
                    {
                        this.Lut[base2 | k] = lutValue;
                    }

                    code++;
                    x++;
                }
            }

            // Derive minCodes, maxCodes, and indices.
            int c = 0, index = 0;

            for (int i = 0; i < ncodes.Length; i++)
            {
                int nc = ncodes[i];
                if (nc == 0)
                {
                    this.MinCodes[i] = -1;
                    this.MaxCodes[i] = -1;
                    this.Indices[i]  = -1;
                }
                else
                {
                    this.MinCodes[i] = c;
                    this.MaxCodes[i] = c + nc - 1;
                    this.Indices[i]  = index;
                    c     += nc;
                    index += nc;
                }

                c <<= 1;
            }
        }