Browse Source

Reduce errors

pull/3153/head
winscripter 1 week ago
parent
commit
b8f4094a77
  1. 12
      src/ImageSharp/Formats/Jxl/Fields/JxlReadVisitor.cs
  2. 65
      src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlBitReader.cs
  3. 15
      src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlDecoderCore.cs

12
src/ImageSharp/Formats/Jxl/Fields/JxlReadVisitor.cs

@ -116,18 +116,6 @@ internal sealed class JxlReadVisitor(JxlBitReader reader) : JxlVisitorBase
reader.SkipBits64((uint)remainingBits);
}
return this.ThrowIfEndOfStreamOrReturnTrue();
}
private bool ThrowIfEndOfStreamOrReturnTrue()
{
if (reader.IsEndOfStream)
{
DebugGuard.IsTrue(false, "Got an invalid end-of-stream");
this.notEnoughBytes = true;
return true;
}
return true;
}
}

65
src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlBitReader.cs

@ -8,56 +8,61 @@ namespace SixLabors.ImageSharp.Formats.Jxl.Processing.Decoder;
/// <summary>
/// Represents a bitstream reader.
/// </summary>
internal ref struct JxlBitReader(ReadOnlySpan<byte> bytes)
internal sealed class JxlBitReader(Stream stream)
{
private readonly ReadOnlySpan<byte> data = bytes;
private ulong buffer;
private uint bufferRemainingBits;
private int pointer;
/// <summary>
/// Gets a value indicating whether this marks an end of stream.
/// </summary>
public bool IsEndOfStream { get; private set; }
/// <summary>
/// Gets the total number of bits consumed.
/// </summary>
public readonly long TotalBitsConsumed => ((long)this.pointer * 8) + (64 - this.bufferRemainingBits);
public long TotalBitsConsumed => ((long)this.pointer * 8) + (64 - this.bufferRemainingBits);
/// <summary>
/// Fetches a new buffer.
/// </summary>
private void RefillCore()
{
int remaining = this.data.Length - this.pointer;
if (remaining <= 0)
{
// we don't have any more data... mark an end of stream
this.buffer = 0;
this.bufferRemainingBits = 0;
this.IsEndOfStream = true;
return;
}
if (remaining >= 8)
Span<byte> temp = stackalloc byte[8];
int bytesRead = stream.Read(temp);
if (bytesRead == 8)
{
this.buffer = BinaryPrimitives.ReadUInt64LittleEndian(this.data[this.pointer..]);
this.buffer = BinaryPrimitives.ReadUInt64LittleEndian(temp);
this.bufferRemainingBits = 64u;
this.pointer += 8;
}
else
{
if (bytesRead == 0)
{
throw new EndOfStreamException();
}
ulong value = 0;
for (int i = 0; i < remaining; i++)
for (int i = 0; i < bytesRead; i++)
{
value |= (ulong)this.data[this.pointer + i] << (8 * i);
value |= (ulong)temp[i] << (8 * i);
}
this.buffer = value;
this.bufferRemainingBits = (uint)(remaining * 8);
this.pointer += remaining;
this.bufferRemainingBits = (uint)(bytesRead * 8);
this.pointer += bytesRead;
}
}
public void JumpToByteBoundary()
{
uint remainder = (uint)(this.TotalBitsConsumed % 8);
if (remainder == 0)
{
return;
}
if (this.ReadBits32(8u - remainder) != 0)
{
throw new InvalidDataException("Non-zero padding bits");
}
}
@ -74,11 +79,6 @@ internal ref struct JxlBitReader(ReadOnlySpan<byte> bytes)
DebugGuard.MustBeLessThanOrEqualTo(n, 64u, nameof(n));
this.MaybeRefill();
if (this.IsEndOfStream)
{
JxlThrowHelper.ThrowEndOfStream();
}
if (n <= this.bufferRemainingBits)
{
ulong result = this.buffer & ((1UL << (int)n) - 1);
@ -119,11 +119,6 @@ internal ref struct JxlBitReader(ReadOnlySpan<byte> bytes)
DebugGuard.MustBeLessThanOrEqualTo(n, 32u, nameof(n));
this.MaybeRefill();
if (this.IsEndOfStream)
{
JxlThrowHelper.ThrowEndOfStream();
}
if (n <= this.bufferRemainingBits)
{
uint result = (uint)(this.buffer & ((1UL << (int)n) - 1));

15
src/ImageSharp/Formats/Jxl/Processing/Decoder/JxlDecoderCore.cs

@ -1753,11 +1753,6 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
this.frameDecoder.InitializeFrame(reader, this.imageBundle!, this.previewFrame);
if (!reader.AllReadsWithinBounds)
{
return this.TryRequestMoreInput() ? 1 : 0;
}
this.AdvanceCodeStream(reader.TotalBitsConsumed / JxlMath.BitsPerByte);
this.frameHeader = this.frameDecoder.GetFrameHeader();
@ -2701,13 +2696,13 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
if (!this.gotSignature)
{
JxlSignatureCheck status = CheckSignature(this.nextInput, this.availableInput);
if (status == JxlSignatureCheck.InvalidSignature)
JxlSignature signature = DetectSignature(this.nextInput, this.availableInput);
if (signature == JxlSignature.Invalid)
{
throw new InvalidOperationException("The signature is invalid.");
}
if (status == JxlSignatureCheck.NotEnoughBytes)
if (signature == JxlSignature.NotEnoughBytes)
{
if (this.inputClosed)
{
@ -2719,7 +2714,7 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
this.gotSignature = true;
if (status == JxlSignatureCheck.Container)
if (signature == JxlSignature.Container)
{
this.haveContainer = true;
}
@ -2750,6 +2745,8 @@ internal sealed class JxlDecoderCore : ImageDecoderCore, IDisposable
}
}
private static void ThrowNotEnoughData() => throw new InvalidOperationException("Not enough data");
protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken) => throw new NotImplementedException();
protected override ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) => throw new NotImplementedException();

Loading…
Cancel
Save