From 614741fa6ddcd4237bf903f12d7d3d053b4b0b44 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 12 Feb 2020 11:27:03 +1100 Subject: [PATCH] Update QuantizeProcessor{TPixel}.cs --- .../Quantization/QuantizeProcessor{TPixel}.cs | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs index 5e732982c..276919d60 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -2,8 +2,9 @@ // Licensed under the Apache License, Version 2.0. using System; - +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Quantization @@ -35,27 +36,50 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization protected override void OnFrameApply(ImageFrame source) { Configuration configuration = this.Configuration; - using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(configuration)) - using (IQuantizedFrame quantized = frameQuantizer.QuantizeFrame(source)) - { - int paletteCount = quantized.Palette.Length - 1; + using IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(configuration); + using IQuantizedFrame quantized = frameQuantizer.QuantizeFrame(source); - // Not parallel to remove "quantized" closure allocation. - // We can operate directly on the source here as we've already read it to get the - // quantized result - for (int y = 0; y < source.Height; y++) - { - Span row = source.GetPixelRowSpan(y); - ReadOnlySpan quantizedPixelSpan = quantized.GetPixelSpan(); + var operation = new RowIntervalOperation(this.SourceRectangle, source, quantized); + ParallelRowIterator.IterateRows( + configuration, + this.SourceRectangle, + in operation); + } - ReadOnlySpan paletteSpan = quantized.Palette.Span; + private readonly struct RowIntervalOperation : IRowIntervalOperation + { + private readonly Rectangle bounds; + private readonly ImageFrame source; + private readonly IQuantizedFrame quantized; + private readonly int maxPaletteIndex; - int yy = y * source.Width; + [MethodImpl(InliningOptions.ShortMethod)] + public RowIntervalOperation( + Rectangle bounds, + ImageFrame source, + IQuantizedFrame quantized) + { + this.bounds = bounds; + this.source = source; + this.quantized = quantized; + this.maxPaletteIndex = quantized.Palette.Length - 1; + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void Invoke(in RowInterval rows) + { + ReadOnlySpan quantizedPixelSpan = this.quantized.GetPixelSpan(); + ReadOnlySpan paletteSpan = this.quantized.Palette.Span; + + for (int y = rows.Min; y < rows.Max; y++) + { + Span row = this.source.GetPixelRowSpan(y); + int yy = y * this.bounds.Width; - for (int x = 0; x < source.Width; x++) + for (int x = this.bounds.X; x < this.bounds.Right; x++) { int i = x + yy; - row[x] = paletteSpan[Math.Min(paletteCount, quantizedPixelSpan[i])]; + row[x] = paletteSpan[Math.Min(this.maxPaletteIndex, quantizedPixelSpan[i])]; } } }