Browse Source

BuildPaletteAndQuantizeFrame, use IPixelSamplingStrategy in GifEncoder

pull/1574/head
Anton Firszov 6 years ago
parent
commit
40b6baecfe
  1. 2
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  2. 6
      src/ImageSharp/Formats/Gif/GifEncoder.cs
  3. 21
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  4. 5
      src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
  5. 2
      src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
  6. 31
      src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs
  7. 8
      src/ImageSharp/Processing/Processors/Quantization/IQuantizer{TPixel}.cs
  8. 6
      src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs
  9. 4
      src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs
  10. 2
      src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
  11. 49
      src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs
  12. 6
      src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs
  13. 26
      tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
  14. 2
      tests/ImageSharp.Tests/Quantization/PixelSamplingStrategyTests.cs
  15. 4
      tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs
  16. 10
      tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs

2
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -337,7 +337,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel>
{
using IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration);
using IndexedImageFrame<TPixel> quantized = frameQuantizer.QuantizeFrame(image, image.Bounds());
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds());
ReadOnlySpan<TPixel> quantizedColors = quantized.Palette.Span;
var color = default(Rgba32);

6
src/ImageSharp/Formats/Gif/GifEncoder.cs

@ -25,7 +25,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
public GifColorTableMode? ColorTableMode { get; set; }
internal IPixelSamplingStrategy GlobalPixelSamplingStrategy { get; set; }
/// <summary>
/// Gets or sets the <see cref="IPixelSamplingStrategy"/> used for quantization
/// when building a global color table in case of <see cref="GifColorTableMode.Global"/>.
/// </summary>
public IPixelSamplingStrategy GlobalPixelSamplingStrategy { get; set; } = new DefaultPixelSamplingStrategy();
/// <inheritdoc/>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)

21
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -49,6 +49,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
private int bitDepth;
/// <summary>
/// The pixel sampling strategy for global quantization.
/// </summary>
private IPixelSamplingStrategy pixelSamplingStrategy;
/// <summary>
/// Initializes a new instance of the <see cref="GifEncoderCore"/> class.
/// </summary>
@ -60,6 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.memoryAllocator = configuration.MemoryAllocator;
this.quantizer = options.Quantizer;
this.colorTableMode = options.ColorTableMode;
this.pixelSamplingStrategy = options.GlobalPixelSamplingStrategy;
}
/// <summary>
@ -81,9 +87,18 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Quantize the image returning a palette.
IndexedImageFrame<TPixel> quantized;
using (IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration))
{
quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
if (useGlobalTable)
{
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image);
quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
}
else
{
quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image.Frames.RootFrame, image.Bounds());
}
}
// Get the number of bits.
@ -185,12 +200,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
};
using IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration, options);
quantized = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
}
else
{
using IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration);
quantized = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
}
}

5
src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs

@ -22,5 +22,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Gets the color table mode: Global or local.
/// </summary>
GifColorTableMode? ColorTableMode { get; }
/// <summary>
/// Gets the <see cref="IPixelSamplingStrategy"/> used for quantization when building a global color table.
/// </summary>
IPixelSamplingStrategy GlobalPixelSamplingStrategy { get; }
}
}

2
src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs

@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Formats.Png
using (IQuantizer<TPixel> frameQuantizer = options.Quantizer.CreatePixelSpecificQuantizer<TPixel>(image.GetConfiguration()))
{
ImageFrame<TPixel> frame = image.Frames.RootFrame;
return frameQuantizer.QuantizeFrame(frame, frame.Bounds());
return frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
}
}

31
src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs

