public static void EnsureNoEOF(this OrigDecoderErrorCode errorCode)
 {
     if (errorCode == OrigDecoderErrorCode.UnexpectedEndOfStream)
     {
         errorCode.ThrowExceptionForErrorCode();
     }
 }
示例#2
0
        public byte ReadByte(Stream inputStream)
        {
            OrigDecoderErrorCode errorCode = this.ReadByteUnsafe(inputStream, out byte result);

            errorCode.EnsureNoError();
            return(result);
        }
 public static void EnsureNoError(this OrigDecoderErrorCode errorCode)
 {
     if (errorCode != OrigDecoderErrorCode.NoError)
     {
         ThrowExceptionForErrorCode(errorCode);
     }
 }
示例#4
0
        public int ReceiveExtend(int t, ref InputProcessor inputProcessor)
        {
            OrigDecoderErrorCode errorCode = this.ReceiveExtendUnsafe(t, ref inputProcessor, out int x);

            errorCode.EnsureNoError();
            return(x);
        }
示例#5
0
        /// <summary>
        /// Reads exactly length bytes into data. It does not care about byte stuffing.
        /// Does not throw on errors, returns <see cref="OrigJpegDecoderCore"/> instead!
        /// </summary>
        /// <param name="data">The data to write to.</param>
        /// <param name="offset">The offset in the source buffer</param>
        /// <param name="length">The number of bytes to read</param>
        /// <returns>The <see cref="OrigDecoderErrorCode"/></returns>
        public OrigDecoderErrorCode ReadFullUnsafe(byte[] data, int offset, int length)
        {
            // Unread the overshot bytes, if any.
            if (this.Bytes.UnreadableBytes != 0)
            {
                if (this.Bits.UnreadBits >= 8)
                {
                    this.UnreadByteStuffedByte();
                }

                this.Bytes.UnreadableBytes = 0;
            }

            this.LastErrorCode = OrigDecoderErrorCode.NoError;
            while (length > 0 && this.LastErrorCode == OrigDecoderErrorCode.NoError)
            {
                if (this.Bytes.J - this.Bytes.I >= length)
                {
                    Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, length);
                    this.Bytes.I += length;
                    length       -= length;
                }
                else
                {
                    Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, this.Bytes.J - this.Bytes.I);
                    offset       += this.Bytes.J - this.Bytes.I;
                    length       -= this.Bytes.J - this.Bytes.I;
                    this.Bytes.I += this.Bytes.J - this.Bytes.I;

                    this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream);
                }
            }

            return(this.LastErrorCode);
        }
示例#6
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="OrigDecoderErrorCode"/></returns>
        public OrigDecoderErrorCode ReceiveExtendUnsafe(int t, ref InputProcessor inputProcessor, out int x)
        {
            if (this.UnreadBits < t)
            {
                OrigDecoderErrorCode errorCode = this.EnsureNBitsUnsafe(t, ref inputProcessor);
                if (errorCode != OrigDecoderErrorCode.NoError)
                {
                    x = int.MaxValue;
                    return(errorCode);
                }
            }

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

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

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

            return(OrigDecoderErrorCode.NoError);
        }
示例#7
0
        /// <summary>
        /// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data.
        /// </summary>
        /// <param name="inputStream">Input stream</param>
        /// <param name="x">The result byte as <see cref="int"/></param>
        /// <returns>The <see cref="OrigDecoderErrorCode"/></returns>
        public OrigDecoderErrorCode ReadByteStuffedByteUnsafe(Stream inputStream, out int x)
        {
            // Take the fast path if bytes.buf contains at least two bytes.
            if (this.I + 2 <= this.J)
            {
                x = this.BufferAsInt[this.I];
                this.I++;
                this.UnreadableBytes = 1;
                if (x != OrigJpegConstants.Markers.XFFInt)
                {
                    return(OrigDecoderErrorCode.NoError);
                }

                if (this.BufferAsInt[this.I] != 0x00)
                {
                    return(OrigDecoderErrorCode.MissingFF00);
                }

                this.I++;
                this.UnreadableBytes = 2;
                x = OrigJpegConstants.Markers.XFF;
                return(OrigDecoderErrorCode.NoError);
            }

            this.UnreadableBytes = 0;

            OrigDecoderErrorCode errorCode = this.ReadByteAsIntUnsafe(inputStream, out x);

            this.UnreadableBytes = 1;
            if (errorCode != OrigDecoderErrorCode.NoError)
            {
                return(errorCode);
            }

            if (x != OrigJpegConstants.Markers.XFF)
            {
                return(OrigDecoderErrorCode.NoError);
            }

            errorCode            = this.ReadByteAsIntUnsafe(inputStream, out x);
            this.UnreadableBytes = 2;
            if (errorCode != OrigDecoderErrorCode.NoError)
            {
                return(errorCode);
            }

            if (x != 0x00)
            {
                return(OrigDecoderErrorCode.MissingFF00);
            }

            x = OrigJpegConstants.Markers.XFF;
            return(OrigDecoderErrorCode.NoError);
        }
