diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index eb6991e6a..82df7304e 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileWuQuantizer() where TPixel : struct, IPixel { - var test = new WuFrameQuantizer(new WuQuantizer(false)); + var test = new WuFrameQuantizer(Configuration.Default.MemoryAllocator, new WuQuantizer(false)); test.QuantizeFrame(new ImageFrame(Configuration.Default, 1, 1)); test.AotGetPalette(); } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 9270bb6b1..ac9757094 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.Formats.Gif using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); - } + } } } } diff --git a/src/ImageSharp/Formats/Gif/LzwEncoder.cs b/src/ImageSharp/Formats/Gif/LzwEncoder.cs index 2d32fd23a..b4c80a3da 100644 --- a/src/ImageSharp/Formats/Gif/LzwEncoder.cs +++ b/src/ImageSharp/Formats/Gif/LzwEncoder.cs @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The span of indexed pixels. /// The stream to write to. - public void Encode(Span indexedPixels, Stream stream) + public void Encode(ReadOnlySpan indexedPixels, Stream stream) { // Write "initial code size" byte stream.WriteByte((byte)this.initialCodeSize); @@ -251,7 +251,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The span of indexed pixels. /// The initial bits. /// The stream to write to. - private void Compress(Span indexedPixels, int intialBits, Stream stream) + private void Compress(ReadOnlySpan indexedPixels, int intialBits, Stream stream) { int fcode; int c; @@ -375,7 +375,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int NextPixel(Span indexedPixels) + private int NextPixel(ReadOnlySpan indexedPixels) { return indexedPixels[this.position++] & 0xFF; } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index db0c7f258..7bdced536 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -676,7 +676,7 @@ namespace SixLabors.ImageSharp.Formats.Png { ref byte colorTableRef = ref MemoryMarshal.GetReference(colorTable.GetSpan()); ref byte alphaTableRef = ref MemoryMarshal.GetReference(alphaTable.GetSpan()); - Span quantizedSpan = quantized.GetPixelSpan(); + ReadOnlySpan quantizedSpan = quantized.GetPixelSpan(); Rgba32 rgba = default; diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs index eac31b21d..d753b08a8 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - public virtual QuantizedFrame QuantizeFrame(ImageFrame image) + public QuantizedFrame QuantizeFrame(ImageFrame image) { Guard.NotNull(image, nameof(image)); @@ -112,17 +112,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette); + Span pixelSpan = quantizedFrame.GetWritablePixelSpan(); if (this.Dither) { // We clone the image as we don't want to alter the original via dithering. using (ImageFrame clone = image.Clone()) { - this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette.Span, width, height); + this.SecondPass(clone, pixelSpan, palette.Span, width, height); } } else { - this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette.Span, width, height); + this.SecondPass(image, pixelSpan, palette.Span, width, height); } return quantizedFrame; diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs index 4f134d98d..21071dd8a 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization ReadOnlySpan quantizedPixelSpan = quantized.GetPixelSpan(); ReadOnlySpan paletteSpan = quantized.Palette.Span; - + int yy = y * source.Width; for (int x = 0; x < source.Width; x++) diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs index ae5b5dda8..a4d06ac2e 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The image width. /// The image height. /// The color palette. - public QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory palette) + internal QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory palette) { Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The [MethodImpl(InliningOptions.ShortMethod)] - public Span GetPixelSpan() => this.pixels.GetSpan(); + public ReadOnlySpan GetPixelSpan() => this.pixels.GetSpan(); /// /// Gets the representation of the pixels as a of contiguous memory @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The row. /// The [MethodImpl(InliningOptions.ShortMethod)] - public Span GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); + public ReadOnlySpan GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); /// public void Dispose() @@ -76,5 +76,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.pixels = null; this.Palette = null; } + + /// + /// Get the non-readonly span of pixel data so can fill it. + /// + internal Span GetWritablePixelSpan() => this.pixels.GetSpan(); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs index 95918f564..2b1a24aee 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs @@ -120,33 +120,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// + /// The . /// The wu quantizer /// /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, /// the second pass quantizes a color based on the position in the histogram. /// - public WuFrameQuantizer(WuQuantizer quantizer) - : this(quantizer, quantizer.MaxColors) + public WuFrameQuantizer(MemoryAllocator memoryAllocator, WuQuantizer quantizer) + : this(memoryAllocator, quantizer, quantizer.MaxColors) { } /// /// Initializes a new instance of the class. /// + /// The . /// The wu quantizer. /// The maximum number of colors to hold in the color palette. /// /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, /// the second pass quantizes a color based on the position in the histogram. /// - public WuFrameQuantizer(WuQuantizer quantizer, int maxColors) - : base(quantizer, false) => this.colors = maxColors; - - /// - public override QuantizedFrame QuantizeFrame(ImageFrame image) + public WuFrameQuantizer(MemoryAllocator memoryAllocator, WuQuantizer quantizer, int maxColors) + : base(quantizer, false) { - Guard.NotNull(image, nameof(image)); - MemoryAllocator memoryAllocator = image.MemoryAllocator; + Guard.NotNull(memoryAllocator, nameof(memoryAllocator)); this.vwt = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); this.vmr = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); @@ -156,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.m2 = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); this.tag = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - return base.QuantizeFrame(image); + this.colors = maxColors; } /// @@ -169,6 +167,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.vma?.Dispose(); this.m2?.Dispose(); this.tag?.Dispose(); + + this.vwt = null; + this.vmr = null; + this.vmg = null; + this.vmb = null; + this.vma = null; + this.m2 = null; + this.tag = null; } internal ReadOnlyMemory AotGetPalette() => this.GetPalette(); diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs index eb8b0fec9..b80cedeb3 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs @@ -72,14 +72,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// public IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel - => new WuFrameQuantizer(this); + { + Guard.NotNull(configuration, nameof(configuration)); + return new WuFrameQuantizer(configuration.MemoryAllocator, this); + } /// public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) where TPixel : struct, IPixel { + Guard.NotNull(configuration, nameof(configuration)); maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); - return new WuFrameQuantizer(this, maxColors); + return new WuFrameQuantizer(configuration.MemoryAllocator, this, maxColors); } private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null;