diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 1b3e0228a..1b7d2e5be 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -360,7 +360,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp for (int y = image.Height - 1; y >= 0; y--) { - ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); + ReadOnlySpan pixelSpan = quantized.GetPixelRowSpan(y); stream.Write(pixelSpan); for (int i = 0; i < this.padding; i++) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 5f14d483b..f8226fc3f 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -380,7 +380,7 @@ namespace SixLabors.ImageSharp.Formats.Png if (this.bitDepth < 8) { - PngEncoderHelpers.ScaleDownFrom8BitArray(quantized.GetRowSpan(row), this.currentScanline.GetSpan(), this.bitDepth); + PngEncoderHelpers.ScaleDownFrom8BitArray(quantized.GetPixelRowSpan(row), this.currentScanline.GetSpan(), this.bitDepth); } else { @@ -987,7 +987,7 @@ namespace SixLabors.ImageSharp.Formats.Png row += Adam7.RowIncrement[pass]) { // collect data - ReadOnlySpan srcRow = quantized.GetRowSpan(row); + ReadOnlySpan srcRow = quantized.GetPixelRowSpan(row); for (int col = startCol, i = 0; col < width; col += Adam7.ColumnIncrement[pass]) diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs index 079a22ecc..2d7e138f4 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs @@ -89,29 +89,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering [MethodImpl(InliningOptions.ShortMethod)] public void ApplyQuantizationDither( ref TFrameQuantizer quantizer, - ReadOnlyMemory palette, ImageFrame source, - Memory output, + QuantizedFrame destination, Rectangle bounds) where TFrameQuantizer : struct, IFrameQuantizer where TPixel : struct, IPixel { - Span outputSpan = output.Span; - ReadOnlySpan paletteSpan = palette.Span; - int width = bounds.Width; + ReadOnlySpan paletteSpan = destination.Palette.Span; int offsetY = bounds.Top; int offsetX = bounds.Left; float scale = quantizer.Options.DitherScale; for (int y = bounds.Top; y < bounds.Bottom; y++) { - Span row = source.GetPixelRowSpan(y); - int rowStart = (y - offsetY) * width; + Span sourceRow = source.GetPixelRowSpan(y); + Span destinationRow = destination.GetPixelRowSpan(y - offsetY); for (int x = bounds.Left; x < bounds.Right; x++) { - TPixel sourcePixel = row[x]; - outputSpan[rowStart + x - offsetX] = quantizer.GetQuantizedColor(sourcePixel, paletteSpan, out TPixel transformed); + TPixel sourcePixel = sourceRow[x]; + destinationRow[x - offsetX] = quantizer.GetQuantizedColor(sourcePixel, paletteSpan, out TPixel transformed); this.Dither(source, bounds, sourcePixel, transformed, x, y, scale); } } @@ -119,23 +116,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// [MethodImpl(InliningOptions.ShortMethod)] - public void ApplyPaletteDither( - Configuration configuration, - ReadOnlyMemory palette, + public void ApplyPaletteDither( + in TPaletteDitherImageProcessor processor, ImageFrame source, - Rectangle bounds, - float scale) + Rectangle bounds) + where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor where TPixel : struct, IPixel { - var pixelMap = new EuclideanPixelMap(palette); - + float scale = processor.DitherScale; + ReadOnlySpan palette = processor.Palette.Span; for (int y = bounds.Top; y < bounds.Bottom; y++) { Span row = source.GetPixelRowSpan(y); for (int x = bounds.Left; x < bounds.Right; x++) { TPixel sourcePixel = row[x]; - pixelMap.GetClosestColor(sourcePixel, out TPixel transformed); + TPixel transformed = processor.GetPaletteColor(sourcePixel, palette); this.Dither(source, bounds, sourcePixel, transformed, x, y, scale); row[x] = transformed; } diff --git a/src/ImageSharp/Processing/Processors/Dithering/IDither.cs b/src/ImageSharp/Processing/Processors/Dithering/IDither.cs index fc8ee32f7..4f2b93efb 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/IDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/IDither.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -19,15 +18,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// The type of frame quantizer. /// The pixel format. /// The frame quantizer. - /// The quantized palette. /// The source image. - /// The output target + /// The destination quantized frame. /// The region of interest bounds. void ApplyQuantizationDither( ref TFrameQuantizer quantizer, - ReadOnlyMemory palette, ImageFrame source, - Memory output, + QuantizedFrame destination, Rectangle bounds) where TFrameQuantizer : struct, IFrameQuantizer where TPixel : struct, IPixel; @@ -36,18 +33,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Transforms the image frame applying a dither matrix. /// This method should be treated as destructive, altering the input pixels. /// + /// The type of palette dithering processor. /// The pixel format. - /// The configuration. - /// The quantized palette. + /// The palette dithering processor. /// The source image. /// The region of interest bounds. - /// The dithering scale used to adjust the amount of dither. Range 0..1. - void ApplyPaletteDither( - Configuration configuration, - ReadOnlyMemory palette, + void ApplyPaletteDither( + in TPaletteDitherImageProcessor processor, ImageFrame source, - Rectangle bounds, - float scale) + Rectangle bounds) + where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor where TPixel : struct, IPixel; } } diff --git a/src/ImageSharp/Processing/Processors/Dithering/IPaletteDitherImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/IPaletteDitherImageProcessor{TPixel}.cs new file mode 100644 index 000000000..73a6c8f4f --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Dithering/IPaletteDitherImageProcessor{TPixel}.cs @@ -0,0 +1,39 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Dithering +{ + /// + /// Implements an algorithm to alter the pixels of an image via palette dithering. + /// + /// The pixel format. + public interface IPaletteDitherImageProcessor + where TPixel : struct, IPixel + { + /// + /// Gets the configration instance to use when performing operations. + /// + public Configuration Configuration { get; } + + /// + /// Gets the dithering palette. + /// + ReadOnlyMemory Palette { get; } + + /// + /// Gets the dithering scale used to adjust the amount of dither. Range 0..1. + /// + float DitherScale { get; } + + /// + /// Returns the color from the dithering palette corresponding to the given color. + /// + /// The color to match. + /// The output color palette. + /// The match. + TPixel GetPaletteColor(TPixel color, ReadOnlySpan palette); + } +} diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs index 69e323bd5..854898e62 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs @@ -105,9 +105,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering [MethodImpl(InliningOptions.ShortMethod)] public void ApplyQuantizationDither( ref TFrameQuantizer quantizer, - ReadOnlyMemory palette, ImageFrame source, - Memory output, + QuantizedFrame destination, Rectangle bounds) where TFrameQuantizer : struct, IFrameQuantizer where TPixel : struct, IPixel @@ -116,10 +115,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering ref quantizer, in Unsafe.AsRef(this), source, - output, - bounds, - palette, - ImageMaths.GetBitsNeededForColorDepth(palette.Span.Length)); + destination, + bounds); ParallelRowIterator.IterateRows( quantizer.Configuration, @@ -129,24 +126,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// [MethodImpl(InliningOptions.ShortMethod)] - public void ApplyPaletteDither( - Configuration configuration, - ReadOnlyMemory palette, + public void ApplyPaletteDither( + in TPaletteDitherImageProcessor processor, ImageFrame source, - Rectangle bounds, - float scale) + Rectangle bounds) + where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor where TPixel : struct, IPixel { - var ditherOperation = new PaletteDitherRowIntervalOperation( + var ditherOperation = new PaletteDitherRowIntervalOperation( + in processor, in Unsafe.AsRef(this), source, - bounds, - palette, - scale, - ImageMaths.GetBitsNeededForColorDepth(palette.Span.Length)); + bounds); ParallelRowIterator.IterateRows( - configuration, + processor.Configuration, bounds, in ditherOperation); } @@ -207,7 +201,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly TFrameQuantizer quantizer; private readonly OrderedDither dither; private readonly ImageFrame source; - private readonly Memory output; + private readonly QuantizedFrame destination; private readonly Rectangle bounds; private readonly ReadOnlyMemory palette; private readonly int bitDepth; @@ -217,84 +211,79 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering ref TFrameQuantizer quantizer, in OrderedDither dither, ImageFrame source, - Memory output, - Rectangle bounds, - ReadOnlyMemory palette, - int bitDepth) + QuantizedFrame destination, + Rectangle bounds) { this.quantizer = quantizer; this.dither = dither; this.source = source; - this.output = output; + this.destination = destination; this.bounds = bounds; - this.palette = palette; - this.bitDepth = bitDepth; + this.palette = destination.Palette; + this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(destination.Palette.Span.Length); } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows) { ReadOnlySpan paletteSpan = this.palette.Span; - Span outputSpan = this.output.Span; - int width = this.bounds.Width; int offsetY = this.bounds.Top; int offsetX = this.bounds.Left; float scale = this.quantizer.Options.DitherScale; for (int y = rows.Min; y < rows.Max; y++) { - Span row = this.source.GetPixelRowSpan(y); - int rowStart = (y - offsetY) * width; + Span sourceRow = this.source.GetPixelRowSpan(y); + Span destinationRow = this.destination.GetPixelRowSpan(y - offsetY); - // TODO: This can be a bulk operation. for (int x = this.bounds.Left; x < this.bounds.Right; x++) { - TPixel dithered = this.dither.Dither(row[x], x, y, this.bitDepth, scale); - outputSpan[rowStart + x - offsetX] = this.quantizer.GetQuantizedColor(dithered, paletteSpan, out TPixel _); + TPixel dithered = this.dither.Dither(sourceRow[x], x, y, this.bitDepth, scale); + destinationRow[x - offsetX] = this.quantizer.GetQuantizedColor(dithered, paletteSpan, out TPixel _); } } } } - private readonly struct PaletteDitherRowIntervalOperation : IRowIntervalOperation + private readonly struct PaletteDitherRowIntervalOperation : IRowIntervalOperation + where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor where TPixel : struct, IPixel { + private readonly TPaletteDitherImageProcessor processor; private readonly OrderedDither dither; private readonly ImageFrame source; private readonly Rectangle bounds; - private readonly EuclideanPixelMap pixelMap; private readonly float scale; private readonly int bitDepth; [MethodImpl(InliningOptions.ShortMethod)] public PaletteDitherRowIntervalOperation( + in TPaletteDitherImageProcessor processor, in OrderedDither dither, ImageFrame source, - Rectangle bounds, - ReadOnlyMemory palette, - float scale, - int bitDepth) + Rectangle bounds) { + this.processor = processor; this.dither = dither; this.source = source; this.bounds = bounds; - this.pixelMap = new EuclideanPixelMap(palette); - this.scale = scale; - this.bitDepth = bitDepth; + this.scale = processor.DitherScale; + this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(processor.Palette.Span.Length); } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows) { + ReadOnlySpan paletteSpan = this.processor.Palette.Span; for (int y = rows.Min; y < rows.Max; y++) { Span row = this.source.GetPixelRowSpan(y); for (int x = this.bounds.Left; x < this.bounds.Right; x++) { - TPixel dithered = this.dither.Dither(row[x], x, y, this.bitDepth, this.scale); - this.pixelMap.GetClosestColor(dithered, out TPixel transformed); - row[x] = transformed; + ref TPixel sourcePixel = ref row[x]; + TPixel dithered = this.dither.Dither(sourcePixel, x, y, this.bitDepth, this.scale); + sourcePixel = this.processor.GetPaletteColor(dithered, paletteSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index 118352ec3..04351d34f 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -3,7 +3,9 @@ using System; using System.Buffers; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Processing.Processors.Dithering { @@ -14,11 +16,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering internal sealed class PaletteDitherProcessor : ImageProcessor where TPixel : struct, IPixel { - private readonly int paletteLength; + private readonly DitherProcessor ditherProcessor; private readonly IDither dither; - private readonly float ditherScale; - private readonly ReadOnlyMemory sourcePalette; - private IMemoryOwner palette; + private IMemoryOwner paletteMemory; private bool isDisposed; /// @@ -31,37 +31,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering public PaletteDitherProcessor(Configuration configuration, PaletteDitherProcessor definition, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) { - this.paletteLength = definition.Palette.Span.Length; this.dither = definition.Dither; - this.ditherScale = definition.DitherScale; - this.sourcePalette = definition.Palette; - } - /// - protected override void OnFrameApply(ImageFrame source) - { - var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); + ReadOnlySpan sourcePalette = definition.Palette.Span; + this.paletteMemory = this.Configuration.MemoryAllocator.Allocate(sourcePalette.Length); + Color.ToPixel(this.Configuration, sourcePalette, this.paletteMemory.Memory.Span); - this.dither.ApplyPaletteDither( + this.ditherProcessor = new DitherProcessor( this.Configuration, - this.palette.Memory, - source, - interest, - this.ditherScale); + this.paletteMemory.Memory, + definition.DitherScale); } /// - protected override void BeforeFrameApply(ImageFrame source) + protected override void OnFrameApply(ImageFrame source) { - // Lazy init palettes: - if (this.palette is null) - { - this.palette = this.Configuration.MemoryAllocator.Allocate(this.paletteLength); - ReadOnlySpan sourcePalette = this.sourcePalette.Span; - Color.ToPixel(this.Configuration, sourcePalette, this.palette.Memory.Span); - } - - base.BeforeFrameApply(source); + var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); + this.dither.ApplyPaletteDither(in this.ditherProcessor, source, interest); } /// @@ -74,13 +60,47 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering if (disposing) { - this.palette?.Dispose(); + this.paletteMemory?.Dispose(); } - this.palette = null; + this.paletteMemory = null; this.isDisposed = true; base.Dispose(disposing); } + + /// + /// Used to allow inlining of calls to + /// . + /// + private readonly struct DitherProcessor : IPaletteDitherImageProcessor + { + private readonly EuclideanPixelMap pixelMap; + + [MethodImpl(InliningOptions.ShortMethod)] + public DitherProcessor( + Configuration configuration, + ReadOnlyMemory palette, + float ditherScale) + { + this.Configuration = configuration; + this.pixelMap = new EuclideanPixelMap(palette); + this.Palette = palette; + this.DitherScale = ditherScale; + } + + public Configuration Configuration { get; } + + public ReadOnlyMemory Palette { get; } + + public float DitherScale { get; } + + [MethodImpl(InliningOptions.ShortMethod)] + public TPixel GetPaletteColor(TPixel color, ReadOnlySpan palette) + { + this.pixelMap.GetClosestColor(color, out TPixel match); + return match; + } + } } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs index a5e8d70b0..720923a16 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs @@ -24,6 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// Initializes a new instance of the struct. /// /// The color palette to map from. + [MethodImpl(InliningOptions.ShortMethod)] public EuclideanPixelMap(ReadOnlyMemory palette) { Guard.MustBeGreaterThan(palette.Length, 0, nameof(palette)); @@ -40,7 +41,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - public ReadOnlyMemory Palette { get; } + public ReadOnlyMemory Palette + { + [MethodImpl(InliningOptions.ShortMethod)] + get; + } /// public override bool Equals(object obj) diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs index 5b49fe9e8..7bf7e9b35 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs @@ -41,18 +41,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization MemoryAllocator memoryAllocator = quantizer.Configuration.MemoryAllocator; var quantizedFrame = new QuantizedFrame(memoryAllocator, interest.Width, interest.Height, palette); - Memory output = quantizedFrame.GetWritablePixelMemory(); if (quantizer.Options.Dither is null) { - SecondPass(ref quantizer, source, interest, output, palette); + SecondPass(ref quantizer, source, quantizedFrame, interest); } else { // We clone the image as we don't want to alter the original via error diffusion based dithering. using (ImageFrame clone = source.Clone()) { - SecondPass(ref quantizer, clone, interest, output, palette); + SecondPass(ref quantizer, clone, quantizedFrame, interest); } } @@ -63,9 +62,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization private static void SecondPass( ref TFrameQuantizer quantizer, ImageFrame source, - Rectangle bounds, - Memory output, - ReadOnlyMemory palette) + QuantizedFrame destination, + Rectangle bounds) where TFrameQuantizer : struct, IFrameQuantizer where TPixel : struct, IPixel { @@ -73,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization if (dither is null) { - var operation = new RowIntervalOperation(quantizer, source, output, bounds, palette); + var operation = new RowIntervalOperation(quantizer, source, destination, bounds); ParallelRowIterator.IterateRows( quantizer.Configuration, bounds, @@ -82,7 +80,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization return; } - dither.ApplyQuantizationDither(ref quantizer, palette, source, output, bounds); + dither.ApplyQuantizationDither(ref quantizer, source, destination, bounds); } private readonly struct RowIntervalOperation : IRowIntervalOperation @@ -91,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { private readonly TFrameQuantizer quantizer; private readonly ImageFrame source; - private readonly Memory output; + private readonly QuantizedFrame destination; private readonly Rectangle bounds; private readonly ReadOnlyMemory palette; @@ -99,35 +97,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public RowIntervalOperation( in TFrameQuantizer quantizer, ImageFrame source, - Memory output, - Rectangle bounds, - ReadOnlyMemory palette) + QuantizedFrame destination, + Rectangle bounds) { this.quantizer = quantizer; this.source = source; - this.output = output; + this.destination = destination; this.bounds = bounds; - this.palette = palette; + this.palette = destination.Palette; } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows) { ReadOnlySpan paletteSpan = this.palette.Span; - Span outputSpan = this.output.Span; - int width = this.bounds.Width; int offsetY = this.bounds.Top; int offsetX = this.bounds.Left; for (int y = rows.Min; y < rows.Max; y++) { - Span row = this.source.GetPixelRowSpan(y); - int rowStart = (y - offsetY) * width; + Span sourceRow = this.source.GetPixelRowSpan(y); + Span destinationRow = this.destination.GetPixelRowSpan(y - offsetY); - // TODO: This can be a bulk operation. for (int x = this.bounds.Left; x < this.bounds.Right; x++) { - outputSpan[rowStart + x - offsetX] = this.quantizer.GetQuantizedColor(row[x], paletteSpan, out TPixel _); + destinationRow[x - offsetX] = this.quantizer.GetQuantizedColor(sourceRow[x], paletteSpan, out TPixel _); } } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs index d3091c3b0..fdf4ab7a6 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs @@ -31,9 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// A representing a quantized version of the source frame pixels. /// - QuantizedFrame QuantizeFrame( - ImageFrame source, - Rectangle bounds); + QuantizedFrame QuantizeFrame(ImageFrame source, Rectangle bounds); /// /// Builds the quantized palette from the given image frame and bounds. @@ -44,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization ReadOnlyMemory BuildPalette(ImageFrame source, Rectangle bounds); /// - /// Returns the index and color from the quantized palette corresponding to the give to the given color. + /// Returns the index and color from the quantized palette corresponding to the given color. /// /// The color to match. /// The output color palette. diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs index fccc799bb..93569a6ce 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs @@ -57,16 +57,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The [MethodImpl(InliningOptions.ShortMethod)] - public ReadOnlySpan GetPixelSpan() => this.pixels.GetSpan(); + public Span GetPixelSpan() => this.pixels.GetSpan(); /// /// Gets the representation of the pixels as a of contiguous memory /// at row beginning from the the first pixel on that row. /// /// The row. - /// The pixel row as a . + /// The pixel row as a . [MethodImpl(InliningOptions.ShortMethod)] - public ReadOnlySpan GetRowSpan(int rowIndex) + public Span GetPixelRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); /// @@ -82,10 +82,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.pixels = null; this.Palette = null; } - - /// - /// Get the non-readonly memory of pixel data so can fill it. - /// - internal Memory GetWritablePixelMemory() => this.pixels.Memory; } }