示例#8
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="OrigDecoderErrorCode"/> 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 OrigDecoderErrorCode EnsureNBitsUnsafe(int n, ref InputProcessor inputProcessor)
 {
     while (true)
     {
         OrigDecoderErrorCode errorCode = this.EnsureBitsStepImpl(ref inputProcessor);
         if (errorCode != OrigDecoderErrorCode.NoError || this.UnreadBits >= n)
         {
             return(errorCode);
         }
     }
 }
示例#9
0
        public static void ThrowExceptionForErrorCode(this OrigDecoderErrorCode errorCode)
        {
            switch (errorCode)
            {
            case OrigDecoderErrorCode.NoError:
                throw new ArgumentException("ThrowExceptionForErrorCode() called with NoError!", nameof(errorCode));

            case OrigDecoderErrorCode.MissingFF00:
                throw new MissingFF00Exception();

            case OrigDecoderErrorCode.UnexpectedEndOfStream:
                throw new EOFException();

            default:
                throw new ArgumentOutOfRangeException(nameof(errorCode), errorCode, null);
            }
        }
示例#10
0
        /// <summary>
        /// Decodes a single bit
        /// TODO: This method (and also the usages) could be optimized by batching!
        /// </summary>
        /// <param name="result">The decoded bit as a <see cref="bool"/></param>
        /// <returns>The <see cref="OrigDecoderErrorCode" /></returns>
        public OrigDecoderErrorCode DecodeBitUnsafe(out bool result)
        {
            if (this.Bits.UnreadBits == 0)
            {
                this.LastErrorCode = this.Bits.Ensure1BitUnsafe(ref this);
                if (this.LastErrorCode != OrigDecoderErrorCode.NoError)
                {
                    result = false;
                    return(this.LastErrorCode);
                }
            }

            result = (this.Bits.Accumulator & this.Bits.Mask) != 0;
            this.Bits.UnreadBits--;
            this.Bits.Mask >>= 1;
            return(this.LastErrorCode = OrigDecoderErrorCode.NoError);
        }
示例#11
0
        /// <summary>
        /// Decodes the given number of bits
        /// </summary>
        /// <param name="count">The number of bits to decode.</param>
        /// <param name="result">The <see cref="uint" /> result</param>
        /// <returns>The <see cref="OrigDecoderErrorCode"/></returns>
        public OrigDecoderErrorCode DecodeBitsUnsafe(int count, out int result)
        {
            if (this.Bits.UnreadBits < count)
            {
                this.LastErrorCode = this.Bits.EnsureNBitsUnsafe(count, ref this);
                if (this.LastErrorCode != OrigDecoderErrorCode.NoError)
                {
                    result = 0;
                    return(this.LastErrorCode);
                }
            }

            result = this.Bits.Accumulator >> (this.Bits.UnreadBits - count);
            result = result & ((1 << count) - 1);
            this.Bits.UnreadBits -= count;
            this.Bits.Mask      >>= count;
            return(this.LastErrorCode = OrigDecoderErrorCode.NoError);
        }
示例#12
0
        public OrigDecoderErrorCode ReadByteAsIntUnsafe(Stream inputStream, out int result)
        {
            OrigDecoderErrorCode errorCode = OrigDecoderErrorCode.NoError;

            while (this.I == this.J)
            {
                errorCode = this.FillUnsafe(inputStream);
                if (errorCode != OrigDecoderErrorCode.NoError)
                {
                    result = 0;
                    return(errorCode);
                }
            }

            result = this.BufferAsInt[this.I];
            this.I++;
            this.UnreadableBytes = 0;
            return(errorCode);
        }
示例#13
0
        public static void ThrowExceptionForErrorCode(this OrigDecoderErrorCode errorCode)
        {
            // REMARK: If this method throws for an image that is expected to be decodable,
            // consider using the ***Unsafe variant of the parsing method that asks for ThrowExceptionForErrorCode()
            // then verify the error code + implement fallback logic manually!
            switch (errorCode)
            {
            case OrigDecoderErrorCode.NoError:
                throw new ArgumentException("ThrowExceptionForErrorCode() called with NoError!", nameof(errorCode));

            case OrigDecoderErrorCode.MissingFF00:
                throw new MissingFF00Exception();

            case OrigDecoderErrorCode.UnexpectedEndOfStream:
                throw new EOFException();

            default:
                throw new ArgumentOutOfRangeException(nameof(errorCode), errorCode, null);
            }
        }
