Browse Source

Revert "quantizer mess"

This reverts commit eab8a96236.
af/UniformUnmanagedMemoryPoolMemoryAllocator-02-MemoryGuards
Anton Firszov 5 years ago
parent
commit
8745f84ac3
  1. 8
      src/ImageSharp/Advanced/AotCompilerTools.cs
  2. 2
      src/ImageSharp/Processing/Processors/Dithering/ErroDither.KnownTypes.cs
  3. 26
      src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs
  4. 8
      src/ImageSharp/Processing/Processors/Dithering/IDither.cs
  5. 2
      src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs
  6. 31
      src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
  7. 4
      src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs
  8. 36
      src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs
  9. 16
      src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs
  10. 12
      src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs
  11. 16
      src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs
  12. 13
      src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs

8
src/ImageSharp/Advanced/AotCompilerTools.cs

@ -508,16 +508,16 @@ namespace SixLabors.ImageSharp.Advanced
[Preserve] [Preserve]
private static void AotCompileDither<TPixel, TDither>() private static void AotCompileDither<TPixel, TDither>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
where TDither : class, IDither where TDither : struct, IDither
{ {
var octree = default(OctreeQuantizer<TPixel>); var octree = default(OctreeQuantizer<TPixel>);
default(TDither).ApplyQuantizationDither<OctreeQuantizer<TPixel>, TPixel>(octree, default, default, default); default(TDither).ApplyQuantizationDither<OctreeQuantizer<TPixel>, TPixel>(ref octree, default, default, default);
var palette = default(PaletteQuantizer<TPixel>); var palette = default(PaletteQuantizer<TPixel>);
default(TDither).ApplyQuantizationDither<PaletteQuantizer<TPixel>, TPixel>(palette, default, default, default); default(TDither).ApplyQuantizationDither<PaletteQuantizer<TPixel>, TPixel>(ref palette, default, default, default);
var wu = default(WuQuantizer<TPixel>); var wu = default(WuQuantizer<TPixel>);
default(TDither).ApplyQuantizationDither<WuQuantizer<TPixel>, TPixel>(wu, default, default, default); default(TDither).ApplyQuantizationDither<WuQuantizer<TPixel>, TPixel>(ref wu, default, default, default);
default(TDither).ApplyPaletteDither<PaletteDitherProcessor<TPixel>.DitherProcessor, TPixel>(default, default, default); default(TDither).ApplyPaletteDither<PaletteDitherProcessor<TPixel>.DitherProcessor, TPixel>(default, default, default);
} }

