diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs index 83406e0d6..9eafaea0a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs @@ -71,16 +71,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// Invoke for block rows, copy the result into . /// - public void CopyBlocksToColorBuffer() + public void CopyBlocksToColorBuffer(int step) { var blockPp = new JpegBlockPostProcessor(this.RawJpeg, this.Component); float maximumValue = MathF.Pow(2, this.RawJpeg.Precision) - 1; int destAreaStride = this.ColorBuffer.Width; + int yBlockStart = step * this.BlockRowsPerStep; + for (int y = 0; y < this.BlockRowsPerStep; y++) { - int yBlock = this.currentComponentRowInBlocks + y; + int yBlock = yBlockStart + y; if (yBlock >= this.SizeInBlocks.Height) { @@ -104,7 +106,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder blockPp.ProcessBlockColorsInto(ref block, ref destAreaOrigin, destAreaStride, maximumValue); } } + } + public void CopyBlocksToColorBuffer() + { + this.CopyBlocksToColorBuffer(this.currentComponentRowInBlocks); this.currentComponentRowInBlocks += this.BlockRowsPerStep; } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index ec1c057b2..16a55e95e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { public abstract void InjectFrameData(JpegFrame frame, IRawJpegData jpegData); - public abstract void ConvertStride(); + public abstract void ConvertStride(int step); public abstract void Dispose(); } @@ -44,8 +44,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private int PixelRowsPerStep; - private int PixelRowCounter; - private bool converted; @@ -55,10 +53,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { if (!this.converted) { - while (this.PixelRowCounter < this.pixelBuffer.Height) + int steps = (int)Math.Ceiling(this.pixelBuffer.Height / (float)this.PixelRowsPerStep); + + for (int i = 0; i < steps; i++) { this.cancellationToken.ThrowIfCancellationRequested(); - this.ConvertStride(); + this.ConvertStride(i); } this.converted = true; @@ -103,20 +103,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.colorConverter = JpegColorConverter.GetConverter(jpegData.ColorSpace, frame.Precision); } - public override void ConvertStride() + public override void ConvertStride(int step) { - int maxY = Math.Min(this.pixelBuffer.Height, this.PixelRowCounter + this.PixelRowsPerStep); + int pixelRowStart = this.PixelRowsPerStep * step; + + int maxY = Math.Min(this.pixelBuffer.Height, pixelRowStart + this.PixelRowsPerStep); var buffers = new Buffer2D[this.componentProcessors.Length]; for (int i = 0; i < this.componentProcessors.Length; i++) { - this.componentProcessors[i].CopyBlocksToColorBuffer(); + this.componentProcessors[i].CopyBlocksToColorBuffer(step); buffers[i] = this.componentProcessors[i].ColorBuffer; } - for (int yy = this.PixelRowCounter; yy < maxY; yy++) + for (int yy = pixelRowStart; yy < maxY; yy++) { - int y = yy - this.PixelRowCounter; + int y = yy - pixelRowStart; var values = new JpegColorConverter.ComponentValues(buffers, y); this.colorConverter.ConvertToRgba(values, this.rgbaBuffer.GetSpan()); @@ -126,8 +128,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // TODO: Investigate if slicing is actually necessary PixelOperations.Instance.FromVector4Destructive(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); } - - this.PixelRowCounter += this.PixelRowsPerStep; } public override void Dispose()