示例#14
0
        private OrigDecoderErrorCode EnsureBitsStepImpl(ref InputProcessor inputProcessor)
        {
            OrigDecoderErrorCode errorCode = inputProcessor.Bytes.ReadByteStuffedByteUnsafe(inputProcessor.InputStream, out int c);

            if (errorCode != OrigDecoderErrorCode.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);
        }
示例#15
0
        /// <summary>
        /// Skips the next n bytes.
        /// Does not throw, returns <see cref="OrigDecoderErrorCode"/> instead!
        /// </summary>
        /// <param name="count">The number of bytes to ignore.</param>
        /// <returns>The <see cref="OrigDecoderErrorCode"/></returns>
        public OrigDecoderErrorCode SkipUnsafe(int count)
        {
            // Unread the overshot bytes, if any.
            if (this.Bytes.UnreadableBytes != 0)
            {
                if (this.Bits.UnreadBits >= 8)
                {
                    this.UnreadByteStuffedByte();
                }

                this.Bytes.UnreadableBytes = 0;
            }

            while (true)
            {
                int m = this.Bytes.J - this.Bytes.I;
                if (m > count)
                {
                    m = count;
                }

                this.Bytes.I += m;
                count        -= m;
                if (count == 0)
                {
                    break;
                }

                this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream);
                if (this.LastErrorCode != OrigDecoderErrorCode.NoError)
                {
                    return(this.LastErrorCode);
                }
            }

            return(this.LastErrorCode = OrigDecoderErrorCode.NoError);
        }
示例#16
0
 public void ResetErrorState() => this.LastErrorCode = OrigDecoderErrorCode.NoError;
示例#17
0
 /// <summary>
 /// Receive extend
 /// </summary>
 /// <param name="t">Byte</param>
 /// <param name="x">Read bits value</param>
 /// <returns>The <see cref="OrigDecoderErrorCode"/></returns>
 public OrigDecoderErrorCode ReceiveExtendUnsafe(int t, out int x)
 {
     this.LastErrorCode = this.Bits.ReceiveExtendUnsafe(t, ref this, out x);
     return(this.LastErrorCode);
 }
示例#18
0
 public void ReadFull(byte[] data, int offset, int length)
 {
     this.LastErrorCode = this.ReadFullUnsafe(data, offset, length);
     this.LastErrorCode.EnsureNoError();
 }
示例#19
0
 public void Skip(int count)
 {
     this.LastErrorCode = this.SkipUnsafe(count);
     this.LastErrorCode.EnsureNoError();
 }
示例#20
0
        /// <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="OrigDecoderErrorCode"/></returns>
        public OrigDecoderErrorCode DecodeHuffmanUnsafe(ref OrigHuffmanTree huffmanTree, out int result)
        {
            result = 0;

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

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

                if (this.LastErrorCode == OrigDecoderErrorCode.NoError)
                {
                    int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - OrigHuffmanTree.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(this.LastErrorCode);
                    }
                }
                else
                {
                    this.UnreadByteStuffedByte();
                    return(this.LastErrorCode);
                }
            }

            int code = 0;

            for (int i = 0; i < OrigHuffmanTree.MaxCodeLength; i++)
            {
                if (this.Bits.UnreadBits == 0)
                {
                    this.LastErrorCode = this.Bits.EnsureNBitsUnsafe(1, ref this);

                    if (this.HasError)
                    {
                        return(this.LastErrorCode);
                    }
                }

                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(this.LastErrorCode = OrigDecoderErrorCode.NoError);
                }

                code <<= 1;
            }

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

            // DUMMY RETURN! C# doesn't know we have thrown an exception!
            return(OrigDecoderErrorCode.NoError);
        }
示例#21
0
 public OrigDecoderErrorCode ReadByteUnsafe(out byte result)
 {
     this.LastErrorCode = this.Bytes.ReadByteUnsafe(this.InputStream, out result);
     return(this.LastErrorCode);
 }
示例#22
0
        public void Fill(Stream inputStream)
        {
            OrigDecoderErrorCode errorCode = this.FillUnsafe(inputStream);

            errorCode.EnsureNoError();
        }
示例#23
0
        public void EnsureNBits(int n, ref InputProcessor inputProcessor)
        {
            OrigDecoderErrorCode errorCode = this.EnsureNBitsUnsafe(n, ref inputProcessor);

            errorCode.EnsureNoError();
        }