2
src/ImageSharp/Processing/Processors/Dithering/ErroDither.KnownTypes.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <summary> /// <summary>
/// An error diffusion dithering implementation. /// An error diffusion dithering implementation.
/// </summary> /// </summary>
public partial class ErrorDither public readonly partial struct ErrorDither
{ {
/// <summary> /// <summary>
/// Applies error diffusion based dithering using the Atkinson image dithering algorithm. /// Applies error diffusion based dithering using the Atkinson image dithering algorithm.

26
src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs

@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// An error diffusion dithering implementation. /// An error diffusion dithering implementation.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/> /// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>
/// </summary> /// </summary>
public partial class ErrorDither : IDither, IEquatable<ErrorDither>, IEquatable<IDither> public readonly partial struct ErrorDither : IDither, IEquatable<ErrorDither>, IEquatable<IDither>
{ {
private readonly int offset; private readonly int offset;
private readonly DenseMatrix<float> matrix; private readonly DenseMatrix<float> matrix;
@ -91,17 +91,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void ApplyQuantizationDither<TFrameQuantizer, TPixel>( public void ApplyQuantizationDither<TFrameQuantizer, TPixel>(
TFrameQuantizer quantizer, ref TFrameQuantizer quantizer,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
IndexedImageFrame<TPixel> destination, IndexedImageFrame<TPixel> destination,
Rectangle bounds) Rectangle bounds)
where TFrameQuantizer : class, IQuantizer<TPixel> where TFrameQuantizer : struct, IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// if (this == default) if (this == default)
// { {
// ThrowDefaultInstance(); ThrowDefaultInstance();
// } }
int offsetY = bounds.Top; int offsetY = bounds.Top;
int offsetX = bounds.Left; int offsetX = bounds.Left;
@ -131,16 +131,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void ApplyPaletteDither<TPaletteDitherImageProcessor, TPixel>( public void ApplyPaletteDither<TPaletteDitherImageProcessor, TPixel>(
TPaletteDitherImageProcessor processor, in TPaletteDitherImageProcessor processor,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
Rectangle bounds) Rectangle bounds)
where TPaletteDitherImageProcessor : class, IPaletteDitherImageProcessor<TPixel> where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// if (this == default) if (this == default)
// { {
// ThrowDefaultInstance(); ThrowDefaultInstance();
// } }
Buffer2D<TPixel> sourceBuffer = source.PixelBuffer; Buffer2D<TPixel> sourceBuffer = source.PixelBuffer;
float scale = processor.DitherScale; float scale = processor.DitherScale;

8
src/ImageSharp/Processing/Processors/Dithering/IDither.cs

@ -22,11 +22,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <param name="destination">The destination quantized frame.</param> /// <param name="destination">The destination quantized frame.</param>
/// <param name="bounds">The region of interest bounds.</param> /// <param name="bounds">The region of interest bounds.</param>
void ApplyQuantizationDither<TFrameQuantizer, TPixel>( void ApplyQuantizationDither<TFrameQuantizer, TPixel>(
TFrameQuantizer quantizer, ref TFrameQuantizer quantizer,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
IndexedImageFrame<TPixel> destination, IndexedImageFrame<TPixel> destination,
Rectangle bounds) Rectangle bounds)
where TFrameQuantizer : class, IQuantizer<TPixel> where TFrameQuantizer : struct, IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel>; where TPixel : unmanaged, IPixel<TPixel>;
/// <summary> /// <summary>
@ -39,10 +39,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <param name="source">The source image.</param> /// <param name="source">The source image.</param>
/// <param name="bounds">The region of interest bounds.</param> /// <param name="bounds">The region of interest bounds.</param>
void ApplyPaletteDither<TPaletteDitherImageProcessor, TPixel>( void ApplyPaletteDither<TPaletteDitherImageProcessor, TPixel>(
TPaletteDitherImageProcessor processor, in TPaletteDitherImageProcessor processor,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
Rectangle bounds) Rectangle bounds)
where TPaletteDitherImageProcessor : class, IPaletteDitherImageProcessor<TPixel> where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor<TPixel>
where TPixel : unmanaged, IPixel<TPixel>; where TPixel : unmanaged, IPixel<TPixel>;
} }
} }

2
src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <content> /// <content>
/// An ordered dithering matrix with equal sides of arbitrary length /// An ordered dithering matrix with equal sides of arbitrary length
/// </content> /// </content>
public partial class OrderedDither public readonly partial struct OrderedDither
{ {
/// <summary> /// <summary>
/// Applies order dithering using the 2x2 Bayer dithering matrix. /// Applies order dithering using the 2x2 Bayer dithering matrix.

31
src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <summary> /// <summary>
/// An ordered dithering matrix with equal sides of arbitrary length /// An ordered dithering matrix with equal sides of arbitrary length
/// </summary> /// </summary>
public partial class OrderedDither : IDither, IEquatable<OrderedDither>, IEquatable<IDither> public readonly partial struct OrderedDither : IDither, IEquatable<OrderedDither>, IEquatable<IDither>
{ {
private readonly DenseMatrix<float> thresholdMatrix; private readonly DenseMatrix<float> thresholdMatrix;
private readonly int modulusX; private readonly int modulusX;
@ -105,17 +105,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void ApplyQuantizationDither<TFrameQuantizer, TPixel>( public void ApplyQuantizationDither<TFrameQuantizer, TPixel>(
TFrameQuantizer quantizer, ref TFrameQuantizer quantizer,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
IndexedImageFrame<TPixel> destination, IndexedImageFrame<TPixel> destination,
Rectangle bounds) Rectangle bounds)
where TFrameQuantizer : class, IQuantizer<TPixel> where TFrameQuantizer : struct, IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// if (this == default) if (this == default)
// { {
// ThrowDefaultInstance(); ThrowDefaultInstance();
// } }
int spread = CalculatePaletteSpread(destination.Palette.Length); int spread = CalculatePaletteSpread(destination.Palette.Length);
float scale = quantizer.Options.DitherScale; float scale = quantizer.Options.DitherScale;
@ -134,24 +134,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
} }
} }
// public void ApplyQuantizationDither<TFrameQuantizer, TPixel>(TFrameQuantizer quantizer, ImageFrame<TPixel> source,
// IndexedImageFrame<TPixel> destination, Rectangle bounds)
// where TFrameQuantizer : class, IQuantizer<TPixel> where TPixel : unmanaged, IPixel<TPixel> =>
// throw new NotImplementedException();
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void ApplyPaletteDither<TPaletteDitherImageProcessor, TPixel>( public void ApplyPaletteDither<TPaletteDitherImageProcessor, TPixel>(
TPaletteDitherImageProcessor processor, in TPaletteDitherImageProcessor processor,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
Rectangle bounds) Rectangle bounds)
where TPaletteDitherImageProcessor : class, IPaletteDitherImageProcessor<TPixel> where TPaletteDitherImageProcessor : struct, IPaletteDitherImageProcessor<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// if (this == default) if (this == default)
// { {
// ThrowDefaultInstance(); ThrowDefaultInstance();
// } }
int spread = CalculatePaletteSpread(processor.Palette.Length); int spread = CalculatePaletteSpread(processor.Palette.Length);
float scale = processor.DitherScale; float scale = processor.DitherScale;

