From b75481b84977cfe7b1fc867967a0a85e01d9e809 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 31 Aug 2017 03:54:04 +0200 Subject: [PATCH] ErrorCode is now a state of InputProcessor --- .../Components/Decoder/InputProcessor.cs | 84 ++++++++++--------- .../Components/Decoder/OrigJpegScanDecoder.cs | 61 +++++++------- .../Jpeg/GolangPort/OrigJpegDecoderCore.cs | 2 +- .../Formats/Jpg/JpegDecoderTests.cs | 4 +- 4 files changed, 78 insertions(+), 73 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs index a3967c7390..668c36ad5d 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder this.Bytes = Bytes.Create(); this.InputStream = inputStream; this.Temp = temp; - this.UnexpectedEndOfStreamReached = false; + this.LastErrorCode = OrigDecoderErrorCode.NoError; } /// @@ -48,48 +48,48 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder public byte[] Temp { get; } /// - /// Gets or sets a value indicating whether an unexpected EOF reached in . + /// Gets a value indicating whether an unexpected EOF reached in . /// - public bool UnexpectedEndOfStreamReached { get; set; } + public bool ReachedEOF => this.LastErrorCode == OrigDecoderErrorCode.UnexpectedEndOfStream; + + public OrigDecoderErrorCode LastErrorCode { get; private set; } + + public void ResetErrorState() => this.LastErrorCode = OrigDecoderErrorCode.NoError; /// - /// If errorCode indicates unexpected EOF, sets to true and returns false. + /// If errorCode indicates unexpected EOF, sets to true and returns false. /// Calls and returns true otherwise. /// /// The /// indicating whether everything is OK - public bool CheckEOFEnsureNoError(OrigDecoderErrorCode errorCode) + public bool CheckEOFEnsureNoError() { - if (errorCode == OrigDecoderErrorCode.UnexpectedEndOfStream) + if (this.LastErrorCode == OrigDecoderErrorCode.UnexpectedEndOfStream) { - this.UnexpectedEndOfStreamReached = true; return false; } - errorCode.EnsureNoError(); + this.LastErrorCode.EnsureNoError(); return true; } /// - /// If errorCode indicates unexpected EOF, sets to true and returns false. + /// If errorCode indicates unexpected EOF, sets to true and returns false. /// Returns true otherwise. /// /// The /// indicating whether everything is OK - public bool CheckEOF(OrigDecoderErrorCode errorCode) + public bool CheckEOF() { - if (errorCode == OrigDecoderErrorCode.UnexpectedEndOfStream) + if (this.LastErrorCode == OrigDecoderErrorCode.UnexpectedEndOfStream) { - this.UnexpectedEndOfStreamReached = true; return false; } return true; } - /// - /// Dispose - /// + /// public void Dispose() { this.Bytes.Dispose(); @@ -115,18 +115,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder { if (this.Bits.UnreadBits == 0) { - OrigDecoderErrorCode errorCode = this.Bits.Ensure1BitUnsafe(ref this); - if (errorCode != OrigDecoderErrorCode.NoError) + this.LastErrorCode = this.Bits.Ensure1BitUnsafe(ref this); + if (this.LastErrorCode != OrigDecoderErrorCode.NoError) { result = false; - return errorCode; + return this.LastErrorCode; } } result = (this.Bits.Accumulator & this.Bits.Mask) != 0; this.Bits.UnreadBits--; this.Bits.Mask >>= 1; - return OrigDecoderErrorCode.NoError; + return this.LastErrorCode = OrigDecoderErrorCode.NoError; } /// @@ -150,8 +150,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder this.Bytes.UnreadableBytes = 0; } - OrigDecoderErrorCode errorCode = OrigDecoderErrorCode.NoError; - while (length > 0 && errorCode == OrigDecoderErrorCode.NoError) + this.LastErrorCode = OrigDecoderErrorCode.NoError; + while (length > 0 && this.LastErrorCode == OrigDecoderErrorCode.NoError) { if (this.Bytes.J - this.Bytes.I >= length) { @@ -166,11 +166,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder length -= this.Bytes.J - this.Bytes.I; this.Bytes.I += this.Bytes.J - this.Bytes.I; - errorCode = this.Bytes.FillUnsafe(this.InputStream); + this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream); } } - return errorCode; + return this.LastErrorCode; } /// @@ -183,14 +183,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder { if (this.Bits.UnreadBits < count) { - this.Bits.EnsureNBits(count, ref this); + 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 OrigDecoderErrorCode.NoError; + return this.LastErrorCode = OrigDecoderErrorCode.NoError; } /// @@ -210,9 +215,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder if (this.Bits.UnreadBits < 8) { - OrigDecoderErrorCode errorCode = this.Bits.Ensure8BitsUnsafe(ref this); + this.LastErrorCode = this.Bits.Ensure8BitsUnsafe(ref this); - if (errorCode == OrigDecoderErrorCode.NoError) + if (this.LastErrorCode == OrigDecoderErrorCode.NoError) { int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - OrigHuffmanTree.LutSizeLog2)) & 0xFF; int v = huffmanTree.Lut[lutIndex]; @@ -223,13 +228,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder this.Bits.UnreadBits -= n; this.Bits.Mask >>= n; result = v >> 8; - return errorCode; + return this.LastErrorCode; } } else { this.UnreadByteStuffedByte(); - return errorCode; + return this.LastErrorCode; } } @@ -252,7 +257,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder if (code <= huffmanTree.MaxCodes[i]) { result = huffmanTree.GetValue(code, i); - return OrigDecoderErrorCode.NoError; + return this.LastErrorCode = OrigDecoderErrorCode.NoError; } code <<= 1; @@ -272,8 +277,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Skip(int count) { - OrigDecoderErrorCode errorCode = this.SkipUnsafe(count); - errorCode.EnsureNoError(); + this.LastErrorCode = this.SkipUnsafe(count); + this.LastErrorCode.EnsureNoError(); } /// @@ -310,14 +315,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder break; } - OrigDecoderErrorCode errorCode = this.Bytes.FillUnsafe(this.InputStream); - if (errorCode != OrigDecoderErrorCode.NoError) + this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream); + if (this.LastErrorCode != OrigDecoderErrorCode.NoError) { - return errorCode; + return this.LastErrorCode; } } - return OrigDecoderErrorCode.NoError; + return this.LastErrorCode = OrigDecoderErrorCode.NoError; } /// @@ -329,8 +334,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ReadFull(byte[] data, int offset, int length) { - OrigDecoderErrorCode errorCode = this.ReadFullUnsafe(data, offset, length); - errorCode.EnsureNoError(); + this.LastErrorCode = this.ReadFullUnsafe(data, offset, length); + this.LastErrorCode.EnsureNoError(); } /// @@ -360,7 +365,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder /// The public OrigDecoderErrorCode ReceiveExtendUnsafe(int t, out int x) { - return this.Bits.ReceiveExtendUnsafe(t, ref this, out x); + this.LastErrorCode = this.Bits.ReceiveExtendUnsafe(t, ref this, out x); + return this.LastErrorCode; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs index a563bcd488..3b09b5c3fc 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs @@ -178,7 +178,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder // Copy block to stack this.data.Block = blockRefOnHeap; - if (!decoder.InputProcessor.UnexpectedEndOfStreamReached) + if (!decoder.InputProcessor.ReachedEOF) { this.DecodeBlock(decoder, scanIndex); } @@ -197,10 +197,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder { // A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input, // but this one assumes well-formed input, and hence the restart marker follows immediately. - if (!decoder.InputProcessor.UnexpectedEndOfStreamReached) + if (!decoder.InputProcessor.ReachedEOF) { - OrigDecoderErrorCode errorCode = decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2); - if (decoder.InputProcessor.CheckEOFEnsureNoError(errorCode)) + decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2); + if (decoder.InputProcessor.CheckEOFEnsureNoError()) { if (decoder.Temp[0] != 0xff || decoder.Temp[1] != expectedRst) { @@ -318,7 +318,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder else { int zig = this.zigStart; - OrigDecoderErrorCode errorCode; + //OrigDecoderErrorCode errorCode; if (zig == 0) { zig++; @@ -326,10 +326,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder // Decode the DC coefficient, as specified in section F.2.2.1. int value; int huffmanIndex = (OrigHuffmanTree.DcTableIndex * OrigHuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].DcTableSelector; - errorCode = decoder.InputProcessor.DecodeHuffmanUnsafe( + decoder.InputProcessor.DecodeHuffmanUnsafe( ref decoder.HuffmanTrees[huffmanIndex], out value); - if (!decoder.InputProcessor.CheckEOF(errorCode)) + if (!decoder.InputProcessor.CheckEOF()) { return; } @@ -340,8 +340,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } int deltaDC; - errorCode = decoder.InputProcessor.ReceiveExtendUnsafe(value, out deltaDC); - if (!decoder.InputProcessor.CheckEOFEnsureNoError(errorCode)) + decoder.InputProcessor.ReceiveExtendUnsafe(value, out deltaDC); + if (!decoder.InputProcessor.CheckEOFEnsureNoError()) { return; } @@ -363,8 +363,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder for (; zig <= this.zigEnd; zig++) { int value; - errorCode = decoder.InputProcessor.DecodeHuffmanUnsafe(ref decoder.HuffmanTrees[huffmannIdx], out value); - if (!decoder.InputProcessor.CheckEOF(errorCode)) + decoder.InputProcessor.DecodeHuffmanUnsafe(ref decoder.HuffmanTrees[huffmannIdx], out value); + if (!decoder.InputProcessor.CheckEOF()) { return; } @@ -380,8 +380,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } int ac; - errorCode = decoder.InputProcessor.ReceiveExtendUnsafe(val1, out ac); - if (!decoder.InputProcessor.CheckEOFEnsureNoError(errorCode)) + decoder.InputProcessor.ReceiveExtendUnsafe(val1, out ac); + if (!decoder.InputProcessor.CheckEOFEnsureNoError()) { return; } @@ -397,8 +397,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder this.eobRun = (ushort)(1 << val0); if (val0 != 0) { - errorCode = this.DecodeEobRun(val0, ref decoder.InputProcessor); - if (!decoder.InputProcessor.CheckEOFEnsureNoError(errorCode)) + this.DecodeEobRun(val0, ref decoder.InputProcessor); + if (!decoder.InputProcessor.CheckEOFEnsureNoError()) { return; } @@ -415,17 +415,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } } - private OrigDecoderErrorCode DecodeEobRun(int count, ref InputProcessor decoder) + private void DecodeEobRun(int count, ref InputProcessor processor) { int bitsResult; - OrigDecoderErrorCode errorCode = decoder.DecodeBitsUnsafe(count, out bitsResult); - if (errorCode != OrigDecoderErrorCode.NoError) + processor.DecodeBitsUnsafe(count, out bitsResult); + if (processor.LastErrorCode != OrigDecoderErrorCode.NoError) { - return errorCode; + return; } this.eobRun |= bitsResult; - return OrigDecoderErrorCode.NoError; } /// @@ -516,8 +515,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } bool bit; - OrigDecoderErrorCode errorCode = bp.DecodeBitUnsafe(out bit); - if (!bp.CheckEOFEnsureNoError(errorCode)) + bp.DecodeBitUnsafe(out bit); + if (!bp.CheckEOFEnsureNoError()) { return; } @@ -546,8 +545,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder int z = 0; int val; - OrigDecoderErrorCode errorCode = bp.DecodeHuffmanUnsafe(ref h, out val); - if (!bp.CheckEOF(errorCode)) + bp.DecodeHuffmanUnsafe(ref h, out val); + if (!bp.CheckEOF()) { return; } @@ -563,8 +562,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder this.eobRun = 1 << val0; if (val0 != 0) { - errorCode = this.DecodeEobRun(val0, ref bp); - if (!bp.CheckEOFEnsureNoError(errorCode)) + this.DecodeEobRun(val0, ref bp); + if (!bp.CheckEOFEnsureNoError()) { return; } @@ -578,8 +577,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder z = delta; bool bit; - errorCode = bp.DecodeBitUnsafe(out bit); - if (!bp.CheckEOFEnsureNoError(errorCode)) + bp.DecodeBitUnsafe(out bit); + if (!bp.CheckEOFEnsureNoError()) { return; } @@ -600,7 +599,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } zig = this.RefineNonZeroes(ref bp, zig, val0, delta); - if (bp.UnexpectedEndOfStreamReached) + if (bp.ReachedEOF) { return; } @@ -650,8 +649,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } bool bit; - OrigDecoderErrorCode errorCode = bp.DecodeBitUnsafe(out bit); - if (!bp.CheckEOFEnsureNoError(errorCode)) + bp.DecodeBitUnsafe(out bit); + if (!bp.CheckEOFEnsureNoError()) { return int.MinValue; } diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs index d37ec91490..33ebe72d01 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs @@ -342,7 +342,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort // when this is a progressive image this gets called a number of times // need to know how many times this should be called in total. this.ProcessStartOfScan(remaining); - if (this.InputProcessor.UnexpectedEndOfStreamReached || !this.IsProgressive) + if (this.InputProcessor.ReachedEOF || !this.IsProgressive) { // if unexpeced EOF reached or this is not a progressive image we can stop processing bytes as we now have the image data. processBytes = false; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 7a145c80e4..32934ec9d7 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -38,7 +38,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Baseline.Bad.BadEOF, TestImages.Jpeg.Baseline.Bad.ExifUndefType, - TestImages.Jpeg.Issues.MissingFF00ProgressiveGirl159, TestImages.Jpeg.Issues.MissingFF00Gear159, }; @@ -46,7 +45,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { TestImages.Jpeg.Progressive.Fb, TestImages.Jpeg.Progressive.Progress, TestImages.Jpeg.Progressive.Festzug, TestImages.Jpeg.Progressive.Bad.BadEOF, - TestImages.Jpeg.Issues.BadCoeffsProgressive178 + TestImages.Jpeg.Issues.BadCoeffsProgressive178, + TestImages.Jpeg.Issues.MissingFF00ProgressiveGirl159, }; public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.RgbaVector;