@ -15,14 +15,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
public class DefaultPixelSamplingStrategy : IPixelSamplingStrategy
{
// TODO: This value shall be determined by benchmarking.
// (Maximum quality while decoding time is still tolerable.)
private const int DefaultMaximumPixels = 8192 * 8192;
// A smaller value should likely work well, providing better perf.
private const int DefaultMaximumPixels = 4096 * 4096;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultPixelSamplingStrategy"/> class.
/// </summary>
public DefaultPixelSamplingStrategy()
: this(DefaultMaximumPixels)
: this(DefaultMaximumPixels, 0.1)
{
}
@ -30,10 +30,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Initializes a new instance of the <see cref="DefaultPixelSamplingStrategy"/> class.
/// </summary>
/// <param name="maximumPixels">The maximum number of pixels to process.</param>
public DefaultPixelSamplingStrategy(int maximumPixels)
/// <param name="minimumScanRatio">always scan at least this portion of total pixels within the image.</param>
public DefaultPixelSamplingStrategy(int maximumPixels, double minimumScanRatio)
{
Guard.MustBeGreaterThan(maximumPixels, 0, nameof(maximumPixels));
this.MaximumPixels = maximumPixels;
this.MinimumScanRatio = minimumScanRatio;
}
/// <summary>
@ -41,11 +43,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// </summary>
public long MaximumPixels { get; }
/// <summary>
/// Gets a value indicating: always scan at least this portion of total pixels within the image.
/// The default is 0.1 (10%).
/// </summary>
public double MinimumScanRatio { get; }
/// <inheritdoc />
public IEnumerable<BufferRegion<TPixel>> EnumeratePixelRegions<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
long maximumPixels = Math.Min(MaximumPixels, (long)image.Width * image.Height * image.Frames.Count);
long maximumPixels = Math.Min(this.MaximumPixels, (long)image.Width * image.Height * image.Frames.Count);
long maxNumberOfRows = maximumPixels / image.Width;
long totalNumberOfRows = (long)image.Height * image.Frames.Count;
@ -61,8 +69,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{
double r = maxNumberOfRows / (double)totalNumberOfRows;
r = Math.Round(r, 1); // Use a rough approximation to make sure we don't leave out large contiguous regions:
r = Math.Max(0.1, r); // always visit at least 10% of the image
// Use a rough approximation to make sure we don't leave out large contiguous regions:
if (maxNumberOfRows > 200)
{
r = Math.Round(r, 2);
}
else
{
r = Math.Round(r, 1);
}
r = Math.Max(this.MinimumScanRatio, r); // always visit the minimum defined portion of the image.
var ratio = new Rational(r);

8
src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs → src/ImageSharp/Processing/Processors/Quantization/IQuantizer{TPixel}.cs

@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Gets the quantized color palette.
/// </summary>
/// <exception cref="InvalidOperationException">
/// The palette has not been built via <see cref="CollectPaletteColors"/>.
/// The palette has not been built via <see cref="AddPaletteColors"/>.
/// </exception>
ReadOnlyMemory<TPixel> Palette { get; }
@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Adds colors to the quantized palette from the given pixel source.
/// </summary>
/// <param name="pixelRegion">The <see cref="BufferRegion{T}"/> of source pixels to register.</param>
void CollectPaletteColors(BufferRegion<TPixel> pixelRegion);
void AddPaletteColors(BufferRegion<TPixel> pixelRegion);
/// <summary>
/// Quantizes an image frame and return the resulting output pixels.
@ -46,6 +46,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <returns>
/// A <see cref="IndexedImageFrame{TPixel}"/> representing a quantized version of the source frame pixels.
/// </returns>
/// <remarks>
/// Only executes the second (quantization) step. The palette has to be built by calling <see cref="AddPaletteColors"/>.
/// To run both steps, use <see cref="QuantizerUtilities.BuildPaletteAndQuantizeFrame{TPixel}"/>.
/// </remarks>
IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds);
/// <summary>

6
src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs

@ -62,14 +62,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{
get
{
FrameQuantizerUtilities.CheckPaletteState(in this.palette);
QuantizerUtilities.CheckPaletteState(in this.palette);
return this.palette;
}
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void CollectPaletteColors(BufferRegion<TPixel> pixelRegion)
public void AddPaletteColors(BufferRegion<TPixel> pixelRegion)
{
Rectangle bounds = pixelRegion.Rectangle;
Buffer2D<TPixel> source = pixelRegion.Buffer;
@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public readonly IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds)
=> FrameQuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
=> QuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]

4
src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs

@ -50,11 +50,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public readonly IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds)
=> FrameQuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
=> QuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void CollectPaletteColors(BufferRegion<TPixel> pixelRegion)
public void AddPaletteColors(BufferRegion<TPixel> pixelRegion)
{
}

2
src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs

