Browse Source

ErrorCode is now a state of InputProcessor

pull/322/head
Anton Firszov 9 years ago
parent
commit
b75481b849
  1. 84
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
  2. 61
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
  3. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  4. 4
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

84
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;
}
/// <summary>
@ -48,48 +48,48 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
public byte[] Temp { get; }
/// <summary>
/// Gets or sets a value indicating whether an unexpected EOF reached in <see cref="InputStream"/>.
/// Gets a value indicating whether an unexpected EOF reached in <see cref="InputStream"/>.
/// </summary>
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;
/// <summary>
/// If errorCode indicates unexpected EOF, sets <see cref="UnexpectedEndOfStreamReached"/> to true and returns false.
/// If errorCode indicates unexpected EOF, sets <see cref="ReachedEOF"/> to true and returns false.
/// Calls <see cref="DecoderThrowHelper.EnsureNoError"/> and returns true otherwise.
/// </summary>
/// <param name="errorCode">The <see cref="OrigDecoderErrorCode"/></param>
/// <returns><see cref="bool"/> indicating whether everything is OK</returns>
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;
}
/// <summary>
/// If errorCode indicates unexpected EOF, sets <see cref="UnexpectedEndOfStreamReached"/> to true and returns false.
/// If errorCode indicates unexpected EOF, sets <see cref="ReachedEOF"/> to true and returns false.
/// Returns true otherwise.
/// </summary>
/// <param name="errorCode">The <see cref="OrigDecoderErrorCode"/></param>
/// <returns><see cref="bool"/> indicating whether everything is OK</returns>
public bool CheckEOF(OrigDecoderErrorCode errorCode)
public bool CheckEOF()
{
if (errorCode == OrigDecoderErrorCode.UnexpectedEndOfStream)
if (this.LastErrorCode == OrigDecoderErrorCode.UnexpectedEndOfStream)
{
this.UnexpectedEndOfStreamReached = true;
return false;
}
return true;
}
/// <summary>
/// Dispose
/// </summary>
/// <inheritdoc />
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;
}
/// <summary>
@ -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;
}
/// <summary>
@ -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;
}
/// <summary>
@ -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();
}
/// <summary>
@ -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;
}
/// <summary>
@ -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();
}
/// <summary>
@ -360,7 +365,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// <returns>The <see cref="OrigDecoderErrorCode"/></returns>
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;
}
}
}

61
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;
}
/// <summary>
@ -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;
}

2
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;

4
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;

Loading…
Cancel
Save