|
|
|
@ -67,14 +67,10 @@ namespace ImageSharp.Formats.Jpg |
|
|
|
/// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="inputStream">Input stream</param>
|
|
|
|
/// <param name="errorCode">Error code</param>
|
|
|
|
/// <returns>The <see cref="byte"/></returns>
|
|
|
|
internal byte ReadByteStuffedByte(Stream inputStream, out DecoderErrorCode errorCode) |
|
|
|
/// <param name="x">The result <see cref="byte"/></param>
|
|
|
|
/// <returns>The <see cref="DecoderErrorCode"/></returns>
|
|
|
|
public DecoderErrorCode ReadByteStuffedByteUnsafe(Stream inputStream, out byte x) |
|
|
|
{ |
|
|
|
byte x; |
|
|
|
|
|
|
|
errorCode = DecoderErrorCode.NoError; |
|
|
|
|
|
|
|
// Take the fast path if bytes.buf contains at least two bytes.
|
|
|
|
if (this.I + 2 <= this.J) |
|
|
|
{ |
|
|
|
@ -83,42 +79,46 @@ namespace ImageSharp.Formats.Jpg |
|
|
|
this.UnreadableBytes = 1; |
|
|
|
if (x != JpegConstants.Markers.XFF) |
|
|
|
{ |
|
|
|
return x; |
|
|
|
return DecoderErrorCode.NoError; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.Buffer[this.I] != 0x00) |
|
|
|
{ |
|
|
|
errorCode = DecoderErrorCode.MissingFF00; |
|
|
|
return 0; |
|
|
|
|
|
|
|
// throw new MissingFF00Exception();
|
|
|
|
return DecoderErrorCode.MissingFF00; |
|
|
|
} |
|
|
|
|
|
|
|
this.I++; |
|
|
|
this.UnreadableBytes = 2; |
|
|
|
return JpegConstants.Markers.XFF; |
|
|
|
x = JpegConstants.Markers.XFF; |
|
|
|
return DecoderErrorCode.NoError; |
|
|
|
} |
|
|
|
|
|
|
|
this.UnreadableBytes = 0; |
|
|
|
|
|
|
|
x = this.ReadByte(inputStream); |
|
|
|
DecoderErrorCode errorCode = this.ReadByteUnsafe(inputStream, out x); |
|
|
|
this.UnreadableBytes = 1; |
|
|
|
if (errorCode != DecoderErrorCode.NoError) |
|
|
|
{ |
|
|
|
return errorCode; |
|
|
|
} |
|
|
|
if (x != JpegConstants.Markers.XFF) |
|
|
|
{ |
|
|
|
return x; |
|
|
|
return DecoderErrorCode.NoError; |
|
|
|
} |
|
|
|
|
|
|
|
x = this.ReadByte(inputStream); |
|
|
|
errorCode = this.ReadByteUnsafe(inputStream, out x); |
|
|
|
this.UnreadableBytes = 2; |
|
|
|
if (errorCode != DecoderErrorCode.NoError) |
|
|
|
{ |
|
|
|
return errorCode; |
|
|
|
} |
|
|
|
if (x != 0x00) |
|
|
|
{ |
|
|
|
errorCode = DecoderErrorCode.MissingFF00; |
|
|
|
return 0; |
|
|
|
|
|
|
|
// throw new MissingFF00Exception();
|
|
|
|
return DecoderErrorCode.MissingFF00; |
|
|
|
} |
|
|
|
|
|
|
|
return JpegConstants.Markers.XFF; |
|
|
|
x = JpegConstants.Markers.XFF; |
|
|
|
return DecoderErrorCode.NoError; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -127,30 +127,68 @@ namespace ImageSharp.Formats.Jpg |
|
|
|
/// <param name="inputStream">Input stream</param>
|
|
|
|
/// <returns>The <see cref="byte"/></returns>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
internal byte ReadByte(Stream inputStream) |
|
|
|
public byte ReadByte(Stream inputStream) |
|
|
|
{ |
|
|
|
byte result; |
|
|
|
DecoderErrorCode errorCode = this.ReadByteUnsafe(inputStream, out result); |
|
|
|
errorCode.EnsureNoError(); |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Extracts the next byte, whether buffered or not buffered into the result out parameter. It does not care about byte stuffing.
|
|
|
|
/// This method does not throw on format error, it returns a <see cref="DecoderErrorCode"/> instead.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="inputStream">Input stream</param>
|
|
|
|
/// <param name="result">The result <see cref="byte"/> as out parameter</param>
|
|
|
|
/// <returns>The <see cref="DecoderErrorCode"/></returns>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public DecoderErrorCode ReadByteUnsafe(Stream inputStream, out byte result) |
|
|
|
{ |
|
|
|
DecoderErrorCode errorCode = DecoderErrorCode.NoError; |
|
|
|
while (this.I == this.J) |
|
|
|
{ |
|
|
|
this.Fill(inputStream); |
|
|
|
errorCode = this.FillUnsafe(inputStream); |
|
|
|
if (errorCode != DecoderErrorCode.NoError) |
|
|
|
{ |
|
|
|
result = 0; |
|
|
|
return errorCode; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
byte x = this.Buffer[this.I]; |
|
|
|
result = this.Buffer[this.I]; |
|
|
|
this.I++; |
|
|
|
this.UnreadableBytes = 0; |
|
|
|
return x; |
|
|
|
return errorCode; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Fills up the bytes buffer from the underlying stream.
|
|
|
|
/// It should only be called when there are no unread bytes in bytes.
|
|
|
|
/// </summary>
|
|
|
|
/// <exception cref="EOFException">Thrown when reached end of stream unexpectedly.</exception>
|
|
|
|
/// <param name="inputStream">Input stream</param>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public void Fill(Stream inputStream) |
|
|
|
{ |
|
|
|
DecoderErrorCode errorCode = this.FillUnsafe(inputStream); |
|
|
|
errorCode.EnsureNoError(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Fills up the bytes buffer from the underlying stream.
|
|
|
|
/// It should only be called when there are no unread bytes in bytes.
|
|
|
|
/// This method does not throw <see cref="EOFException"/>, returns a <see cref="DecoderErrorCode"/> instead!
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="inputStream">Input stream</param>
|
|
|
|
/// <returns>The <see cref="DecoderErrorCode"/></returns>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
internal void Fill(Stream inputStream) |
|
|
|
public DecoderErrorCode FillUnsafe(Stream inputStream) |
|
|
|
{ |
|
|
|
if (this.I != this.J) |
|
|
|
{ |
|
|
|
throw new ImageFormatException("Fill called when unread bytes exist."); |
|
|
|
// Unrecoverable error in the input, throwing!
|
|
|
|
DecoderThrowHelper.ThrowImageFormatException.FillCalledWhenUnreadBytesExist(); |
|
|
|
} |
|
|
|
|
|
|
|
// Move the last 2 bytes to the start of the buffer, in case we need
|
|
|
|
@ -167,10 +205,11 @@ namespace ImageSharp.Formats.Jpg |
|
|
|
int n = inputStream.Read(this.Buffer, this.J, this.Buffer.Length - this.J); |
|
|
|
if (n == 0) |
|
|
|
{ |
|
|
|
throw new EOFException(); |
|
|
|
return DecoderErrorCode.UnexpectedEndOfStream; |
|
|
|
} |
|
|
|
|
|
|
|
this.J += n; |
|
|
|
return DecoderErrorCode.NoError; |
|
|
|
} |
|
|
|
} |
|
|
|
} |