@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
Configuration configuration = this.Configuration;
using IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(configuration);
using IndexedImageFrame<TPixel> quantized = frameQuantizer.QuantizeFrame(source, interest);
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(source, interest);
var operation = new RowIntervalOperation(this.SourceRectangle, source, quantized);
ParallelRowIterator.IterateRowIntervals(

49
src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerUtilities.cs → src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <summary>
/// Contains utility methods for <see cref="IQuantizer{TPixel}"/> instances.
/// </summary>
public static class FrameQuantizerUtilities
public static class QuantizerUtilities
{
/// <summary>
/// Helper method for throwing an exception when a frame quantizer palette has
@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="palette">The frame quantizer palette.</param>
/// <exception cref="InvalidOperationException">
/// The palette has not been built via <see cref="IQuantizer{TPixel}.CollectPaletteColors"/>
/// The palette has not been built via <see cref="IQuantizer{TPixel}.AddPaletteColors"/>
/// </exception>
public static void CheckPaletteState<TPixel>(in ReadOnlyMemory<TPixel> palette)
where TPixel : unmanaged, IPixel<TPixel>
@ -33,12 +33,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
}
}
/// <summary>
/// Execute both steps of the quantization.
/// </summary>
/// <param name="quantizer">The pixel specific quantizer.</param>
/// <param name="source">The source image frame to quantize.</param>
/// <param name="bounds">The bounds within the frame to quantize.</param>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <returns>
/// A <see cref="IndexedImageFrame{TPixel}"/> representing a quantized version of the source frame pixels.
/// </returns>
public static IndexedImageFrame<TPixel> BuildPaletteAndQuantizeFrame<TPixel>(
this IQuantizer<TPixel> quantizer,
ImageFrame<TPixel> source,
Rectangle bounds)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(quantizer, nameof(quantizer));
Guard.NotNull(source, nameof(source));
var interest = Rectangle.Intersect(source.Bounds(), bounds);
BufferRegion<TPixel> region = source.PixelBuffer.GetRegion(interest);
// Collect the palette. Required before the second pass runs.
quantizer.AddPaletteColors(region);
return quantizer.QuantizeFrame(source, bounds);
}
/// <summary>
/// Quantizes an image frame and return the resulting output pixels.
/// </summary>
/// <typeparam name="TFrameQuantizer">The type of frame quantizer.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="quantizer">The frame quantizer.</param>
/// <param name="quantizer">The pixel specific quantizer.</param>
/// <param name="source">The source image frame to quantize.</param>
/// <param name="bounds">The bounds within the frame to quantize.</param>
/// <returns>
@ -53,10 +80,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{
Guard.NotNull(source, nameof(source));
var interest = Rectangle.Intersect(source.Bounds(), bounds);
BufferRegion<TPixel> region = source.PixelBuffer.GetRegion(interest);
// Collect the palette. Required before the second pass runs.
quantizer.CollectPaletteColors(region);
var destination = new IndexedImageFrame<TPixel>(
quantizer.Configuration,
@ -78,6 +101,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
return destination;
}
internal static void BuildPalette<TPixel>(
this IQuantizer<TPixel> quantizer,
IPixelSamplingStrategy pixelSamplingStrategy,
Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
foreach (BufferRegion<TPixel> region in pixelSamplingStrategy.EnumeratePixelRegions(image))
{
quantizer.AddPaletteColors(region);
}
}
[MethodImpl(InliningOptions.ShortMethod)]
private static void SecondPass<TFrameQuantizer, TPixel>(
ref TFrameQuantizer quantizer,

6
src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs

@ -112,13 +112,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{
get
{
FrameQuantizerUtilities.CheckPaletteState(in this.palette);
QuantizerUtilities.CheckPaletteState(in this.palette);
return this.palette;
}
}
/// <inheritdoc/>
public void CollectPaletteColors(BufferRegion<TPixel> pixelRegion)
public void AddPaletteColors(BufferRegion<TPixel> pixelRegion)
{
Rectangle bounds = pixelRegion.Rectangle;
Buffer2D<TPixel> source = pixelRegion.Buffer;
@ -150,7 +150,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public readonly IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds)
=> FrameQuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
=> QuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
/// <inheritdoc/>
public readonly byte GetQuantizedColor(TPixel color, out TPixel match)

26
tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs

@ -134,27 +134,35 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
}
[Theory]
[WithFile(TestImages.Gif.GlobalQuantizationTest, PixelTypes.Rgba32)]
public void Encode_GlobalPalette_QuantizeMultipleFrames<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(TestImages.Gif.GlobalQuantizationTest, PixelTypes.Rgba32, 427500, 0.1)]
[WithFile(TestImages.Gif.GlobalQuantizationTest, PixelTypes.Rgba32, 200000, 0.1)]
[WithFile(TestImages.Gif.GlobalQuantizationTest, PixelTypes.Rgba32, 100000, 0.1)]
[WithFile(TestImages.Gif.GlobalQuantizationTest, PixelTypes.Rgba32, 50000, 0.1)]
[WithFile(TestImages.Gif.Cheers, PixelTypes.Rgba32, 4000000, 0.01)]
[WithFile(TestImages.Gif.Cheers, PixelTypes.Rgba32, 1000000, 0.01)]
public void Encode_GlobalPalette_DefaultPixelSamplingStrategy<TPixel>(TestImageProvider<TPixel> provider, int maxPixels, double scanRatio)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
var encoder = new GifEncoder()
{
ColorTableMode = GifColorTableMode.Global
ColorTableMode = GifColorTableMode.Global,
GlobalPixelSamplingStrategy = new DefaultPixelSamplingStrategy(maxPixels, scanRatio)
};
string testOutputFile = provider.Utility.SaveTestOutputFile(
image,
"gif",
encoder,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(testOutputFile);
using var encoded = Image.Load<TPixel>(testOutputFile, referenceDecoder);
ValidatorComparer.VerifySimilarity(image, encoded);
testOutputDetails: $"{maxPixels}_{scanRatio}",
appendPixelTypeToFileName: false);
// TODO: For proper regression testing of gifs, use a multi-frame reference output, or find a working reference decoder.
// IImageDecoder referenceDecoder = TestEnvironment.Ge
// ReferenceDecoder(testOutputFile);
// using var encoded = Image.Load<TPixel>(testOutputFile, referenceDecoder);
// ValidatorComparer.VerifySimilarity(image, encoded);
}
[Fact]

