diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
index 39ee6687b..44eb01a6d 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
@@ -16,16 +16,6 @@ namespace ImageSharp.Formats.Jpg
///
internal unsafe struct JpegScanDecoder
{
- ///
- /// Number of MCU-s (Minimum Coded Units) in the image along the X axis
- ///
- public int XNumberOfMCUs;
-
- ///
- /// Number of MCU-s (Minimum Coded Units) in the image along the Y axis
- ///
- public int YNumberOfMCUs;
-
///
/// The AC table index
///
@@ -77,7 +67,7 @@ namespace ImageSharp.Formats.Jpg
private int ah;
///
- /// Successive approximation high and low value
+ /// Successive approximation low value
///
private int al;
@@ -124,9 +114,9 @@ namespace ImageSharp.Formats.Jpg
int mcu = 0;
byte expectedRst = JpegConstants.Markers.RST0;
- for (int my = 0; my < this.YNumberOfMCUs; my++)
+ for (int my = 0; my < decoder.MCUCountY; my++)
{
- for (int mx = 0; mx < this.XNumberOfMCUs; mx++)
+ for (int mx = 0; mx < decoder.MCUCountX; mx++)
{
for (int i = 0; i < this.componentScanCount; i++)
{
@@ -165,7 +155,7 @@ namespace ImageSharp.Formats.Jpg
}
else
{
- int q = this.XNumberOfMCUs * hi;
+ int q = decoder.MCUCountX * hi;
this.bx = blockCount % q;
this.by = blockCount / q;
blockCount++;
@@ -183,7 +173,7 @@ namespace ImageSharp.Formats.Jpg
// Load the previous partially decoded coefficients, if applicable.
if (decoder.IsProgressive)
{
- int blockIndex = ((this.by * this.XNumberOfMCUs) * hi) + this.bx;
+ int blockIndex = ((this.by * decoder.MCUCountX) * hi) + this.bx;
this.data.Block = decoder.ProgCoeffs[compIndex][blockIndex];
}
else
@@ -200,7 +190,7 @@ namespace ImageSharp.Formats.Jpg
// for i
mcu++;
- if (decoder.RestartInterval > 0 && mcu % decoder.RestartInterval == 0 && mcu < this.XNumberOfMCUs * this.YNumberOfMCUs)
+ if (decoder.RestartInterval > 0 && mcu % decoder.RestartInterval == 0 && mcu < decoder.TotalMCUCount)
{
// 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.
@@ -302,12 +292,6 @@ namespace ImageSharp.Formats.Jpg
}
}
- // XNumberOfMCUs and YNumberOfMCUs are the number of MCUs (Minimum Coded Units) in the image.
- int h0 = decoder.ComponentArray[0].HorizontalFactor;
- int v0 = decoder.ComponentArray[0].VerticalFactor;
- this.XNumberOfMCUs = (decoder.ImageWidth + (8 * h0) - 1) / (8 * h0);
- this.YNumberOfMCUs = (decoder.ImageHeight + (8 * v0) - 1) / (8 * v0);
-
if (decoder.IsProgressive)
{
for (int i = 0; i < this.componentScanCount; i++)
@@ -315,8 +299,9 @@ namespace ImageSharp.Formats.Jpg
int compIndex = this.pointers.Scan[i].Index;
if (decoder.ProgCoeffs[compIndex] == null)
{
- int size = this.XNumberOfMCUs * this.YNumberOfMCUs * decoder.ComponentArray[compIndex].HorizontalFactor
- * decoder.ComponentArray[compIndex].VerticalFactor;
+ int size = decoder.TotalMCUCount
+ * decoder.ComponentArray[compIndex].HorizontalFactor
+ * decoder.ComponentArray[compIndex].VerticalFactor;
decoder.ProgCoeffs[compIndex] = new Block8x8F[size];
}
@@ -414,7 +399,7 @@ namespace ImageSharp.Formats.Jpg
{
// We haven't completely decoded this 8x8 block. Save the coefficients.
// this.ProgCoeffs[compIndex][((@by * XNumberOfMCUs) * hi) + bx] = b.Clone();
- decoder.ProgCoeffs[compIndex][((this.by * this.XNumberOfMCUs) * hi) + this.bx] = *b;
+ decoder.ProgCoeffs[compIndex][((this.by * decoder.MCUCountX) * hi) + this.bx] = *b;
// At this point, we could execute the rest of the loop body to dequantize and
// perform the inverse DCT, to save early stages of a progressive image to the
diff --git a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
index 2dd547c91..451420ad5 100644
--- a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
@@ -166,6 +166,21 @@ namespace ImageSharp.Formats
///
public int RestartInterval { get; private set; }
+ ///
+ /// Gets the number of MCU-s (Minimum Coded Units) in the image along the X axis
+ ///
+ public int MCUCountX { get; private set; }
+
+ ///
+ /// Gets the number of MCU-s (Minimum Coded Units) in the image along the Y axis
+ ///
+ public int MCUCountY { get; private set; }
+
+ ///
+ /// Gets the the total number of MCU-s (Minimum Coded Units) in the image.
+ ///
+ public int TotalMCUCount => this.MCUCountX * this.MCUCountY;
+
///
/// Decodes the image from the specified this._stream and sets
/// the data to image.
@@ -871,9 +886,7 @@ namespace ImageSharp.Formats
///
/// Makes the image from the buffer.
///
- /// The horizontal MCU count
- /// The vertical MCU count
- private void MakeImage(int mxx, int myy)
+ private void MakeImage()
{
if (this.grayImage.IsInitialized || this.ycbcrImage != null)
{
@@ -882,7 +895,7 @@ namespace ImageSharp.Formats
if (this.ComponentCount == 1)
{
- this.grayImage = JpegPixelArea.CreatePooled(8 * mxx, 8 * myy);
+ this.grayImage = JpegPixelArea.CreatePooled(8 * this.MCUCountX, 8 * this.MCUCountY);
}
else
{
@@ -914,14 +927,14 @@ namespace ImageSharp.Formats
break;
}
- this.ycbcrImage = new YCbCrImage(8 * h0 * mxx, 8 * v0 * myy, ratio);
+ this.ycbcrImage = new YCbCrImage(8 * h0 * this.MCUCountX, 8 * v0 * this.MCUCountY, ratio);
if (this.ComponentCount == 4)
{
int h3 = this.ComponentArray[3].HorizontalFactor;
int v3 = this.ComponentArray[3].VerticalFactor;
- this.blackImage = JpegPixelArea.CreatePooled(8 * h3 * mxx, 8 * v3 * myy);
+ this.blackImage = JpegPixelArea.CreatePooled(8 * h3 * this.MCUCountX, 8 * v3 * this.MCUCountY);
}
}
}
@@ -1390,6 +1403,11 @@ namespace ImageSharp.Formats
this.ComponentArray[i].HorizontalFactor = h;
this.ComponentArray[i].VerticalFactor = v;
}
+
+ int h0 = this.ComponentArray[0].HorizontalFactor;
+ int v0 = this.ComponentArray[0].VerticalFactor;
+ this.MCUCountX = (this.ImageWidth + (8 * h0) - 1) / (8 * h0);
+ this.MCUCountY = (this.ImageHeight + (8 * v0) - 1) / (8 * v0);
}
///
@@ -1405,7 +1423,7 @@ namespace ImageSharp.Formats
JpegScanDecoder scan = default(JpegScanDecoder);
JpegScanDecoder.Init(&scan, this, remaining);
this.Bits = default(Bits);
- this.MakeImage(scan.XNumberOfMCUs, scan.YNumberOfMCUs);
+ this.MakeImage();
scan.ProcessBlocks(this);
}