Browse Source

MCU counters refactored to JpegDecoderCore from JpegScanDecoder

af/merge-core
Anton Firszov 9 years ago
parent
commit
f7f0455b24
  1. 35
      src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
  2. 32
      src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs

35
src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs

@ -16,16 +16,6 @@ namespace ImageSharp.Formats.Jpg
/// </summary>
internal unsafe struct JpegScanDecoder
{
/// <summary>
/// Number of MCU-s (Minimum Coded Units) in the image along the X axis
/// </summary>
public int XNumberOfMCUs;
/// <summary>
/// Number of MCU-s (Minimum Coded Units) in the image along the Y axis
/// </summary>
public int YNumberOfMCUs;
/// <summary>
/// The AC table index
/// </summary>
@ -77,7 +67,7 @@ namespace ImageSharp.Formats.Jpg
private int ah;
/// <summary>
/// Successive approximation high and low value
/// Successive approximation low value
/// </summary>
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

32
src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs

@ -166,6 +166,21 @@ namespace ImageSharp.Formats
/// </summary>
public int RestartInterval { get; private set; }
/// <summary>
/// Gets the number of MCU-s (Minimum Coded Units) in the image along the X axis
/// </summary>
public int MCUCountX { get; private set; }
/// <summary>
/// Gets the number of MCU-s (Minimum Coded Units) in the image along the Y axis
/// </summary>
public int MCUCountY { get; private set; }
/// <summary>
/// Gets the the total number of MCU-s (Minimum Coded Units) in the image.
/// </summary>
public int TotalMCUCount => this.MCUCountX * this.MCUCountY;
/// <summary>
/// Decodes the image from the specified this._stream and sets
/// the data to image.
@ -871,9 +886,7 @@ namespace ImageSharp.Formats
/// <summary>
/// Makes the image from the buffer.
/// </summary>
/// <param name="mxx">The horizontal MCU count</param>
/// <param name="myy">The vertical MCU count</param>
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);
}
/// <summary>
@ -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);
}

Loading…
Cancel
Save