diff --git a/src/ImageSharp/Color/Color.WebSafePalette.cs b/src/ImageSharp/Color/Color.WebSafePalette.cs
index 506432ac2d..8e5fb2a55b 100644
--- a/src/ImageSharp/Color/Color.WebSafePalette.cs
+++ b/src/ImageSharp/Color/Color.WebSafePalette.cs
@@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp
///
/// Gets a collection of named, web safe colors as defined in the CSS Color Module Level 4.
///
- public static ReadOnlySpan WebSafePalette => WebSafePaletteLazy.Value;
+ public static ReadOnlyMemory WebSafePalette => WebSafePaletteLazy.Value;
private static Color[] CreateWebSafePalette() => new[]
{
diff --git a/src/ImageSharp/Color/Color.WernerPalette.cs b/src/ImageSharp/Color/Color.WernerPalette.cs
index 37980b15fd..768fe065cd 100644
--- a/src/ImageSharp/Color/Color.WernerPalette.cs
+++ b/src/ImageSharp/Color/Color.WernerPalette.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp
/// Gets a collection of colors as defined in the original second edition of Werner’s Nomenclature of Colours 1821.
/// The hex codes were collected and defined by Nicholas Rougeux .
///
- public static ReadOnlySpan WernerPalette => WernerPaletteLazy.Value;
+ public static ReadOnlyMemory WernerPalette => WernerPaletteLazy.Value;
private static Color[] CreateWernerPalette() => new[]
{
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 12a515cca7..2770790a28 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -144,8 +144,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
private void EncodeGlobal(Image image, QuantizedFrame quantized, int transparencyIndex, Stream stream)
where TPixel : struct, IPixel
{
- var palleteQuantizer = new PaletteQuantizer(quantized.Palette, this.quantizer.Diffuser);
-
for (int i = 0; i < image.Frames.Count; i++)
{
ImageFrame frame = image.Frames[i];
@@ -160,10 +158,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
else
{
- using (IFrameQuantizer palleteFrameQuantizer = palleteQuantizer.CreateFrameQuantizer(image.GetConfiguration()))
- using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame))
+ using (IFrameQuantizer palleteFrameQuantizer =
+ new PaletteFrameQuantizer(this.quantizer.Diffuser, quantized.Palette))
{
- this.WriteImageData(paletteQuantized, stream);
+ using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame))
+ {
+ this.WriteImageData(paletteQuantized, stream);
+ }
}
}
}
diff --git a/src/ImageSharp/Processing/DiffuseExtensions.cs b/src/ImageSharp/Processing/DiffuseExtensions.cs
index cd714c3da3..f9a1bdde0e 100644
--- a/src/ImageSharp/Processing/DiffuseExtensions.cs
+++ b/src/ImageSharp/Processing/DiffuseExtensions.cs
@@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering
this IImageProcessingContext source,
IErrorDiffuser diffuser,
float threshold,
- ReadOnlySpan palette) =>
+ ReadOnlyMemory palette) =>
source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette));
///
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering
this IImageProcessingContext source,
IErrorDiffuser diffuser,
float threshold,
- ReadOnlySpan palette,
+ ReadOnlyMemory palette,
Rectangle rectangle) =>
source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette), rectangle);
}
diff --git a/src/ImageSharp/Processing/DitherExtensions.cs b/src/ImageSharp/Processing/DitherExtensions.cs
index 55794aec20..f83a9e9e81 100644
--- a/src/ImageSharp/Processing/DitherExtensions.cs
+++ b/src/ImageSharp/Processing/DitherExtensions.cs
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing
public static IImageProcessingContext Dither(
this IImageProcessingContext source,
IOrderedDither dither,
- ReadOnlySpan palette) =>
+ ReadOnlyMemory palette) =>
source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette));
///
@@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing
public static IImageProcessingContext Dither(
this IImageProcessingContext source,
IOrderedDither dither,
- ReadOnlySpan palette,
+ ReadOnlyMemory palette,
Rectangle rectangle) =>
source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette), rectangle);
}
diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs
index 5436a7733f..e0b79c2b20 100644
--- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs
@@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// The error diffuser
/// The threshold to split the image. Must be between 0 and 1.
/// The palette to select substitute colors from.
- public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold, ReadOnlySpan palette)
+ public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold, ReadOnlyMemory palette)
: base(palette)
{
Guard.NotNull(diffuser, nameof(diffuser));
diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs
index ba7c1e9980..ac6554d4c1 100644
--- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
///
/// The ordered ditherer.
/// The palette to select substitute colors from.
- public OrderedDitherPaletteProcessor(IOrderedDither dither, ReadOnlySpan palette)
+ public OrderedDitherPaletteProcessor(IOrderedDither dither, ReadOnlyMemory palette)
: base(palette) => this.Dither = dither ?? throw new ArgumentNullException(nameof(dither));
///
diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs
index 904d026345..de798b64bc 100644
--- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs
@@ -12,23 +12,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
///
public abstract class PaletteDitherProcessor : IImageProcessor
{
- private readonly Color[] palette;
-
///
/// Initializes a new instance of the class.
///
/// The palette to select substitute colors from.
- protected PaletteDitherProcessor(ReadOnlySpan palette)
+ protected PaletteDitherProcessor(ReadOnlyMemory palette)
{
- // This shouldn't be a perf issue:
- // these arrays are small, and created with low frequency.
- this.palette = palette.ToArray();
+ this.Palette = palette;
}
///
/// Gets the palette to select substitute colors from.
///
- public ReadOnlySpan Palette => this.palette;
+ public ReadOnlyMemory Palette { get; }
///
public abstract IImageProcessor CreatePixelSpecificProcessor()
diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs
index 334eab833c..205b589b1e 100644
--- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs
@@ -20,13 +20,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
{
private readonly Dictionary> cache = new Dictionary>();
+ private TPixel[] palette;
+
///
/// The vector representation of the image palette.
///
private Vector4[] paletteVector;
- private TPixel[] palette;
-
///
/// Initializes a new instance of the class.
///
@@ -37,6 +37,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
protected PaletteDitherProcessor Definition { get; }
+ protected override void BeforeFrameApply(
+ ImageFrame source,
+ Rectangle sourceRectangle,
+ Configuration configuration)
+ {
+ base.BeforeFrameApply(source, sourceRectangle, configuration);
+
+ // Lazy init palette:
+ if (this.palette is null)
+ {
+ ReadOnlySpan sourcePalette = this.Definition.Palette.Span;
+ this.palette = new TPixel[sourcePalette.Length];
+ Color.ToPixel(configuration, sourcePalette, this.palette);
+ }
+
+ // Lazy init paletteVector:
+ if (this.paletteVector is null)
+ {
+ this.paletteVector = new Vector4[this.palette.Length];
+ PixelOperations.Instance.ToVector4(
+ configuration,
+ (ReadOnlySpan)this.palette,
+ (Span)this.paletteVector,
+ PixelConversionModifiers.Scale);
+ }
+ }
+
///
/// Returns the two closest colors from the palette calculated via Euclidean distance in the Rgba space.
///
@@ -88,25 +115,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
return pair;
}
-
- protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
- {
- base.BeforeFrameApply(source, sourceRectangle, configuration);
-
- // Lazy init palette:
- if (this.palette is null)
- {
- ReadOnlySpan sourcePalette = this.Definition.Palette;
- this.palette = new TPixel[sourcePalette.Length];
- Color.ToPixel(configuration, sourcePalette, this.palette);
- }
-
- // Lazy init paletteVector:
- if (this.paletteVector is null)
- {
- this.paletteVector = new Vector4[this.palette.Length];
- PixelOperations.Instance.ToVector4(configuration, (ReadOnlySpan)this.palette, (Span)this.paletteVector, PixelConversionModifiers.Scale);
- }
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
index dcdddb217c..255be5ed59 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
@@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
///
- /// Gets the options effecting blending and composition
+ /// Gets the options effecting blending and composition.
///
public GraphicsOptions GraphicsOptions { get; }
diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs
similarity index 81%
rename from src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs
rename to src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs
index f23343f6d7..6d8136513f 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// The base class for all implementations
///
/// The pixel format.
- public abstract class FrameQuantizerBase : IFrameQuantizer
+ public abstract class FrameQuantizer : IFrameQuantizer
where TPixel : struct, IPixel
{
///
@@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
private Vector4[] paletteVector;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The quantizer
///
@@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// only call the method.
/// If two passes are required, the code will also call .
///
- protected FrameQuantizerBase(IQuantizer quantizer, bool singlePass)
+ protected FrameQuantizer(IQuantizer quantizer, bool singlePass)
{
Guard.NotNull(quantizer, nameof(quantizer));
@@ -52,6 +52,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.Dither = this.Diffuser != null;
this.singlePass = singlePass;
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The diffuser
+ ///
+ /// If true, the quantization process only needs to loop through the source pixels once
+ ///
+ ///
+ /// If you construct this class with a true for , then the code will
+ /// only call the method.
+ /// If two passes are required, the code will also call .
+ ///
+ protected FrameQuantizer(IErrorDiffuser diffuser, bool singlePass)
+ {
+ this.Diffuser = diffuser;
+ this.Dither = this.Diffuser != null;
+ this.singlePass = singlePass;
+ }
///
public bool Dither { get; }
@@ -77,22 +96,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
}
// Collect the palette. Required before the second pass runs.
- TPixel[] palette = this.GetPalette();
+ ReadOnlyMemory palette = this.GetPalette();
this.paletteVector = new Vector4[palette.Length];
- PixelOperations.Instance.ToVector4(image.Configuration, (ReadOnlySpan)palette, (Span)this.paletteVector, PixelConversionModifiers.Scale);
- var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette);
+ PixelOperations.Instance.ToVector4(image.Configuration, palette.Span, (Span)this.paletteVector, PixelConversionModifiers.Scale);
+
+ // TODO: Pass ReadOnlyMemory instead of array!
+ var quantizedFrame = new QuantizedFrame(
+ image.MemoryAllocator,
+ width,
+ height,
+ palette.Span.ToArray());
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, width, height);
+ this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette.Span, width, height);
}
}
else
{
- this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette, width, height);
+ this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette.Span, width, height);
}
return quantizedFrame;
@@ -134,7 +159,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
///
///
- protected abstract TPixel[] GetPalette();
+ protected abstract ReadOnlyMemory GetPalette();
///
/// Returns the index of the first instance of the transparent color in the palette.
diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs
index dd56375f63..85a4d20295 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
///
/// The pixel format.
- internal sealed class OctreeFrameQuantizer : FrameQuantizerBase
+ internal sealed class OctreeFrameQuantizer : FrameQuantizer
where TPixel : struct, IPixel
{
///
@@ -136,10 +136,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
}
}
- internal TPixel[] AotGetPalette() => this.GetPalette();
+ internal ReadOnlyMemory AotGetPalette() => this.GetPalette();
///
- protected override TPixel[] GetPalette() => this.octree.Palletize(this.colors);
+ protected override ReadOnlyMemory GetPalette() => this.octree.Palletize(this.colors);
///
/// Process the pixel in the second pass of the algorithm.
diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs
index f8a19f8c40..265c343e68 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs
@@ -6,6 +6,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing.Processors.Dithering;
namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{
@@ -14,21 +15,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
///
/// The pixel format.
- internal sealed class PaletteFrameQuantizer : FrameQuantizerBase
+ internal sealed class PaletteFrameQuantizer : FrameQuantizer
where TPixel : struct, IPixel
{
///
/// The reduced image palette.
///
- private readonly TPixel[] palette;
+ private readonly ReadOnlyMemory palette;
///
/// Initializes a new instance of the class.
///
- /// The palette quantizer.
+ /// The palette quantizer.
/// An array of all colors in the palette.
- public PaletteFrameQuantizer(IQuantizer quantizer, TPixel[] colors)
- : base(quantizer, true) => this.palette = colors;
+ public PaletteFrameQuantizer(IErrorDiffuser diffuser, ReadOnlyMemory colors)
+ : base(diffuser, true) => this.palette = colors;
///
protected override void SecondPass(
@@ -85,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- protected override TPixel[] GetPalette() => this.palette;
+ protected override ReadOnlyMemory GetPalette() => this.palette;
///
/// Process the pixel in the second pass of the algorithm
diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs
index 6b2be3d038..ba434a4b21 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Dithering;
@@ -14,61 +15,65 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// By default the quantizer uses dithering.
///
///
- public abstract class PaletteQuantizer : IQuantizer
+ public class PaletteQuantizer : IQuantizer
{
///
/// Initializes a new instance of the class.
///
- protected PaletteQuantizer()
- : this(true)
+ /// The palette.
+ public PaletteQuantizer(ReadOnlyMemory palette)
+ : this(palette, true)
{
}
///
/// Initializes a new instance of the class.
///
+ /// The palette.
/// Whether to apply dithering to the output image
- protected PaletteQuantizer(bool dither)
- : this(GetDiffuser(dither))
+ public PaletteQuantizer(ReadOnlyMemory palette, bool dither)
+ : this(palette, GetDiffuser(dither))
{
}
///
/// Initializes a new instance of the class.
///
+ /// The palette.
/// The error diffusion algorithm, if any, to apply to the output image
- protected PaletteQuantizer(IErrorDiffuser diffuser) => this.Diffuser = diffuser;
+ public PaletteQuantizer(ReadOnlyMemory palette, IErrorDiffuser diffuser)
+ {
+ this.Palette = palette;
+ this.Diffuser = diffuser;
+ }
///
public IErrorDiffuser Diffuser { get; }
- ///
- public abstract IFrameQuantizer CreateFrameQuantizer(Configuration configuration)
- where TPixel : struct, IPixel;
-
- ///
- public abstract IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors)
- where TPixel : struct, IPixel;
-
///
- /// Creates the generic frame quantizer.
+ /// Gets the palette.
///
- /// The pixel format.
- /// The to configure internal operations.
- /// The color palette.
- /// The maximum number of colors to hold in the color palette.
- /// The
- protected IFrameQuantizer CreateFrameQuantizer(Configuration configuration, TPixel[] palette, int maxColors)
+ public ReadOnlyMemory Palette { get; }
+
+ ///
+ public IFrameQuantizer CreateFrameQuantizer(Configuration configuration)
where TPixel : struct, IPixel
{
- int max = Math.Min(QuantizerConstants.MaxColors, Math.Min(maxColors, palette.Length));
+ TPixel[] palette = new TPixel[this.Palette.Length];
+ Color.ToPixel(configuration, this.Palette.Span, palette.AsSpan());
+ return new PaletteFrameQuantizer(this.Diffuser, palette);
+ }
- if (max != palette.Length)
- {
- return new PaletteFrameQuantizer(this, palette.AsSpan(0, max).ToArray());
- }
+ ///
+ public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors)
+ where TPixel : struct, IPixel
+ {
+ maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors);
+ int max = Math.Min(maxColors, this.Palette.Length);
- return new PaletteFrameQuantizer(this, palette);
+ TPixel[] palette = new TPixel[max];
+ Color.ToPixel(configuration, this.Palette.Span.Slice(0, max), palette.AsSpan());
+ return new PaletteFrameQuantizer(this.Diffuser, palette);
}
private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null;
diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs
deleted file mode 100644
index a350adfc0c..0000000000
--- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Processors.Dithering;
-
-namespace SixLabors.ImageSharp.Processing.Processors.Quantization
-{
- ///
- /// A generic palette quantizer.
- ///
- /// The pixel format.
- public class PaletteQuantizer : IQuantizer
- where TPixel : struct, IPixel
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The color palette to use.
- public PaletteQuantizer(TPixel[] palette)
- : this(palette, true)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The color palette to use.
- /// Whether to apply dithering to the output image
- public PaletteQuantizer(TPixel[] palette, bool dither)
- : this(palette, GetDiffuser(dither))
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The color palette to use.
- /// The error diffusion algorithm, if any, to apply to the output image
- public PaletteQuantizer(TPixel[] palette, IErrorDiffuser diffuser)
- {
- Guard.MustBeBetweenOrEqualTo(palette.Length, QuantizerConstants.MinColors, QuantizerConstants.MaxColors, nameof(palette));
- this.Palette = palette;
- this.Diffuser = diffuser;
- }
-
- ///
- public IErrorDiffuser Diffuser { get; }
-
- ///
- /// Gets the palette.
- ///
- public TPixel[] Palette { get; }
-
- ///
- /// Creates the generic frame quantizer.
- ///
- /// The to configure internal operations.
- /// The .
- public IFrameQuantizer CreateFrameQuantizer(Configuration configuration)
- => ((IQuantizer)this).CreateFrameQuantizer(configuration);
-
- ///
- /// Creates the generic frame quantizer.
- ///
- /// The to configure internal operations.
- /// The maximum number of colors to hold in the color palette.
- /// The .
- public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors)
- => ((IQuantizer)this).CreateFrameQuantizer(configuration, maxColors);
-
- ///
- IFrameQuantizer IQuantizer.CreateFrameQuantizer(Configuration configuration)
- {
- if (!typeof(TPixel).Equals(typeof(TPixel1)))
- {
- throw new InvalidOperationException("Generic method type must be the same as class type.");
- }
-
- TPixel[] paletteRef = this.Palette;
- return new PaletteFrameQuantizer(this, Unsafe.As(ref paletteRef));
- }
-
- ///
- IFrameQuantizer IQuantizer.CreateFrameQuantizer(Configuration configuration, int maxColors)
- {
- if (!typeof(TPixel).Equals(typeof(TPixel1)))
- {
- throw new InvalidOperationException("Generic method type must be the same as class type.");
- }
-
- TPixel[] paletteRef = this.Palette;
- TPixel1[] castPalette = Unsafe.As(ref paletteRef);
-
- maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors);
- int max = Math.Min(maxColors, castPalette.Length);
-
- if (max != castPalette.Length)
- {
- return new PaletteFrameQuantizer(this, castPalette.AsSpan(0, max).ToArray());
- }
-
- return new PaletteFrameQuantizer(this, castPalette);
- }
-
- private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null;
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs
index 93630a9166..3f6dfde281 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs
@@ -15,6 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Initializes a new instance of the class.
///
public WebSafePaletteQuantizer()
+ : this(true)
{
}
@@ -23,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
/// Whether to apply dithering to the output image
public WebSafePaletteQuantizer(bool dither)
- : base(dither)
+ : base(Color.WebSafePalette, dither)
{
}
@@ -32,16 +33,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
/// The error diffusion algorithm, if any, to apply to the output image
public WebSafePaletteQuantizer(IErrorDiffuser diffuser)
- : base(diffuser)
+ : base(Color.WebSafePalette, diffuser)
{
}
-
- ///
- public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration)
- => this.CreateFrameQuantizer(configuration, NamedColors.WebSafePalette.Length);
-
- ///
- public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors)
- => this.CreateFrameQuantizer(configuration, NamedColors.WebSafePalette, maxColors);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs
index 2ff9f5090c..d659ecabf7 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs
@@ -16,6 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Initializes a new instance of the class.
///
public WernerPaletteQuantizer()
+ : this(true)
{
}
@@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
/// Whether to apply dithering to the output image
public WernerPaletteQuantizer(bool dither)
- : base(dither)
+ : base(Color.WernerPalette, dither)
{
}
@@ -33,16 +34,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
/// The error diffusion algorithm, if any, to apply to the output image
public WernerPaletteQuantizer(IErrorDiffuser diffuser)
- : base(diffuser)
+ : base(Color.WernerPalette, diffuser)
{
}
-
- ///
- public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration)
- => this.CreateFrameQuantizer(configuration, NamedColors.WernerPalette.Length);
-
- ///
- public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors)
- => this.CreateFrameQuantizer(configuration, NamedColors.WernerPalette, maxColors);
}
}
\ 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 1f1513adf1..95918f564a 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs
@@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
///
/// The pixel format.
- internal sealed class WuFrameQuantizer : FrameQuantizerBase
+ internal sealed class WuFrameQuantizer : FrameQuantizer
where TPixel : struct, IPixel
{
// The following two variables determine the amount of bits to preserve when calculating the histogram.
@@ -171,10 +171,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.tag?.Dispose();
}
- internal TPixel[] AotGetPalette() => this.GetPalette();
+ internal ReadOnlyMemory AotGetPalette() => this.GetPalette();
///
- protected override TPixel[] GetPalette()
+ protected override ReadOnlyMemory GetPalette()
{
if (this.palette is null)
{
diff --git a/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs
index 59dcde2a63..d91688cd2c 100644
--- a/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs
+++ b/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs
@@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
this.operations.Dither(this.orderedDither);
OrderedDitherPaletteProcessor p = this.Verify();
Assert.Equal(this.orderedDither, p.Dither);
- Assert.Equal(Color.WebSafePalette.ToArray(), p.Palette);
+ Assert.Equal(Color.WebSafePalette, p.Palette);
}
[Fact]
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs
index a4e6edd53e..05ce700476 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs
@@ -11,21 +11,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Quantization
{
public class PaletteQuantizerTests
{
- private static readonly Rgba32[] Rgb = new Rgba32[] { Rgba32.Red, Rgba32.Green, Rgba32.Blue };
+ private static readonly Color[] Rgb = new Color[] { Rgba32.Red, Rgba32.Green, Rgba32.Blue };
[Fact]
public void PaletteQuantizerConstructor()
{
- var quantizer = new PaletteQuantizer(Rgb);
+ var quantizer = new PaletteQuantizer(Rgb);
Assert.Equal(Rgb, quantizer.Palette);
Assert.Equal(KnownDiffusers.FloydSteinberg, quantizer.Diffuser);
- quantizer = new PaletteQuantizer(Rgb, false);
+ quantizer = new PaletteQuantizer(Rgb, false);
Assert.Equal(Rgb, quantizer.Palette);
Assert.Null(quantizer.Diffuser);
- quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson);
+ quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson);
Assert.Equal(Rgb, quantizer.Palette);
Assert.Equal(KnownDiffusers.Atkinson, quantizer.Diffuser);
}
@@ -33,35 +33,27 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Quantization
[Fact]
public void PaletteQuantizerCanCreateFrameQuantizer()
{
- var quantizer = new PaletteQuantizer(Rgb);
- IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default);
+ var quantizer = new PaletteQuantizer(Rgb);
+ IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default);
Assert.NotNull(frameQuantizer);
Assert.True(frameQuantizer.Dither);
Assert.Equal(KnownDiffusers.FloydSteinberg, frameQuantizer.Diffuser);
- quantizer = new PaletteQuantizer(Rgb, false);
- frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default);
+ quantizer = new PaletteQuantizer(Rgb, false);
+ frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default);
Assert.NotNull(frameQuantizer);
Assert.False(frameQuantizer.Dither);
Assert.Null(frameQuantizer.Diffuser);
- quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson);
- frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default);
+ quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson);
+ frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default);
Assert.NotNull(frameQuantizer);
Assert.True(frameQuantizer.Dither);
Assert.Equal(KnownDiffusers.Atkinson, frameQuantizer.Diffuser);
}
- [Fact]
- public void PaletteQuantizerThrowsOnInvalidGenericMethodCall()
- {
- var quantizer = new PaletteQuantizer(Rgb);
-
- Assert.Throws(() => ((IQuantizer)quantizer).CreateFrameQuantizer(Configuration.Default));
- }
-
[Fact]
public void KnownQuantizersWebSafeTests()
{