4
src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs

@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
protected override void OnFrameApply(ImageFrame<TPixel> source) protected override void OnFrameApply(ImageFrame<TPixel> source)
{ {
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
this.dither.ApplyPaletteDither(this.ditherProcessor, source, interest); this.dither.ApplyPaletteDither(in this.ditherProcessor, source, interest);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <see cref="IPaletteDitherImageProcessor{TPixel}.GetPaletteColor(TPixel)"/>. /// <see cref="IPaletteDitherImageProcessor{TPixel}.GetPaletteColor(TPixel)"/>.
/// </summary> /// </summary>
/// <remarks>Internal for AOT</remarks> /// <remarks>Internal for AOT</remarks>
internal class DitherProcessor : IPaletteDitherImageProcessor<TPixel>, IDisposable internal readonly struct DitherProcessor : IPaletteDitherImageProcessor<TPixel>, IDisposable
{ {
private readonly EuclideanPixelMap<TPixel> pixelMap; private readonly EuclideanPixelMap<TPixel> pixelMap;

36
src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs

@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
private Rgba32[] rgbaPalette; private Rgba32[] rgbaPalette;
private ColorDistanceCache cache; private readonly ColorDistanceCache cache;
private readonly Configuration configuration; private readonly Configuration configuration;
/// <summary> /// <summary>
@ -136,13 +136,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
return (deltaR * deltaR) + (deltaG * deltaG) + (deltaB * deltaB) + (deltaA * deltaA); return (deltaR * deltaR) + (deltaG * deltaG) + (deltaB * deltaB) + (deltaA * deltaA);
} }
public void Dispose() public void Dispose() => this.cache.Dispose();
{
this.cache.Dispose();
GC.SuppressFinalize(this);
}
~EuclideanPixelMap() => throw new Exception("very bad");
/// <summary> /// <summary>
/// A cache for storing color distance matching results. /// A cache for storing color distance matching results.
@ -155,7 +149,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Entry count is currently limited to 1185921 entries (2371842 bytes ~2.26MB). /// Entry count is currently limited to 1185921 entries (2371842 bytes ~2.26MB).
/// </para> /// </para>
/// </remarks> /// </remarks>
private class ColorDistanceCache : IDisposable private unsafe struct ColorDistanceCache : IDisposable
{ {
private const int IndexBits = 5; private const int IndexBits = 5;
private const int IndexAlphaBits = 5; private const int IndexAlphaBits = 5;
@ -164,18 +158,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
private const int RgbShift = 8 - IndexBits; private const int RgbShift = 8 - IndexBits;
private const int AlphaShift = 8 - IndexAlphaBits; private const int AlphaShift = 8 - IndexAlphaBits;
private const int Entries = IndexCount * IndexCount * IndexCount * IndexAlphaCount; private const int Entries = IndexCount * IndexCount * IndexCount * IndexAlphaCount;
// private MemoryHandle tableHandle; private MemoryHandle tableHandle;
private readonly IMemoryOwner<short> table; private readonly IMemoryOwner<short> table;
// private readonly short* tablePointer; private readonly short* tablePointer;
private Memory<short> tableMemory;
public ColorDistanceCache(MemoryAllocator allocator) public ColorDistanceCache(MemoryAllocator allocator)
{ {
this.table = allocator.Allocate<short>(Entries); this.table = allocator.Allocate<short>(Entries);
this.table.GetSpan().Fill(-1); this.table.GetSpan().Fill(-1);
this.tableMemory = this.table.Memory; this.tableHandle = this.table.Memory.Pin();
// this.tableHandle = this.table.Memory.Pin(); this.tablePointer = (short*)this.tableHandle.Pointer;
// this.tablePointer = (short*)this.tableHandle.Pointer;
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
@ -186,8 +178,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
int b = rgba.B >> RgbShift; int b = rgba.B >> RgbShift;
int a = rgba.A >> AlphaShift; int a = rgba.A >> AlphaShift;
int idx = GetPaletteIndex(r, g, b, a); int idx = GetPaletteIndex(r, g, b, a);
// this.tablePointer[idx] = index; this.tablePointer[idx] = index;
this.table.Memory.Span[idx] = index;
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
@ -198,8 +189,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
int b = rgba.B >> RgbShift; int b = rgba.B >> RgbShift;
int a = rgba.A >> AlphaShift; int a = rgba.A >> AlphaShift;
int idx = GetPaletteIndex(r, g, b, a); int idx = GetPaletteIndex(r, g, b, a);
// match = this.tablePointer[idx]; match = this.tablePointer[idx];
match = this.tableMemory.Span[idx];
return match > -1; return match > -1;
} }
@ -224,15 +214,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{ {
if (this.table != null) if (this.table != null)
{ {
// this.tableHandle.Dispose(); this.tableHandle.Dispose();
this.table.Dispose(); this.table.Dispose();
} }
GC.SuppressFinalize(this);
}
~ColorDistanceCache()
{
throw new Exception("very bad");
} }
} }
} }

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

