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> /// </summary>
internal unsafe struct JpegScanDecoder 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> /// <summary>
/// The AC table index /// The AC table index
/// </summary> /// </summary>
@ -77,7 +67,7 @@ namespace ImageSharp.Formats.Jpg
private int ah; private int ah;
/// <summary> /// <summary>
/// Successive approximation high and low value /// Successive approximation low value
/// </summary> /// </summary>
private int al; private int al;
@ -124,9 +114,9 @@ namespace ImageSharp.Formats.Jpg
int mcu = 0; int mcu = 0;
byte expectedRst = JpegConstants.Markers.RST0; 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++) for (int i = 0; i < this.componentScanCount; i++)
{ {
@ -165,7 +155,7 @@ namespace ImageSharp.Formats.Jpg
} }
else else
{ {
int q = this.XNumberOfMCUs * hi; int q = decoder.MCUCountX * hi;
this.bx = blockCount % q; this.bx = blockCount % q;
this.by = blockCount / q; this.by = blockCount / q;
blockCount++; blockCount++;
@ -183,7 +173,7 @@ namespace ImageSharp.Formats.Jpg
// Load the previous partially decoded coefficients, if applicable. // Load the previous partially decoded coefficients, if applicable.
if (decoder.IsProgressive) 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]; this.data.Block = decoder.ProgCoeffs[compIndex][blockIndex];
} }
else else
@ -200,7 +190,7 @@ namespace ImageSharp.Formats.Jpg
// for i // for i
mcu++; 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, // 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. // 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) if (decoder.IsProgressive)
{ {
for (int i = 0; i < this.componentScanCount; i++) for (int i = 0; i < this.componentScanCount; i++)
@ -315,8 +299,9 @@ namespace ImageSharp.Formats.Jpg
int compIndex = this.pointers.Scan[i].Index; int compIndex = this.pointers.Scan[i].Index;
if (decoder.ProgCoeffs[compIndex] == null) if (decoder.ProgCoeffs[compIndex] == null)
{ {
int size = this.XNumberOfMCUs * this.YNumberOfMCUs * decoder.ComponentArray[compIndex].HorizontalFactor int size = decoder.TotalMCUCount
* decoder.ComponentArray[compIndex].VerticalFactor; * decoder.ComponentArray[compIndex].HorizontalFactor
* decoder.ComponentArray[compIndex].VerticalFactor;
decoder.ProgCoeffs[compIndex] = new Block8x8F[size]; 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. // We haven't completely decoded this 8x8 block. Save the coefficients.
// this.ProgCoeffs[compIndex][((@by * XNumberOfMCUs) * hi) + bx] = b.Clone(); // 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 // 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 // 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> /// </summary>
public int RestartInterval { get; private set; } 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> /// <summary>
/// Decodes the image from the specified this._stream and sets /// Decodes the image from the specified this._stream and sets
/// the data to image. /// the data to image.
@ -871,9 +886,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Makes the image from the buffer. /// Makes the image from the buffer.
/// </summary> /// </summary>
/// <param name="mxx">The horizontal MCU count</param> private void MakeImage()
/// <param name="myy">The vertical MCU count</param>
private void MakeImage(int mxx, int myy)
{ {
if (this.grayImage.IsInitialized || this.ycbcrImage != null) if (this.grayImage.IsInitialized || this.ycbcrImage != null)
{ {
@ -882,7 +895,7 @@ namespace ImageSharp.Formats
if (this.ComponentCount == 1) if (this.ComponentCount == 1)
{ {
this.grayImage = JpegPixelArea.CreatePooled(8 * mxx, 8 * myy); this.grayImage = JpegPixelArea.CreatePooled(8 * this.MCUCountX, 8 * this.MCUCountY);
} }
else else
{ {
@ -914,14 +927,14 @@ namespace ImageSharp.Formats
break; 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) if (this.ComponentCount == 4)
{ {
int h3 = this.ComponentArray[3].HorizontalFactor; int h3 = this.ComponentArray[3].HorizontalFactor;
int v3 = this.ComponentArray[3].VerticalFactor; 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].HorizontalFactor = h;
this.ComponentArray[i].VerticalFactor = v; 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> /// <summary>
@ -1405,7 +1423,7 @@ namespace ImageSharp.Formats
JpegScanDecoder scan = default(JpegScanDecoder); JpegScanDecoder scan = default(JpegScanDecoder);
JpegScanDecoder.Init(&scan, this, remaining); JpegScanDecoder.Init(&scan, this, remaining);
this.Bits = default(Bits); this.Bits = default(Bits);
this.MakeImage(scan.XNumberOfMCUs, scan.YNumberOfMCUs); this.MakeImage();
scan.ProcessBlocks(this); scan.ProcessBlocks(this);
} }

Loading…
Cancel
Save