From f7f0455b24c8b249ff8310af4ff4d0d2282f22d1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 22 Jan 2017 02:08:30 +0100 Subject: [PATCH] MCU counters refactored to JpegDecoderCore from JpegScanDecoder --- .../Components/Decoder/JpegScanDecoder.cs | 35 ++++++------------- .../JpegDecoderCore.cs | 32 +++++++++++++---- 2 files changed, 35 insertions(+), 32 deletions(-) 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); }