@ -5,7 +5,6 @@ using System;
using System.Buffers; using System.Buffers;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -17,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/> /// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/>
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
public class OctreeQuantizer<TPixel> : IQuantizer<TPixel> public struct OctreeQuantizer<TPixel> : IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
private readonly int maxColors; private readonly int maxColors;
@ -53,11 +52,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.isDisposed = false; this.isDisposed = false;
} }
~OctreeQuantizer()
{
throw new Exception("Very bad");
}
/// <inheritdoc/> /// <inheritdoc/>
public Configuration Configuration { get; } public Configuration Configuration { get; }
@ -132,12 +126,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds) public readonly IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds)
=> QuantizerUtilities.QuantizeFrame(this, source, bounds); => QuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public byte GetQuantizedColor(TPixel color, out TPixel match) public readonly byte GetQuantizedColor(TPixel color, out TPixel match)
{ {
// Octree only maps the RGB component of a color // Octree only maps the RGB component of a color
// so cannot tell the difference between a fully transparent // so cannot tell the difference between a fully transparent
@ -164,8 +158,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.pixelMap?.Dispose(); this.pixelMap?.Dispose();
this.pixelMap = null; this.pixelMap = null;
} }
GC.SuppressFinalize(this);
} }
/// <summary> /// <summary>

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

@ -3,7 +3,6 @@
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -14,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/> /// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/>
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
internal class PaletteQuantizer<TPixel> : IQuantizer<TPixel> internal struct PaletteQuantizer<TPixel> : IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
private EuclideanPixelMap<TPixel> pixelMap; private EuclideanPixelMap<TPixel> pixelMap;
@ -36,8 +35,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.pixelMap = new EuclideanPixelMap<TPixel>(configuration, palette); this.pixelMap = new EuclideanPixelMap<TPixel>(configuration, palette);
} }
~PaletteQuantizer() => throw new Exception("Very bad");
/// <inheritdoc/> /// <inheritdoc/>
public Configuration Configuration { get; } public Configuration Configuration { get; }
@ -49,8 +46,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds) public readonly IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds)
=> QuantizerUtilities.QuantizeFrame(this, source, bounds); => QuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
@ -60,7 +57,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public byte GetQuantizedColor(TPixel color, out TPixel match) public readonly byte GetQuantizedColor(TPixel color, out TPixel match)
=> (byte)this.pixelMap.GetClosestColor(color, out match); => (byte)this.pixelMap.GetClosestColor(color, out match);
/// <inheritdoc/> /// <inheritdoc/>
@ -68,7 +65,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{ {
this.pixelMap?.Dispose(); this.pixelMap?.Dispose();
this.pixelMap = null; this.pixelMap = null;
GC.SuppressFinalize(this);
} }
} }
} }

