diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/Bits.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/Bits.cs
index 8e46e18066..f80e75b990 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/Bits.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/Bits.cs
@@ -37,9 +37,24 @@ namespace ImageSharp.Formats.Jpg
///
/// The number of bits to ensure.
/// Jpeg decoder
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void EnsureNBits(int n, JpegDecoderCore decoder)
+ {
+ DecoderErrorCode errorCode = this.EnsureNBitsUnsafe(n, decoder);
+ errorCode.EnsureNoError();
+ }
+
+ ///
+ /// 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 < n.
+ /// This method does not throw. Returns instead.
+ ///
+ /// The number of bits to ensure.
+ /// Jpeg decoder
/// Error code
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal DecoderErrorCode EnsureNBits(int n, JpegDecoderCore decoder)
+ public DecoderErrorCode EnsureNBitsUnsafe(int n, JpegDecoderCore decoder)
{
while (true)
{
@@ -84,8 +99,7 @@ namespace ImageSharp.Formats.Jpg
{
if (this.UnreadBits < t)
{
- DecoderErrorCode errorCode = this.EnsureNBits(t, decoder);
- errorCode.EnsureNoError();
+ this.EnsureNBits(t, decoder);
}
this.UnreadBits -= t;
diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/EOFException.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/EOFException.cs
index 81857b456c..b695e68123 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/EOFException.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/EOFException.cs
@@ -13,6 +13,9 @@ namespace ImageSharp.Formats.Jpg
///
internal class EOFException : Exception
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public EOFException()
: base("Reached end of stream before proceeding EOI marker!")
{
diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.ComputationData.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.ComputationData.cs
index ef04bf4188..06f170be5a 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.ComputationData.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.ComputationData.cs
@@ -13,7 +13,7 @@ namespace ImageSharp.Formats.Jpg
internal unsafe partial struct JpegScanDecoder
{
///
- /// Holds the "large" data blocks needed for computations
+ /// Holds the "large" data blocks needed for computations.
///
[StructLayout(LayoutKind.Sequential)]
public struct ComputationData
@@ -44,12 +44,12 @@ namespace ImageSharp.Formats.Jpg
public UnzigData Unzig;
///
- /// The no-idea-what's this data
+ /// The buffer storing the -s for each component
///
public fixed byte ScanData[3 * JpegDecoderCore.MaxComponents];
///
- /// The DC component values
+ /// The DC values for each component
///
public fixed int Dc[JpegDecoderCore.MaxComponents];
diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
index 8c2f079707..ef2ce18883 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
@@ -2,7 +2,6 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
// ReSharper disable InconsistentNaming
namespace ImageSharp.Formats.Jpg
{
@@ -10,8 +9,21 @@ namespace ImageSharp.Formats.Jpg
using System.Runtime.CompilerServices;
///
- /// Encapsulates the impementation of Jpeg SOS decoder.
- /// See JpegScanDecoder.md!
+ /// Encapsulates the impementation of Jpeg SOS decoder. See JpegScanDecoder.md!
+ /// and are the spectral selection bounds.
+ /// and are the successive approximation high and low values.
+ /// The spec calls these values Ss, Se, Ah and Al.
+ /// For progressive JPEGs, these are the two more-or-less independent
+ /// aspects of progression. Spectral selection progression is when not
+ /// all of a block's 64 DCT coefficients are transmitted in one pass.
+ /// For example, three passes could transmit coefficient 0 (the DC
+ /// component), coefficients 1-5, and coefficients 6-63, in zig-zag
+ /// order. Successive approximation is when not all of the bits of a
+ /// band of coefficients are transmitted in one pass. For example,
+ /// three passes could transmit the 6 most significant bits, followed
+ /// by the second-least significant bit, followed by the least
+ /// significant bit.
+ /// For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
///
internal unsafe partial struct JpegScanDecoder
{
@@ -35,21 +47,6 @@ namespace ImageSharp.Formats.Jpg
///
private int by;
- // zigStart and zigEnd are the spectral selection bounds.
- // ah and al are the successive approximation high and low values.
- // The spec calls these values Ss, Se, Ah and Al.
- // For progressive JPEGs, these are the two more-or-less independent
- // aspects of progression. Spectral selection progression is when not
- // all of a block's 64 DCT coefficients are transmitted in one pass.
- // For example, three passes could transmit coefficient 0 (the DC
- // component), coefficients 1-5, and coefficients 6-63, in zig-zag
- // order. Successive approximation is when not all of the bits of a
- // band of coefficients are transmitted in one pass. For example,
- // three passes could transmit the 6 most significant bits, followed
- // by the second-least significant bit, followed by the least
- // significant bit.
- // For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
-
///
/// Start index of the zig-zag selection bound
///
@@ -91,14 +88,14 @@ namespace ImageSharp.Formats.Jpg
private ushort eobRun;
///
- /// The buffer
+ /// Pointers to elements of
///
- private ComputationData data;
+ private DataPointers pointers;
///
- /// Pointers to elements of
+ /// The buffer
///
- private DataPointers pointers;
+ private ComputationData data;
///
/// Initializes the default instance after creation.
@@ -320,7 +317,6 @@ namespace ImageSharp.Formats.Jpg
else
{
int zig = this.zigStart;
- DecoderErrorCode errorCode;
if (zig == 0)
{
zig++;
@@ -335,7 +331,6 @@ namespace ImageSharp.Formats.Jpg
}
int deltaDC = decoder.Bits.ReceiveExtend(value, decoder);
- // errorCode.EnsureNoError();
this.pointers.Dc[this.componentIndex] += deltaDC;
@@ -364,7 +359,6 @@ namespace ImageSharp.Formats.Jpg
}
int ac = decoder.Bits.ReceiveExtend(val1, decoder);
- // errorCode.EnsureNoError();
// b[Unzig[zig]] = ac << al;
Block8x8F.SetScalarAt(b, this.pointers.Unzig[zig], ac << this.al);
diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.md b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.md
index 215f21807b..4ca4d1f642 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.md
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.md
@@ -4,7 +4,7 @@ The implementation is optimized to hold most of the necessary data in a single v
#### Benefits:
- Maximized locality of reference by keeping most of the operation data on the stack
-- Reaching this without long parameter lists, most of the values describing the state of the decoder algorithm
+- Achieving this without long parameter lists, most of the values describing the state of the decoder algorithm
are members of the `JpegScanDecoder` struct
- Most of the logic related to Scan decoding is refactored & simplified now to live in the methods of `JpegScanDecoder`
- The first step is done towards separating the stream reading from block processing. They can be refactored later to be executed in two disctinct loops.
@@ -16,8 +16,8 @@ are members of the `JpegScanDecoder` struct
|JpegScanDecoder |
|-------------------|
|Variables |
-|ComputationData |
|DataPointers |
+|ComputationData |
- **ComputationData** holds the "large" data blocks needed for computations (Mostly `Block8x8F`-s)
- **DataPointers** contains pointers to the memory regions of `ComponentData` so they can be easily passed around to pointer based utility methods of `Block8x8F`
diff --git a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
index 3bb774b69e..aa5158395c 100644
--- a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
@@ -431,8 +431,7 @@ namespace ImageSharp.Formats
{
if (this.Bits.UnreadBits == 0)
{
- DecoderErrorCode errorCode = this.Bits.EnsureNBits(1, this);
- errorCode.EnsureNoError();
+ this.Bits.EnsureNBits(1, this);
}
bool ret = (this.Bits.Accumulator & this.Bits.Mask) != 0;
@@ -506,8 +505,7 @@ namespace ImageSharp.Formats
{
if (this.Bits.UnreadBits < count)
{
- DecoderErrorCode errorCode = this.Bits.EnsureNBits(count, this);
- errorCode.EnsureNoError();
+ this.Bits.EnsureNBits(count, this);
}
uint ret = this.Bits.Accumulator >> (this.Bits.UnreadBits - count);
@@ -532,7 +530,7 @@ namespace ImageSharp.Formats
if (this.Bits.UnreadBits < 8)
{
- DecoderErrorCode errorCode = this.Bits.EnsureNBits(8, this);
+ DecoderErrorCode errorCode = this.Bits.EnsureNBitsUnsafe(8, this);
if (errorCode == DecoderErrorCode.NoError)
{
@@ -561,8 +559,7 @@ namespace ImageSharp.Formats
{
if (this.Bits.UnreadBits == 0)
{
- DecoderErrorCode errorCode = this.Bits.EnsureNBits(1, this);
- errorCode.EnsureNoError();
+ this.Bits.EnsureNBits(1, this);
}
if ((this.Bits.Accumulator & this.Bits.Mask) != 0)