2
tests/ImageSharp.Tests/Quantization/PixelSamplingStrategyTests.cs

@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
{
using Image<L8> image = CreateTestImage(width, height, noOfFrames);
var strategy = new DefaultPixelSamplingStrategy(maximumNumberOfPixels);
var strategy = new DefaultPixelSamplingStrategy(maximumNumberOfPixels, 0.1);
long visitedPixels = 0;
foreach (BufferRegion<L8> region in strategy.EnumeratePixelRegions(image))

4
tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs

@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Tests
foreach (ImageFrame<TPixel> frame in image.Frames)
{
using (IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(this.Configuration))
using (IndexedImageFrame<TPixel> quantized = frameQuantizer.QuantizeFrame(frame, frame.Bounds()))
using (IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds()))
{
int index = this.GetTransparentIndex(quantized);
Assert.Equal(index, quantized.GetPixelRowSpan(0)[0]);
@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Tests
foreach (ImageFrame<TPixel> frame in image.Frames)
{
using (IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(this.Configuration))
using (IndexedImageFrame<TPixel> quantized = frameQuantizer.QuantizeFrame(frame, frame.Bounds()))
using (IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds()))
{
int index = this.GetTransparentIndex(quantized);
Assert.Equal(index, quantized.GetPixelRowSpan(0)[0]);

10
tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
ImageFrame<Rgba32> frame = image.Frames.RootFrame;
using IQuantizer<Rgba32> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<Rgba32>(config);
using IndexedImageFrame<Rgba32> result = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
using IndexedImageFrame<Rgba32> result = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
Assert.Equal(1, result.Palette.Length);
Assert.Equal(1, result.Width);
@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
ImageFrame<Rgba32> frame = image.Frames.RootFrame;
using IQuantizer<Rgba32> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<Rgba32>(config);
using IndexedImageFrame<Rgba32> result = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
using IndexedImageFrame<Rgba32> result = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
Assert.Equal(1, result.Palette.Length);
Assert.Equal(1, result.Width);
@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
ImageFrame<Rgba32> frame = image.Frames.RootFrame;
using IQuantizer<Rgba32> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<Rgba32>(config);
using IndexedImageFrame<Rgba32> result = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
using IndexedImageFrame<Rgba32> result = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
Assert.Equal(256, result.Palette.Length);
Assert.Equal(1, result.Width);
@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
ImageFrame<TPixel> frame = image.Frames.RootFrame;
using IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(config);
using IndexedImageFrame<TPixel> result = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
using IndexedImageFrame<TPixel> result = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
Assert.Equal(48, result.Palette.Length);
}
@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization
ImageFrame<Rgba32> frame = image.Frames.RootFrame;
using (IQuantizer<Rgba32> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<Rgba32>(config))
using (IndexedImageFrame<Rgba32> result = frameQuantizer.QuantizeFrame(frame, frame.Bounds()))
using (IndexedImageFrame<Rgba32> result = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds()))
{
Assert.Equal(4 * 8, result.Palette.Length);
Assert.Equal(1, result.Width);

Loading…
Cancel
Save