16
src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs

@ -71,10 +71,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// A <see cref="IndexedImageFrame{TPixel}"/> representing a quantized version of the source frame pixels. /// A <see cref="IndexedImageFrame{TPixel}"/> representing a quantized version of the source frame pixels.
/// </returns> /// </returns>
public static IndexedImageFrame<TPixel> QuantizeFrame<TFrameQuantizer, TPixel>( public static IndexedImageFrame<TPixel> QuantizeFrame<TFrameQuantizer, TPixel>(
TFrameQuantizer quantizer, ref TFrameQuantizer quantizer,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
Rectangle bounds) Rectangle bounds)
where TFrameQuantizer : class, IQuantizer<TPixel> where TFrameQuantizer : struct, IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(source, nameof(source)); Guard.NotNull(source, nameof(source));
@ -88,13 +88,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
if (quantizer.Options.Dither is null) if (quantizer.Options.Dither is null)
{ {
SecondPass(quantizer, source, destination, interest); SecondPass(ref quantizer, source, destination, interest);
} }
else else
{ {
// We clone the image as we don't want to alter the original via error diffusion based dithering. // We clone the image as we don't want to alter the original via error diffusion based dithering.
using ImageFrame<TPixel> clone = source.Clone(); using ImageFrame<TPixel> clone = source.Clone();
SecondPass(quantizer, clone, destination, interest); SecondPass(ref quantizer, clone, destination, interest);
} }
return destination; return destination;
@ -114,11 +114,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
private static void SecondPass<TFrameQuantizer, TPixel>( private static void SecondPass<TFrameQuantizer, TPixel>(
TFrameQuantizer quantizer, ref TFrameQuantizer quantizer,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
IndexedImageFrame<TPixel> destination, IndexedImageFrame<TPixel> destination,
Rectangle bounds) Rectangle bounds)
where TFrameQuantizer : class, IQuantizer<TPixel> where TFrameQuantizer : struct, IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
IDither dither = quantizer.Options.Dither; IDither dither = quantizer.Options.Dither;
@ -136,14 +136,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
for (int x = bounds.Left; x < bounds.Right; x++) for (int x = bounds.Left; x < bounds.Right; x++)
{ {
destinationRow[x - offsetX] = quantizer.GetQuantizedColor(sourceRow[x], out TPixel _); destinationRow[x - offsetX] = Unsafe.AsRef(quantizer).GetQuantizedColor(sourceRow[x], out TPixel _);
} }
} }
return; return;
} }
dither.ApplyQuantizationDither(quantizer, source, destination, bounds); dither.ApplyQuantizationDither(ref quantizer, source, destination, bounds);
} }
} }
} }

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

@ -5,7 +5,6 @@ using System;
using System.Buffers; using System.Buffers;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -32,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
internal class WuQuantizer<TPixel> : IQuantizer<TPixel> internal struct WuQuantizer<TPixel> : IQuantizer<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
private readonly MemoryAllocator memoryAllocator; private readonly MemoryAllocator memoryAllocator;
@ -101,8 +100,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.isDithering = this.isDithering = !(this.Options.Dither is null); this.isDithering = this.isDithering = !(this.Options.Dither is null);
} }
~WuQuantizer() => throw new Exception("very bad");
/// <inheritdoc/> /// <inheritdoc/>
public Configuration Configuration { get; } public Configuration Configuration { get; }
@ -165,11 +162,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds) public readonly IndexedImageFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> source, Rectangle bounds)
=> QuantizerUtilities.QuantizeFrame(this, source, bounds); => QuantizerUtilities.QuantizeFrame(ref Unsafe.AsRef(this), source, bounds);
/// <inheritdoc/> /// <inheritdoc/>
public byte GetQuantizedColor(TPixel color, out TPixel match) public readonly byte GetQuantizedColor(TPixel color, out TPixel match)
{ {
if (this.isDithering) if (this.isDithering)
{ {
@ -206,8 +203,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.pixelMap?.Dispose(); this.pixelMap?.Dispose();
this.pixelMap = null; this.pixelMap = null;
} }
GC.SuppressFinalize(this);
} }
/// <summary> /// <summary>

Loading…
Cancel
Save