From 2e6ac845ed3f5c290c4590c966614bd1a272724b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 26 Aug 2020 15:14:08 +0100 Subject: [PATCH 01/11] Encode then decode. --- src/ImageSharp/Advanced/AotCompilerTools.cs | 73 +++++++++------------ 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 2ea456286f..dc0c59e7bf 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -3,12 +3,12 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -27,14 +27,14 @@ namespace SixLabors.ImageSharp.Advanced { static AotCompilerTools() { - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); } /// @@ -90,10 +90,7 @@ namespace SixLabors.ImageSharp.Advanced Unsafe.SizeOf(); - AotCodec(new Formats.Png.PngDecoder(), new Formats.Png.PngEncoder()); - AotCodec(new Formats.Bmp.BmpDecoder(), new Formats.Bmp.BmpEncoder()); - AotCodec(new Formats.Gif.GifDecoder(), new Formats.Gif.GifEncoder()); - AotCodec(new Formats.Jpeg.JpegDecoder(), new Formats.Jpeg.JpegEncoder()); + AotCodecs(); // TODO: Do the discovery work to figure out what works and what doesn't. } @@ -112,11 +109,9 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileOctreeQuantizer() where TPixel : unmanaged, IPixel { - using (var test = new OctreeQuantizer(Configuration.Default, new OctreeQuantizer().Options)) - { - var frame = new ImageFrame(Configuration.Default, 1, 1); - test.QuantizeFrame(frame, frame.Bounds()); - } + using var test = new OctreeQuantizer(Configuration.Default, new OctreeQuantizer().Options); + var frame = new ImageFrame(Configuration.Default, 1, 1); + test.QuantizeFrame(frame, frame.Bounds()); } /// @@ -126,11 +121,9 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileWuQuantizer() where TPixel : unmanaged, IPixel { - using (var test = new WuQuantizer(Configuration.Default, new WuQuantizer().Options)) - { - var frame = new ImageFrame(Configuration.Default, 1, 1); - test.QuantizeFrame(frame, frame.Bounds()); - } + using var test = new WuQuantizer(Configuration.Default, new WuQuantizer().Options); + var frame = new ImageFrame(Configuration.Default, 1, 1); + test.QuantizeFrame(frame, frame.Bounds()); } /// @@ -140,11 +133,9 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompilePaletteQuantizer() where TPixel : unmanaged, IPixel { - using (var test = (PaletteQuantizer)new PaletteQuantizer(Array.Empty()).CreatePixelSpecificQuantizer(Configuration.Default)) - { - var frame = new ImageFrame(Configuration.Default, 1, 1); - test.QuantizeFrame(frame, frame.Bounds()); - } + using var test = (PaletteQuantizer)new PaletteQuantizer(Array.Empty()).CreatePixelSpecificQuantizer(Configuration.Default); + var frame = new ImageFrame(Configuration.Default, 1, 1); + test.QuantizeFrame(frame, frame.Bounds()); } /// @@ -167,26 +158,22 @@ namespace SixLabors.ImageSharp.Advanced /// /// This method pre-seeds the decoder and encoder for a given pixel format in the AoT compiler for iOS. /// - /// The image decoder to seed. - /// The image encoder to seed. /// The pixel format. - private static void AotCodec(IImageDecoder decoder, IImageEncoder encoder) + private static void AotCodecs() where TPixel : unmanaged, IPixel { - try + Configuration configuration = Configuration.Default; + ImageFormatManager formatsManager = configuration.ImageFormatsManager; + foreach (IImageFormat imageFormat in configuration.ImageFormats) { - decoder.Decode(Configuration.Default, null); - } - catch - { - } + using var ms = new MemoryStream(); + using (var encoded = new Image(1, 1)) + { + encoded.Save(ms, formatsManager.FindEncoder(imageFormat)); + ms.Position = 0; + } - try - { - encoder.Encode(null, null); - } - catch - { + using var decoded = Image.Load(ms); } } From 0fa3921de620b49778e250d2a6b88a6a8a6dd9be Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 7 Sep 2020 12:36:18 +0100 Subject: [PATCH 02/11] Add all IPixel interface methods. --- src/ImageSharp/Advanced/AotCompilerTools.cs | 27 ++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index dc0c59e7bf..666eb513f1 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -82,6 +82,7 @@ namespace SixLabors.ImageSharp.Advanced where TPixel : unmanaged, IPixel { // This is we actually call all the individual methods you need to seed. + AotPixelInterface(); AotCompileOctreeQuantizer(); AotCompileWuQuantizer(); AotCompilePaletteQuantizer(); @@ -95,6 +96,30 @@ namespace SixLabors.ImageSharp.Advanced // TODO: Do the discovery work to figure out what works and what doesn't. } + private static void AotPixelInterface() + where TPixel : unmanaged, IPixel + { + TPixel pixel = default; + Rgba32 rgba32 = default; + pixel.ToRgba32(ref rgba32); + pixel.FromRgba32(rgba32); + pixel.FromScaledVector4(pixel.ToScaledVector4()); + pixel.FromVector4(pixel.ToVector4()); + + pixel.FromArgb32(default); + pixel.FromBgr24(default); + pixel.FromBgra32(default); + pixel.FromBgra5551(default); + pixel.FromL16(default); + pixel.FromL8(default); + pixel.FromLa16(default); + pixel.FromLa32(default); + pixel.FromRgb24(default); + pixel.FromRgb48(default); + pixel.FromRgba64(default); + pixel.FromRgb24(default); + } + /// /// This method doesn't actually do anything but serves an important purpose... /// If you are running ImageSharp on iOS and try to call SaveAsGif, it will throw an exception: @@ -107,7 +132,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. private static void AotCompileOctreeQuantizer() - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, IPixel { using var test = new OctreeQuantizer(Configuration.Default, new OctreeQuantizer().Options); var frame = new ImageFrame(Configuration.Default, 1, 1); From 65d103ed65f99b8ce1ef52d0f1164cfa8de4a810 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 8 Sep 2020 08:53:50 +0100 Subject: [PATCH 03/11] Update AotCompilerTools.cs --- src/ImageSharp/Advanced/AotCompilerTools.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 666eb513f1..ed23cd445a 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -198,7 +198,8 @@ namespace SixLabors.ImageSharp.Advanced ms.Position = 0; } - using var decoded = Image.Load(ms); + using var decoded = Image.Load(ms); + Span span = decoded.GetPixelRowSpan(0); } } From 72960ec97949d87a7ed4a74316fe6595450c3028 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 1 Mar 2021 14:42:51 +0000 Subject: [PATCH 04/11] Fix ordered dither output for small palette lengths. --- src/ImageSharp/ImageSharp.csproj | 4 +- src/ImageSharp/Processing/KnownDitherings.cs | 5 ++ .../Processors/Dithering/ErrorDither.cs | 31 ++++---- .../Dithering/OrderedDither.KnownTypes.cs | 5 ++ .../Processors/Dithering/OrderedDither.cs | 75 ++++++++++--------- .../Processors/Dithering/DitherTests.cs | 1 + .../Processors/Quantization/QuantizerTests.cs | 2 +- .../TestUtilities/TestUtils.cs | 2 +- 8 files changed, 71 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index ca6ca16898..832d551fd7 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -31,8 +31,8 @@ - - + + diff --git a/src/ImageSharp/Processing/KnownDitherings.cs b/src/ImageSharp/Processing/KnownDitherings.cs index 1c086b7408..9537acda18 100644 --- a/src/ImageSharp/Processing/KnownDitherings.cs +++ b/src/ImageSharp/Processing/KnownDitherings.cs @@ -30,6 +30,11 @@ namespace SixLabors.ImageSharp.Processing /// public static IDither Bayer8x8 { get; } = OrderedDither.Bayer8x8; + /// + /// Gets the order ditherer using the 16x16 Bayer dithering matrix + /// + public static IDither Bayer16x16 { get; } = OrderedDither.Bayer16x16; + /// /// Gets the error Dither that implements the Atkinson algorithm. /// diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs index 30ac5f135b..b853fcb669 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// The diffusion matrix. /// The starting offset within the matrix. - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ErrorDither(in DenseMatrix matrix, int offset) { this.matrix = matrix; @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => !(left == right); /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ApplyQuantizationDither( ref TFrameQuantizer quantizer, ImageFrame source, @@ -96,26 +96,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering where TFrameQuantizer : struct, IQuantizer where TPixel : unmanaged, IPixel { - int offsetY = bounds.Top; - int offsetX = bounds.Left; float scale = quantizer.Options.DitherScale; for (int y = bounds.Top; y < bounds.Bottom; y++) { - ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); - ref byte destinationRowRef = ref MemoryMarshal.GetReference(destination.GetWritablePixelRowSpanUnsafe(y - offsetY)); + ReadOnlySpan sourceRow = source.GetPixelRowSpan(y).Slice(bounds.X, bounds.Width); + Span destRow = + destination.GetWritablePixelRowSpanUnsafe(y - bounds.Y).Slice(0, sourceRow.Length); - for (int x = bounds.Left; x < bounds.Right; x++) + for (int x = 0; x < sourceRow.Length; x++) { - TPixel sourcePixel = Unsafe.Add(ref sourceRowRef, x); - Unsafe.Add(ref destinationRowRef, x - offsetX) = quantizer.GetQuantizedColor(sourcePixel, out TPixel transformed); + TPixel sourcePixel = sourceRow[x]; + destRow[x] = quantizer.GetQuantizedColor(sourcePixel, out TPixel transformed); this.Dither(source, bounds, sourcePixel, transformed, x, y, scale); } } } /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ApplyPaletteDither( in TPaletteDitherImageProcessor processor, ImageFrame source, @@ -124,13 +123,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering where TPixel : unmanaged, IPixel { float scale = processor.DitherScale; + for (int y = bounds.Top; y < bounds.Bottom; y++) { - ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); - for (int x = bounds.Left; x < bounds.Right; x++) + Span row = source.GetPixelRowSpan(y).Slice(bounds.X, bounds.Width); + + for (int x = 0; x < row.Length; x++) { - ref TPixel sourcePixel = ref Unsafe.Add(ref sourceRowRef, x); - TPixel transformed = Unsafe.AsRef(processor).GetPaletteColor(sourcePixel); + ref TPixel sourcePixel = ref row[x]; + TPixel transformed = processor.GetPaletteColor(sourcePixel); this.Dither(source, bounds, sourcePixel, transformed, x, y, scale); sourcePixel = transformed; } @@ -138,7 +139,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering } // Internal for AOT - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal TPixel Dither( ImageFrame image, Rectangle bounds, diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs index 71ad6db973..1934604522 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs @@ -23,6 +23,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// public static OrderedDither Bayer8x8 = new OrderedDither(8); + /// + /// Applies order dithering using the 16x16 Bayer dithering matrix. + /// + public static OrderedDither Bayer16x16 = new OrderedDither(16); + /// /// Applies order dithering using the 3x3 ordered dithering matrix. /// diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs index 9b99a5257d..a89d23cc00 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -23,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Initializes a new instance of the struct. /// /// The length of the matrix sides - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public OrderedDither(uint length) { DenseMatrix ditherMatrix = OrderedDitherFactory.CreateDitherMatrix(length); @@ -102,7 +101,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => !(left == right); /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ApplyQuantizationDither( ref TFrameQuantizer quantizer, ImageFrame source, @@ -125,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering } /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ApplyPaletteDither( in TPaletteDitherImageProcessor processor, ImageFrame source, @@ -145,24 +144,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering in ditherOperation); } - [MethodImpl(InliningOptions.ShortMethod)] + // Spread assumes an even colorspace distribution and precision. + // Cubed root used because we always compare to Rgb. + // https://bisqwit.iki.fi/story/howto/dither/jy/ + // https://en.wikipedia.org/wiki/Ordered_dithering#Algorithm + internal static int CalculatePaletteSpread(int colors) => (int)(255 / (Math.Pow(colors, 1.0 / 3) - 1)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal TPixel Dither( TPixel source, int x, int y, - int bitDepth, + int spread, float scale) where TPixel : unmanaged, IPixel { - Rgba32 rgba = default; + Unsafe.SkipInit(out Rgba32 rgba); source.ToRgba32(ref rgba); - Rgba32 attempt; + Unsafe.SkipInit(out Rgba32 attempt); - // Spread assumes an even colorspace distribution and precision. - // Calculated as 0-255/component count. 256 / bitDepth - // https://bisqwit.iki.fi/story/howto/dither/jy/ - // https://en.wikipedia.org/wiki/Ordered_dithering#Algorithm - int spread = 256 / bitDepth; float factor = spread * this.thresholdMatrix[y % this.modulusY, x % this.modulusX] * scale; attempt.R = (byte)Numerics.Clamp(rgba.R + factor, byte.MinValue, byte.MaxValue); @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => obj is OrderedDither dither && this.Equals(dither); /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(OrderedDither other) => this.thresholdMatrix.Equals(other.thresholdMatrix) && this.modulusX == other.modulusX && this.modulusY == other.modulusY; @@ -190,7 +190,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => this.Equals((object)other); /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => HashCode.Combine(this.thresholdMatrix, this.modulusX, this.modulusY); @@ -203,9 +203,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly ImageFrame source; private readonly IndexedImageFrame destination; private readonly Rectangle bounds; - private readonly int bitDepth; + private readonly int spread; - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public QuantizeDitherRowOperation( ref TFrameQuantizer quantizer, in OrderedDither dither, @@ -218,23 +218,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering this.source = source; this.destination = destination; this.bounds = bounds; - this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(destination.Palette.Length); + this.spread = CalculatePaletteSpread(destination.Palette.Length); } - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(int y) { - int offsetY = this.bounds.Top; - int offsetX = this.bounds.Left; + ref TFrameQuantizer quantizer = ref Unsafe.AsRef(this.quantizer); + int spread = this.spread; float scale = this.quantizer.Options.DitherScale; - ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); - ref byte destinationRowRef = ref MemoryMarshal.GetReference(this.destination.GetWritablePixelRowSpanUnsafe(y - offsetY)); + ReadOnlySpan sourceRow = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); + Span destRow = + this.destination.GetWritablePixelRowSpanUnsafe(y - this.bounds.Y).Slice(0, sourceRow.Length); - for (int x = this.bounds.Left; x < this.bounds.Right; x++) + for (int x = 0; x < sourceRow.Length; x++) { - TPixel dithered = this.dither.Dither(Unsafe.Add(ref sourceRowRef, x), x, y, this.bitDepth, scale); - Unsafe.Add(ref destinationRowRef, x - offsetX) = Unsafe.AsRef(this.quantizer).GetQuantizedColor(dithered, out TPixel _); + TPixel dithered = this.dither.Dither(sourceRow[x], x, y, spread, scale); + destRow[x] = quantizer.GetQuantizedColor(dithered, out TPixel _); } } } @@ -248,9 +249,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly ImageFrame source; private readonly Rectangle bounds; private readonly float scale; - private readonly int bitDepth; + private readonly int spread; - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public PaletteDitherRowOperation( in TPaletteDitherImageProcessor processor, in OrderedDither dither, @@ -262,19 +263,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering this.source = source; this.bounds = bounds; this.scale = processor.DitherScale; - this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(processor.Palette.Length); + this.spread = CalculatePaletteSpread(processor.Palette.Length); } - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(int y) { - ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); + ref TPaletteDitherImageProcessor processor = ref Unsafe.AsRef(this.processor); + int spread = this.spread; + float scale = this.scale; + + Span row = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); - for (int x = this.bounds.Left; x < this.bounds.Right; x++) + for (int x = 0; x < row.Length; x++) { - ref TPixel sourcePixel = ref Unsafe.Add(ref sourceRowRef, x); - TPixel dithered = this.dither.Dither(sourcePixel, x, y, this.bitDepth, this.scale); - sourcePixel = Unsafe.AsRef(this.processor).GetPaletteColor(dithered); + ref TPixel sourcePixel = ref row[x]; + TPixel dithered = this.dither.Dither(sourcePixel, x, y, spread, scale); + sourcePixel = processor.GetPaletteColor(dithered); } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index adc3c381a0..5c1b5da7f1 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -37,6 +37,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { KnownDitherings.Bayer2x2, nameof(KnownDitherings.Bayer2x2) }, { KnownDitherings.Bayer4x4, nameof(KnownDitherings.Bayer4x4) }, { KnownDitherings.Bayer8x8, nameof(KnownDitherings.Bayer8x8) }, + { KnownDitherings.Bayer16x16, nameof(KnownDitherings.Bayer16x16) }, { KnownDitherings.Ordered3x3, nameof(KnownDitherings.Ordered3x3) } }; diff --git a/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs index a25eca5b02..3f4656d411 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs @@ -169,8 +169,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Quantization provider.RunRectangleConstrainedValidatingProcessorTest( (x, rect) => x.Quantize(quantizer, rect), - comparer: ValidatorComparer, testOutputDetails: testOutputDetails, + comparer: ValidatorComparer, appendPixelTypeToFileName: false); } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index 39ebf7f159..5f41021a06 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.Tests using (Image image = provider.GetImage()) { FormattableString testOutputDetails = $""; - image.Mutate(ctx => { testOutputDetails = processAndGetTestOutputDetails(ctx); }); + image.Mutate(ctx => testOutputDetails = processAndGetTestOutputDetails(ctx)); image.DebugSave( provider, From a54bce1faa4e7b45717b39e040658a6a543c3ff2 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 1 Mar 2021 16:41:10 +0000 Subject: [PATCH 05/11] Update refs. --- .../Processors/Dithering/ErrorDither.cs | 32 +++++++++---------- ...erFilterInBox_Rgba32_CalliphoraPartial.png | 4 +-- ...DependOnSinglePixelType_Bgra32_filter0.png | 4 +-- ...tDependOnSinglePixelType_Rgb24_filter0.png | 4 +-- ...DependOnSinglePixelType_Rgba32_filter0.png | 4 +-- ...ndOnSinglePixelType_RgbaVector_filter0.png | 4 +-- ..._WorksWithAllDitherers_Bike_Bayer16x16.png | 3 ++ ...er_WorksWithAllDitherers_Bike_Bayer2x2.png | 4 +-- ...er_WorksWithAllDitherers_Bike_Bayer4x4.png | 4 +-- ...er_WorksWithAllDitherers_Bike_Bayer8x8.png | 4 +-- ..._WorksWithAllDitherers_Bike_Ordered3x3.png | 4 +-- ...Ditherers_CalliphoraPartial_Bayer16x16.png | 3 ++ ...llDitherers_CalliphoraPartial_Bayer2x2.png | 4 +-- ...llDitherers_CalliphoraPartial_Bayer4x4.png | 4 +-- ...llDitherers_CalliphoraPartial_Bayer8x8.png | 4 +-- ...Ditherers_CalliphoraPartial_Ordered3x3.png | 4 +-- ...Box_Bike_OctreeQuantizer_OrderedDither.png | 4 +-- ..._WebSafePaletteQuantizer_OrderedDither.png | 4 +-- ...e_WernerPaletteQuantizer_OrderedDither.png | 4 +-- ...onInBox_Bike_WuQuantizer_OrderedDither.png | 4 +-- ...aPartial_OctreeQuantizer_OrderedDither.png | 4 +-- ..._WebSafePaletteQuantizer_OrderedDither.png | 4 +-- ...l_WernerPaletteQuantizer_OrderedDither.png | 4 +-- ...phoraPartial_WuQuantizer_OrderedDither.png | 4 +-- ...vid_OctreeQuantizer_OrderedDither_0.25.png | 4 +-- ...avid_OctreeQuantizer_OrderedDither_0.5.png | 4 +-- ...vid_OctreeQuantizer_OrderedDither_0.75.png | 4 +-- ..._david_OctreeQuantizer_OrderedDither_1.png | 4 +-- ...afePaletteQuantizer_OrderedDither_0.25.png | 4 +-- ...SafePaletteQuantizer_OrderedDither_0.5.png | 4 +-- ...afePaletteQuantizer_OrderedDither_0.75.png | 4 +-- ...ebSafePaletteQuantizer_OrderedDither_1.png | 4 +-- ...nerPaletteQuantizer_OrderedDither_0.25.png | 4 +-- ...rnerPaletteQuantizer_OrderedDither_0.5.png | 4 +-- ...nerPaletteQuantizer_OrderedDither_0.75.png | 4 +-- ...WernerPaletteQuantizer_OrderedDither_1.png | 4 +-- ...e_david_WuQuantizer_OrderedDither_0.25.png | 4 +-- ...le_david_WuQuantizer_OrderedDither_0.5.png | 4 +-- ...e_david_WuQuantizer_OrderedDither_0.75.png | 4 +-- ...cale_david_WuQuantizer_OrderedDither_1.png | 4 +-- ...ion_Bike_OctreeQuantizer_OrderedDither.png | 4 +-- ..._WebSafePaletteQuantizer_OrderedDither.png | 4 +-- ...e_WernerPaletteQuantizer_OrderedDither.png | 4 +-- ...ization_Bike_WuQuantizer_OrderedDither.png | 4 +-- ...aPartial_OctreeQuantizer_OrderedDither.png | 4 +-- ..._WebSafePaletteQuantizer_OrderedDither.png | 4 +-- ...l_WernerPaletteQuantizer_OrderedDither.png | 4 +-- ...phoraPartial_WuQuantizer_OrderedDither.png | 4 +-- 48 files changed, 111 insertions(+), 107 deletions(-) create mode 100644 tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png create mode 100644 tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs index b853fcb669..1a107c2cfd 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs @@ -5,7 +5,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -25,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// The diffusion matrix. /// The starting offset within the matrix. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public ErrorDither(in DenseMatrix matrix, int offset) { this.matrix = matrix; @@ -87,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => !(left == right); /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void ApplyQuantizationDither( ref TFrameQuantizer quantizer, ImageFrame source, @@ -96,25 +95,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering where TFrameQuantizer : struct, IQuantizer where TPixel : unmanaged, IPixel { + int offsetY = bounds.Top; + int offsetX = bounds.Left; float scale = quantizer.Options.DitherScale; for (int y = bounds.Top; y < bounds.Bottom; y++) { - ReadOnlySpan sourceRow = source.GetPixelRowSpan(y).Slice(bounds.X, bounds.Width); - Span destRow = - destination.GetWritablePixelRowSpanUnsafe(y - bounds.Y).Slice(0, sourceRow.Length); + ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); + ref byte destinationRowRef = ref MemoryMarshal.GetReference(destination.GetWritablePixelRowSpanUnsafe(y - offsetY)); - for (int x = 0; x < sourceRow.Length; x++) + for (int x = bounds.Left; x < bounds.Right; x++) { - TPixel sourcePixel = sourceRow[x]; - destRow[x] = quantizer.GetQuantizedColor(sourcePixel, out TPixel transformed); + TPixel sourcePixel = Unsafe.Add(ref sourceRowRef, x); + Unsafe.Add(ref destinationRowRef, x - offsetX) = quantizer.GetQuantizedColor(sourcePixel, out TPixel transformed); this.Dither(source, bounds, sourcePixel, transformed, x, y, scale); } } } /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void ApplyPaletteDither( in TPaletteDitherImageProcessor processor, ImageFrame source, @@ -123,15 +123,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering where TPixel : unmanaged, IPixel { float scale = processor.DitherScale; - for (int y = bounds.Top; y < bounds.Bottom; y++) { - Span row = source.GetPixelRowSpan(y).Slice(bounds.X, bounds.Width); - - for (int x = 0; x < row.Length; x++) + ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); + for (int x = bounds.Left; x < bounds.Right; x++) { - ref TPixel sourcePixel = ref row[x]; - TPixel transformed = processor.GetPaletteColor(sourcePixel); + ref TPixel sourcePixel = ref Unsafe.Add(ref sourceRowRef, x); + TPixel transformed = Unsafe.AsRef(processor).GetPaletteColor(sourcePixel); this.Dither(source, bounds, sourcePixel, transformed, x, y, scale); sourcePixel = transformed; } @@ -139,7 +137,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering } // Internal for AOT - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] internal TPixel Dither( ImageFrame image, Rectangle bounds, diff --git a/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png index 572c719e9e..5059748d2b 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ce9f105031562af60baff3619b9bc84a9f76d77a555a334149d13ddf1e9b44b -size 269077 +oid sha256:d0c8ccdfbf6b1c961f6531ae61207a7f89507f469c875677f1755ea3d6c8d900 +size 326504 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png index b6d77f3f14..0082bae441 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56b0fc0343c220f672611d1adceffd4f59ba917e7c5766b19568271d0b4a95e0 -size 788 +oid sha256:14231fa7c5c98504277b6452901679027661c5e272106bdcfc516dd519a5ff6c +size 1049 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png index b6d77f3f14..0082bae441 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56b0fc0343c220f672611d1adceffd4f59ba917e7c5766b19568271d0b4a95e0 -size 788 +oid sha256:14231fa7c5c98504277b6452901679027661c5e272106bdcfc516dd519a5ff6c +size 1049 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png index b6d77f3f14..208e4fe0ef 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56b0fc0343c220f672611d1adceffd4f59ba917e7c5766b19568271d0b4a95e0 -size 788 +oid sha256:d55bf31ae306fcf91993b488444e83ad0f684f4a2642879e38e27e7b9fb1fa56 +size 1051 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png index b6d77f3f14..0082bae441 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56b0fc0343c220f672611d1adceffd4f59ba917e7c5766b19568271d0b4a95e0 -size 788 +oid sha256:14231fa7c5c98504277b6452901679027661c5e272106bdcfc516dd519a5ff6c +size 1049 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png new file mode 100644 index 0000000000..6b7ee76a90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:208a0b9a189c8801e97495a93302814679441bbbe1769810eb37bcb52a78518f +size 83344 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png index dc944f2123..e91a9551f1 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97f4582029805abbae7575df9935a77b55ab7c4f4190f7cfb7a68b3f3dac9cfc -size 39840 +oid sha256:c95ae441b8b090a0c838db5ed3e9b3ae1040225420e79b76c806f88b96716b8f +size 80344 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png index 55f36449f2..ffd30f62ce 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:186be7a7c23b9150e669b3aa15e3f7af7e619759ecc4ea2a7be7645c124caebb -size 40570 +oid sha256:e5ab9eb0b80de50f117446c46025918893c431c228e212bef9371f4f788cee14 +size 82652 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png index e2c5332cde..e24920a4d5 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e038cf3f08e27f7b83921256112378f69cc56880added2fc60bf1f710e2e497e -size 40547 +oid sha256:f76c909b7e804c8dd80b07fd5346d2036d2fded2bf9a855bd20f7da154a111f3 +size 83554 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png index 93f286cf29..d70774d3a7 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f071a490e7a297e7f861a9669afc7641f2fcb264cdef84f562d41fd97ed66504 -size 40751 +oid sha256:656dfb6c9a53830d915a8c8810d09872333a9230073e25b4f0668269afb15e00 +size 83188 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png new file mode 100644 index 0000000000..c3eda832a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b56aa9a03e7f6733fac6b6ceddba50e85727201c4f79aea64540cc79f7fd942e +size 88333 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png index 1c6b287913..56660f434b 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9994ba45741132a51fab9fdd71e6aaab7ce748c6c393b7515b85bad71878e3ee -size 49984 +oid sha256:863debcf1bc4a4e3fb0e3c29b8b3f8b98bb7ac47901e89a90a57a2dde5d81f53 +size 90431 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png index 9647659023..c434e317af 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5360890509baffe70fd84499a0b0e18057f1220660782b1d82e39d36c04dc3f1 -size 49638 +oid sha256:a92785de634c09d73dc91d1a33e52dedd7d5dea79d269753d959f2a1f81afb2b +size 89207 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png index 36d8991097..4b04715b9a 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e8603ec1daebec049e34658a07bb85333ac996d5d16d64aa318b7f47d966bf6 -size 49253 +oid sha256:e0aeb15a04553142cade051d523bbc18b2e63997efa0b0c5f5b8bab8662074f7 +size 88550 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png index 2d93e79503..fc1e540cc0 100644 --- a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74bdc85112c696133c251d05080c100675cb72f07ed8a8e542faa5255fd0c942 -size 49248 +oid sha256:4801d48fc6691bc2fd555a4bed8a7abdde7edac3dc13b33da580688d11bc4eb4 +size 89543 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png index 5880d74893..5d8e6b4565 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da1630504bf471ef7ee717dd575c9bfaa3cae3839ad9415a5f1abf2c5fa7d418 -size 319991 +oid sha256:adc156f6010679f2ff076405557d0a34cd50464240bbafafbf44edf37b5a1186 +size 321968 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png index 50fdf621a8..97613bcaa3 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b2c154c970f5a80ff3e97f0c0fbe832998e72687be090073416a96d41647141 -size 296210 +oid sha256:ec93dd8fc45e9eb3b1ad13bd89dfc487f5d6eccd2ad8fa1fede67fa7819a263a +size 299393 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png index c58ca55215..2ea043d6fe 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e2747cbfc098f4368fd87599b06debbe2a21bcf29260788b868bf9333c9f03c -size 296458 +oid sha256:8f3ef9dab0169bd262408a30ce2a1d20da5acb331fd56ce66de2f7efe4555a9a +size 299734 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png index f94978c555..e04186940b 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9adda119665eb27ca1475ce19ab0958b00d6778b9e1733c42cf5e77350f40000 -size 332734 +oid sha256:f3d8d9e978668ae8f76004dc2a8440ffe2f55875ee92046ca2be02f426def1a6 +size 333260 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png index c1a78c2ba2..b912690dee 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7295356c1e0c5f59220bfaf154760e86663709c8e0dbaf156efa13ac45b947a -size 348440 +oid sha256:bdb6866053be7dbe1e56e6972b50bc030d30a050f73a4429993e3c639e06d345 +size 349125 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png index 602699838e..f1b04e74c6 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07b4f6147884f323c99734ddf295d2fc1a072ac95f003d63e217aaa63cdb6b7a -size 325067 +oid sha256:0adaaae399376c94af866adfcb2c5777c0dd91d2d4424f24490909e68d2483c9 +size 326321 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png index f7bc04c741..f54900a2f1 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7a849cce2215bc40da6fd3581e8a7fc87b6ef916e227c622c901985d6ee9b1b -size 333793 +oid sha256:0571bde66f19b41cf1ba6f3b63f3d380a1025ae2f92dda8b9c494f8869c325e4 +size 334758 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png index d158820c0f..8165d47763 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a07a6698cca2e13b674102c92f23b934955406c61c485514d9bbbe62da3e04f5 -size 353191 +oid sha256:8cc6c263430489a8866fab47c26f399a034b0dd583d27b12edc68244919321d0 +size 353592 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png index de86ae9a4b..47552e4571 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2fc87ffa7c22b4b054903c6f19bdfcca1d0cdb01df6f853ae4361da3c99f5ab6 -size 34595 +oid sha256:ec01d4ee9173d01f92b5643782f4b6c7e0b4342b530acf6062f5f17c6d7b1e9a +size 36290 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png index a6361a10b2..36e1349ede 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:243d875938b1a68e6c49a07259a9a155f0d36a2fbdc3350b38e13a3d0c6bff7f -size 36085 +oid sha256:2ed04ff17bc4d7c57a9594bb4872f430cc3df4d92c7199d5c5db2420ecc20a95 +size 38303 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png index d052f58840..760d17d5aa 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8076572e9e9a391939c166491553421a83aec5085b1bab155fdf7459840054ed -size 37194 +oid sha256:2f8e53d995f27780851c044d552473ee52ec9dcc2e0dfa9a806c9f8d2fd62692 +size 39251 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png index f07eed5711..efaa7bb44b 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ad464bf9a0dfbebbc7f3b7a3ff641e2db103456943a8fde5d71d675df66f4c6 -size 37895 +oid sha256:6a7a1cefa7e70387ccb9e90c5633725ce936635da39c131a59cec7089392c358 +size 39744 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png index be7686c0ca..94175f4895 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b7369ddaf16e3e13554bf7647096e8947f7ccadadc58646b7c53beee6304f90 -size 17047 +oid sha256:a3b56c451b5e7461782dec2f5dccab18e7ad33efe3d9f1906421c32c75923648 +size 17790 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png index 7878b8c353..c227f65870 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6e0c73170db2f2d84d4951108b8cdd4967e4272ecadcf5268cd7b34d81df760 -size 17786 +oid sha256:c4d81ab162bd065f438504ea2a44be93cefd7f1b31d7d983e23108e8e19b86fa +size 18390 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png index f7761f6cd0..35e12cf859 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d54587aab60d4200bb6e01a0ff707230959602b93ff55fbf48c85b61cfb0932a -size 18161 +oid sha256:1d2cb1111d2a3915072ca53404215052bbff42ff9639e8e3c2b4f6a70591fd0e +size 19145 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png index 24414f4d4c..6ff5504ab7 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fee85efaf11a2da44933c5ab9e5858558044d1707e40a6fadda6ed5214e40c9c -size 18453 +oid sha256:1133884d19f663d3c643ebe11bdeac65e2ab3d533be43a40b61b3292ea59cd3b +size 19680 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png index 3aecca075b..3b9f8866b4 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4947713871d8e832f74f855bc60c3efdacef46fa826a37dfa4ceb2a1e4e23680 -size 21484 +oid sha256:64b29bbd6edca8e444822a97ce9bc674db175c299cbec1cbe596552419f49be7 +size 22239 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png index 78fda73874..1efaf38b6c 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61b794eb8ff00a1088f4584c98066fd5e309c1711f2a430ae24fc482524e6573 -size 22374 +oid sha256:ae09ad6a81dbfc56c60b7e47720338b3ba3b8aa29982016c36a39baa33f75054 +size 23353 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png index 21f8d67744..ed9531e7bb 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe1e3eae55fad479016d869a3b483155f3be947636da96d105e16072fbb4e350 -size 22968 +oid sha256:e9e9094177282dd635a02b97855299e9275af364fd66812dd72b3ef2545b5660 +size 24487 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png index 9c90d31b0c..22b642dffa 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2df6b0869c9cb406417bca7eedd2b05968a5265b933dfbec87fff018c7b83ce9 -size 23395 +oid sha256:874ffc514300dd727c6c46943fc9f8955013c1d355fc1bd60848660ed9b4f6b2 +size 25182 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png index 5a2dc3f01d..39820f08c6 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b984d1f65c4c9b933b7f30c06c7f036f77463c9df092165145457f607c7e8ef -size 27395 +oid sha256:46989a5fd14a9555eee28081ad78c34e26f5c38e6d7360cb36de8a87d2916685 +size 29187 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png index 780703f694..e152e9c48e 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ae97e27986c742e451b490e28415d3083bd2cc7bc581852d846f55030f1bd87 -size 28778 +oid sha256:c73448e92f13c979c3a0c4f16532a6f47a14e6e1974d686674862070787b6489 +size 31145 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png index fcdaf069f4..f37e332f37 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e92f0af9f0de526e6f9da454b16a0dfa164e04ef48ac1b6b0b4958c28821d6b1 -size 30124 +oid sha256:afc516374154a209a07f069eb7832808eefc0db4f2a3fbfa765848ca0d7acedf +size 31974 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png index 35feecd3a6..e4b8623075 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c40b16fcfb88c87aaa8be255257703edbcbe82cf33a1ef107b9076deb62f4d02 -size 30663 +oid sha256:be814de172c0b290e4af81ea175e14643e9dc34ce3400ae1f3b64228e29bf49d +size 32237 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png index 296b3f2c71..302188cf58 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c16042705b2cdf610a8a70b9932b3410df7266ec63497e947f99ee049d95d55 -size 134155 +oid sha256:3528fe676ae29534d80edcd08ca5874bcaaae6c1133332070dcd008df2c50da7 +size 138694 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png index a83e7367f8..e24920a4d5 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8586c2d716e1a4b8309ee8010eed5ad6abeaef957eba616466df86155246cea6 -size 75964 +oid sha256:f76c909b7e804c8dd80b07fd5346d2036d2fded2bf9a855bd20f7da154a111f3 +size 83554 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png index 087c28243a..32475f3874 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2facff0487dafe3de174758f7e1c237e7d6405fb5efd087a25ea502eaa94ea82 -size 71959 +oid sha256:22cebdb64f32d4818a35c07a4a2f5c2b1bae1fd465944d553b37a211f3e78ff8 +size 79480 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png index c07774ad69..74c5cb62da 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa01ed20182ea419ceee6ac19a4044a9aa31e33c797b87c07f6673816f9c6bf8 -size 172305 +oid sha256:385063f3976342ea525487e53801df14e644eb0a56898b1e81e0667323ff3f1a +size 172869 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png index feda429b1c..2d16e4af11 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b0a1b167065207ae11637d1d3b3e89069aa2f7c5f5d37d3974f84eef4b06cb4 -size 141157 +oid sha256:27e0be11cb36a419a590de19cce432f5b78d9a3c86d024ca43b5904e758c569d +size 144104 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png index bf33383b26..4b04715b9a 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:300f04232c77cf6dce492d6782fac4b96fc868819a8b6125d29d41a07dcecbb3 -size 85437 +oid sha256:e0aeb15a04553142cade051d523bbc18b2e63997efa0b0c5f5b8bab8662074f7 +size 88550 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png index c123626a87..07003dfa4e 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57dbc32780b6c9bedf6a6c3d275f5c4d960c295eee4e731631a0f88ec2109b0 -size 108975 +oid sha256:e720cb4ab955614764cc0c10f08146a50e08d4c5712a02b581ae25a4e4935c3a +size 113199 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png index cfbaff51e7..9f04685444 100644 --- a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88c97f88cc6c48a448ee77c0fbdcba29d8f091978fe8906fa1aaf1265de13ac6 -size 173601 +oid sha256:462a0d7d7d8056042e49dff3a896114d7db09b9e40e72e6b87f711caf6c1a993 +size 175519 From 5f4a7accfb15db86e5ed8ec0c4e68ef19b654184 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 2 Mar 2021 15:58:24 +0000 Subject: [PATCH 06/11] Update OrderedDither.cs --- .../Processors/Dithering/OrderedDither.cs | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs index a89d23cc00..2b7eb165eb 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Initializes a new instance of the struct. /// /// The length of the matrix sides - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public OrderedDither(uint length) { DenseMatrix ditherMatrix = OrderedDitherFactory.CreateDitherMatrix(length); @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => !(left == right); /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void ApplyQuantizationDither( ref TFrameQuantizer quantizer, ImageFrame source, @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering } /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void ApplyPaletteDither( in TPaletteDitherImageProcessor processor, ImageFrame source, @@ -145,12 +145,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering } // Spread assumes an even colorspace distribution and precision. - // Cubed root used because we always compare to Rgb. + // TODO: Cubed root is currently used to represent 3 color channels + // but we should introduce something to PixelTypeInfo. // https://bisqwit.iki.fi/story/howto/dither/jy/ // https://en.wikipedia.org/wiki/Ordered_dithering#Algorithm - internal static int CalculatePaletteSpread(int colors) => (int)(255 / (Math.Pow(colors, 1.0 / 3) - 1)); + internal static int CalculatePaletteSpread(int colors) + => (int)(255 / Math.Max(1, Math.Pow(colors, 1.0 / 3) - 1)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] internal TPixel Dither( TPixel source, int x, @@ -181,7 +183,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => obj is OrderedDither dither && this.Equals(dither); /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(OrderedDither other) => this.thresholdMatrix.Equals(other.thresholdMatrix) && this.modulusX == other.modulusX && this.modulusY == other.modulusY; @@ -190,7 +192,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => this.Equals((object)other); /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public override int GetHashCode() => HashCode.Combine(this.thresholdMatrix, this.modulusX, this.modulusY); @@ -205,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly Rectangle bounds; private readonly int spread; - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public QuantizeDitherRowOperation( ref TFrameQuantizer quantizer, in OrderedDither dither, @@ -221,7 +223,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering this.spread = CalculatePaletteSpread(destination.Palette.Length); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { ref TFrameQuantizer quantizer = ref Unsafe.AsRef(this.quantizer); @@ -251,7 +253,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly float scale; private readonly int spread; - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public PaletteDitherRowOperation( in TPaletteDitherImageProcessor processor, in OrderedDither dither, @@ -266,7 +268,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering this.spread = CalculatePaletteSpread(processor.Palette.Length); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { ref TPaletteDitherImageProcessor processor = ref Unsafe.AsRef(this.processor); From 58c5bf18dc12afd2cd9dc92d921d36125ef2614b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 2 Mar 2021 16:35:12 +0000 Subject: [PATCH 07/11] Bump Magick.NET --- tests/Directory.Build.targets | 2 +- .../TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index 9495b912b6..af86f49b09 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -21,7 +21,7 @@ - + diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index d20e7d2a7e..163bb84d56 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -7,7 +7,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using ImageMagick; -using ImageMagick.Formats.Bmp; +using ImageMagick.Formats; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; From d1c2172406783ed88b8c1f0358837719f932fd64 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 9 Mar 2021 12:07:47 +0100 Subject: [PATCH 08/11] Image.Load(byte[]) should return non-generic Image --- src/ImageSharp/Image.FromBytes.cs | 4 ++-- tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 50950c192a..b8b4f056d9 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -92,8 +92,8 @@ namespace SixLabors.ImageSharp /// The configuration is null. /// The data is null. /// A new . - public static Image Load(byte[] data) - => Load(Configuration.Default, data); + public static Image Load(byte[] data) + => Load(Configuration.Default, data); /// /// Load a new instance of from the given encoded byte array. diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 058d669d40..446f1e9d47 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -155,9 +155,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif [Fact] public void CanDecodeIntermingledImages() { - using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) + using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) using (Image.Load(TestFile.Create(TestImages.Png.Icon).Bytes)) - using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) + using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) { for (int i = 0; i < kumin1.Frames.Count; i++) { From 583bb6bd6d2a016f0f525f23ba830f1ee2d191cf Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 9 Mar 2021 12:14:09 +0100 Subject: [PATCH 09/11] Also fix "" --- src/ImageSharp/Image.FromBytes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index b8b4f056d9..a33a345a0f 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp /// The byte array containing image data. /// The configuration is null. /// The data is null. - /// A new . + /// A new . public static Image Load(byte[] data) => Load(Configuration.Default, data); From 10739590ce81ed37e63dd05dabbff7e96ba48944 Mon Sep 17 00:00:00 2001 From: UltraNamahage <60680748+UltraNamahage@users.noreply.github.com> Date: Wed, 10 Mar 2021 18:46:49 +0900 Subject: [PATCH 10/11] Have AotCompilerTools cache additional methods. --- src/ImageSharp/Advanced/AotCompilerTools.cs | 348 ++++++++++++++++++++ 1 file changed, 348 insertions(+) diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index ed23cd445a..666b459e42 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -7,10 +7,25 @@ using System.IO; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg.Components; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Formats.Tga; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.ImageSharp.Processing.Processors.Binarization; +using SixLabors.ImageSharp.Processing.Processors.Convolution; using SixLabors.ImageSharp.Processing.Processors.Dithering; +using SixLabors.ImageSharp.Processing.Processors.Drawing; +using SixLabors.ImageSharp.Processing.Processors.Effects; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using SixLabors.ImageSharp.Processing.Processors.Normalization; +using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.ImageSharp.Processing.Processors.Quantization; +using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Advanced { @@ -89,6 +104,18 @@ namespace SixLabors.ImageSharp.Advanced AotCompileDithering(); AotCompilePixelOperations(); + AotCompileImage(); + AotCompileImageProcessingContextFactory(); + AotCompileImageEncoderInternals(); + AotCompileImageDecoderInternals(); + AotCompileImageEncoders(); + AotCompileImageDecoders(); + AotCompileImageProcessors(); + AotCompileGenericImageProcessors(); + AotCompileResamplers(); + AotCompileQuantizers(); + AotCompilePixelSamplingStrategys(); + Unsafe.SizeOf(); AotCodecs(); @@ -213,5 +240,326 @@ namespace SixLabors.ImageSharp.Advanced var pixelOp = new PixelOperations(); pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear); } + + /// + /// This method pre-seeds the for a given pixel format in the AoT compiler. + /// + /// The pixel format. + private static unsafe void AotCompileImage() + where TPixel : unmanaged, IPixel + { + Image img = default; + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + img.CloneAs(default); + + ImageFrame.LoadPixelData(default, default(ReadOnlySpan), default, default); + ImageFrame.LoadPixelData(default, default(ReadOnlySpan), default, default); + } + + private static void AotCompileImageProcessingContextFactory() + where TPixel : unmanaged, IPixel + => default(DefaultImageOperationsProviderFactory).CreateImageProcessingContext(default, default, default); + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + private static void AotCompileImageEncoderInternals() + where TPixel : unmanaged, IPixel + { + default(BmpEncoderCore).Encode(default, default, default); + default(GifEncoderCore).Encode(default, default, default); + default(JpegEncoderCore).Encode(default, default, default); + default(PngEncoderCore).Encode(default, default, default); + default(TgaEncoderCore).Encode(default, default, default); + } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + private static void AotCompileImageDecoderInternals() + where TPixel : unmanaged, IPixel + { + default(BmpDecoderCore).Decode(default, default, default); + default(GifDecoderCore).Decode(default, default, default); + default(JpegDecoderCore).Decode(default, default, default); + default(PngDecoderCore).Decode(default, default, default); + default(TgaDecoderCore).Decode(default, default, default); + } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + private static void AotCompileImageEncoders() + where TPixel : unmanaged, IPixel + { + AotCompileImageEncoder(); + AotCompileImageEncoder(); + AotCompileImageEncoder(); + AotCompileImageEncoder(); + AotCompileImageEncoder(); + } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + private static void AotCompileImageDecoders() + where TPixel : unmanaged, IPixel + { + AotCompileImageDecoder(); + AotCompileImageDecoder(); + AotCompileImageDecoder(); + AotCompileImageDecoder(); + AotCompileImageDecoder(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The encoder. + private static void AotCompileImageEncoder() + where TPixel : unmanaged, IPixel + where TEncoder : class, IImageEncoder + { + default(TEncoder).Encode(default, default); + default(TEncoder).EncodeAsync(default, default, default); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The decoder. + private static void AotCompileImageDecoder() + where TPixel : unmanaged, IPixel + where TDecoder : class, IImageDecoder + { + default(TDecoder).Decode(default, default); + default(TDecoder).DecodeAsync(default, default, default); + } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// + /// There is no structure that implements ISwizzler. + /// + /// The pixel format. + private static void AotCompileImageProcessors() + where TPixel : unmanaged, IPixel + { + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + AotCompileImageProcessor(); + + AotCompilerCloningImageProcessor(); + AotCompilerCloningImageProcessor(); + AotCompilerCloningImageProcessor(); + AotCompilerCloningImageProcessor(); + AotCompilerCloningImageProcessor(); + AotCompilerCloningImageProcessor(); + AotCompilerCloningImageProcessor(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The processor type + private static void AotCompileImageProcessor() + where TPixel : unmanaged, IPixel + where TProc : class, IImageProcessor + => default(TProc).CreatePixelSpecificProcessor(default, default, default); + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The processor type + private static void AotCompilerCloningImageProcessor() + where TPixel : unmanaged, IPixel + where TProc : class, ICloningImageProcessor + => default(TProc).CreatePixelSpecificCloningProcessor(default, default, default); + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// + /// There is no structure that implements ISwizzler. + /// + /// The pixel format. + private static void AotCompileGenericImageProcessors() + where TPixel : unmanaged, IPixel + { + AotCompileGenericCloningImageProcessor>(); + AotCompileGenericCloningImageProcessor>(); + AotCompileGenericCloningImageProcessor>(); + AotCompileGenericCloningImageProcessor>(); + AotCompileGenericCloningImageProcessor>(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The processor type + private static void AotCompileGenericCloningImageProcessor() + where TPixel : unmanaged, IPixel + where TProc : class, ICloningImageProcessor + => default(TProc).CloneAndExecute(); + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + private static void AotCompileResamplers() + where TPixel : unmanaged, IPixel + { + AotCompileResampler(); + AotCompileResampler(); + AotCompileResampler(); + AotCompileResampler(); + AotCompileResampler(); + AotCompileResampler(); + AotCompileResampler(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The processor type + private static void AotCompileResampler() + where TPixel : unmanaged, IPixel + where TResampler : struct, IResampler + { + default(TResampler).ApplyTransform(default); + + default(AffineTransformProcessor).ApplyTransform(default); + default(ProjectiveTransformProcessor).ApplyTransform(default); + default(ResizeProcessor).ApplyTransform(default); + default(RotateProcessor).ApplyTransform(default); + } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + private static void AotCompileQuantizers() + where TPixel : unmanaged, IPixel + { + AotCompileQuantizer(); + AotCompileQuantizer(); + AotCompileQuantizer(); + AotCompileQuantizer(); + AotCompileQuantizer(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The quantizer type + private static void AotCompileQuantizer() + where TPixel : unmanaged, IPixel + + where TQuantizer : class, IQuantizer + { + default(TQuantizer).CreatePixelSpecificQuantizer(default); + default(TQuantizer).CreatePixelSpecificQuantizer(default, default); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + private static void AotCompilePixelSamplingStrategys() + where TPixel : unmanaged, IPixel + { + default(DefaultPixelSamplingStrategy).EnumeratePixelRegions(default); + default(ExtensivePixelSamplingStrategy).EnumeratePixelRegions(default); + } } } From ece070705369bd3bc8329813aef57d0d1d2edaf9 Mon Sep 17 00:00:00 2001 From: UltraNamahage <60680748+UltraNamahage@users.noreply.github.com> Date: Sun, 14 Mar 2021 04:10:01 +0900 Subject: [PATCH 11/11] Organize Seed and solve the problem of more Seed and code strips with the Preserve attribute. --- src/ImageSharp/Advanced/AotCompilerTools.cs | 320 +++++++++--------- src/ImageSharp/Advanced/PreserveAttribute.cs | 14 + .../PaletteDitherProcessor{TPixel}.cs | 3 +- 3 files changed, 168 insertions(+), 169 deletions(-) create mode 100644 src/ImageSharp/Advanced/PreserveAttribute.cs diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 666b459e42..ea4cd1c8c4 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Formats; @@ -13,6 +12,7 @@ using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Tga; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; @@ -40,70 +40,82 @@ namespace SixLabors.ImageSharp.Advanced [ExcludeFromCodeCoverage] internal static class AotCompilerTools { - static AotCompilerTools() - { - Unsafe.SizeOf(); - Unsafe.SizeOf(); - Unsafe.SizeOf(); - Unsafe.SizeOf(); - Unsafe.SizeOf(); - Unsafe.SizeOf(); - Unsafe.SizeOf(); - Unsafe.SizeOf(); - } - /// /// This is the method that seeds the AoT compiler. /// None of these seed methods needs to actually be called to seed the compiler. /// The calls just need to be present when the code is compiled, and each implementation will be built. /// + /// + /// This method doesn't actually do anything but serves an important purpose... + /// If you are running ImageSharp on iOS and try to call SaveAsGif, it will throw an exception: + /// "Attempting to JIT compile method... OctreeFrameQuantizer.ConstructPalette... while running in aot-only mode." + /// The reason this happens is the SaveAsGif method makes heavy use of generics, which are too confusing for the AoT + /// compiler used on Xamarin.iOS. It spins up the JIT compiler to try and figure it out, but that is an illegal op on + /// iOS so it bombs out. + /// If you are getting the above error, you need to call this method, which will pre-seed the AoT compiler with the + /// necessary methods to complete the SaveAsGif call. That's it, otherwise you should NEVER need this method!!! + /// + [Preserve] private static void SeedEverything() { - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); - Seed(); + try + { + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + Unsafe.SizeOf(); + + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + } + catch + { + // nop + } + + throw new InvalidOperationException("This method is used for AOT code generation only. Do not call it at runtime."); } /// /// Seeds the compiler using the given pixel format. /// /// The pixel format. + [Preserve] private static void Seed() where TPixel : unmanaged, IPixel { // This is we actually call all the individual methods you need to seed. - AotPixelInterface(); - AotCompileOctreeQuantizer(); - AotCompileWuQuantizer(); - AotCompilePaletteQuantizer(); - AotCompileDithering(); - AotCompilePixelOperations(); - AotCompileImage(); AotCompileImageProcessingContextFactory(); AotCompileImageEncoderInternals(); @@ -115,136 +127,19 @@ namespace SixLabors.ImageSharp.Advanced AotCompileResamplers(); AotCompileQuantizers(); AotCompilePixelSamplingStrategys(); + AotCompileDithers(); + AotCompileMemoryManagers(); Unsafe.SizeOf(); - AotCodecs(); - // TODO: Do the discovery work to figure out what works and what doesn't. } - private static void AotPixelInterface() - where TPixel : unmanaged, IPixel - { - TPixel pixel = default; - Rgba32 rgba32 = default; - pixel.ToRgba32(ref rgba32); - pixel.FromRgba32(rgba32); - pixel.FromScaledVector4(pixel.ToScaledVector4()); - pixel.FromVector4(pixel.ToVector4()); - - pixel.FromArgb32(default); - pixel.FromBgr24(default); - pixel.FromBgra32(default); - pixel.FromBgra5551(default); - pixel.FromL16(default); - pixel.FromL8(default); - pixel.FromLa16(default); - pixel.FromLa32(default); - pixel.FromRgb24(default); - pixel.FromRgb48(default); - pixel.FromRgba64(default); - pixel.FromRgb24(default); - } - - /// - /// This method doesn't actually do anything but serves an important purpose... - /// If you are running ImageSharp on iOS and try to call SaveAsGif, it will throw an exception: - /// "Attempting to JIT compile method... OctreeFrameQuantizer.ConstructPalette... while running in aot-only mode." - /// The reason this happens is the SaveAsGif method makes heavy use of generics, which are too confusing for the AoT - /// compiler used on Xamarin.iOS. It spins up the JIT compiler to try and figure it out, but that is an illegal op on - /// iOS so it bombs out. - /// If you are getting the above error, you need to call this method, which will pre-seed the AoT compiler with the - /// necessary methods to complete the SaveAsGif call. That's it, otherwise you should NEVER need this method!!! - /// - /// The pixel format. - private static void AotCompileOctreeQuantizer() - where TPixel : unmanaged, IPixel - { - using var test = new OctreeQuantizer(Configuration.Default, new OctreeQuantizer().Options); - var frame = new ImageFrame(Configuration.Default, 1, 1); - test.QuantizeFrame(frame, frame.Bounds()); - } - - /// - /// This method pre-seeds the WuQuantizer in the AoT compiler for iOS. - /// - /// The pixel format. - private static void AotCompileWuQuantizer() - where TPixel : unmanaged, IPixel - { - using var test = new WuQuantizer(Configuration.Default, new WuQuantizer().Options); - var frame = new ImageFrame(Configuration.Default, 1, 1); - test.QuantizeFrame(frame, frame.Bounds()); - } - - /// - /// This method pre-seeds the PaletteQuantizer in the AoT compiler for iOS. - /// - /// The pixel format. - private static void AotCompilePaletteQuantizer() - where TPixel : unmanaged, IPixel - { - using var test = (PaletteQuantizer)new PaletteQuantizer(Array.Empty()).CreatePixelSpecificQuantizer(Configuration.Default); - var frame = new ImageFrame(Configuration.Default, 1, 1); - test.QuantizeFrame(frame, frame.Bounds()); - } - - /// - /// This method pre-seeds the default dithering engine (FloydSteinbergDiffuser) in the AoT compiler for iOS. - /// - /// The pixel format. - private static void AotCompileDithering() - where TPixel : unmanaged, IPixel - { - ErrorDither errorDither = ErrorDither.FloydSteinberg; - OrderedDither orderedDither = OrderedDither.Bayer2x2; - TPixel pixel = default; - using (var image = new ImageFrame(Configuration.Default, 1, 1)) - { - errorDither.Dither(image, image.Bounds(), pixel, pixel, 0, 0, 0); - orderedDither.Dither(pixel, 0, 0, 0, 0); - } - } - - /// - /// This method pre-seeds the decoder and encoder for a given pixel format in the AoT compiler for iOS. - /// - /// The pixel format. - private static void AotCodecs() - where TPixel : unmanaged, IPixel - { - Configuration configuration = Configuration.Default; - ImageFormatManager formatsManager = configuration.ImageFormatsManager; - foreach (IImageFormat imageFormat in configuration.ImageFormats) - { - using var ms = new MemoryStream(); - using (var encoded = new Image(1, 1)) - { - encoded.Save(ms, formatsManager.FindEncoder(imageFormat)); - ms.Position = 0; - } - - using var decoded = Image.Load(ms); - Span span = decoded.GetPixelRowSpan(0); - } - } - - /// - /// This method pre-seeds the PixelOperations engine for the AoT compiler on iOS. - /// - /// The pixel format. - private static void AotCompilePixelOperations() - where TPixel : unmanaged, IPixel - { - var pixelOp = new PixelOperations(); - pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear); - } - /// /// This method pre-seeds the for a given pixel format in the AoT compiler. /// /// The pixel format. + [Preserve] private static unsafe void AotCompileImage() where TPixel : unmanaged, IPixel { @@ -282,6 +177,11 @@ namespace SixLabors.ImageSharp.Advanced ImageFrame.LoadPixelData(default, default(ReadOnlySpan), default, default); } + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + [Preserve] private static void AotCompileImageProcessingContextFactory() where TPixel : unmanaged, IPixel => default(DefaultImageOperationsProviderFactory).CreateImageProcessingContext(default, default, default); @@ -290,6 +190,7 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompileImageEncoderInternals() where TPixel : unmanaged, IPixel { @@ -304,6 +205,7 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompileImageDecoderInternals() where TPixel : unmanaged, IPixel { @@ -318,6 +220,7 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompileImageEncoders() where TPixel : unmanaged, IPixel { @@ -332,6 +235,7 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompileImageDecoders() where TPixel : unmanaged, IPixel { @@ -347,6 +251,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The encoder. + [Preserve] private static void AotCompileImageEncoder() where TPixel : unmanaged, IPixel where TEncoder : class, IImageEncoder @@ -360,6 +265,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The decoder. + [Preserve] private static void AotCompileImageDecoder() where TPixel : unmanaged, IPixel where TDecoder : class, IImageDecoder @@ -375,6 +281,7 @@ namespace SixLabors.ImageSharp.Advanced /// There is no structure that implements ISwizzler. /// /// The pixel format. + [Preserve] private static void AotCompileImageProcessors() where TPixel : unmanaged, IPixel { @@ -448,6 +355,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The processor type + [Preserve] private static void AotCompileImageProcessor() where TPixel : unmanaged, IPixel where TProc : class, IImageProcessor @@ -458,6 +366,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The processor type + [Preserve] private static void AotCompilerCloningImageProcessor() where TPixel : unmanaged, IPixel where TProc : class, ICloningImageProcessor @@ -470,6 +379,7 @@ namespace SixLabors.ImageSharp.Advanced /// There is no structure that implements ISwizzler. /// /// The pixel format. + [Preserve] private static void AotCompileGenericImageProcessors() where TPixel : unmanaged, IPixel { @@ -485,6 +395,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The processor type + [Preserve] private static void AotCompileGenericCloningImageProcessor() where TPixel : unmanaged, IPixel where TProc : class, ICloningImageProcessor @@ -494,6 +405,7 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompileResamplers() where TPixel : unmanaged, IPixel { @@ -511,6 +423,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The processor type + [Preserve] private static void AotCompileResampler() where TPixel : unmanaged, IPixel where TResampler : struct, IResampler @@ -527,6 +440,7 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompileQuantizers() where TPixel : unmanaged, IPixel { @@ -542,6 +456,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The pixel format. /// The quantizer type + [Preserve] private static void AotCompileQuantizer() where TPixel : unmanaged, IPixel @@ -555,11 +470,80 @@ namespace SixLabors.ImageSharp.Advanced /// This method pre-seeds the in the AoT compiler. /// /// The pixel format. + [Preserve] private static void AotCompilePixelSamplingStrategys() where TPixel : unmanaged, IPixel { default(DefaultPixelSamplingStrategy).EnumeratePixelRegions(default); default(ExtensivePixelSamplingStrategy).EnumeratePixelRegions(default); } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + [Preserve] + private static void AotCompileDithers() + where TPixel : unmanaged, IPixel + { + AotCompileDither(); + AotCompileDither(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The dither. + [Preserve] + private static void AotCompileDither() + where TPixel : unmanaged, IPixel + where TDither : struct, IDither + { + var octree = default(OctreeQuantizer); + default(TDither).ApplyQuantizationDither, TPixel>(ref octree, default, default, default); + + var palette = default(PaletteQuantizer); + default(TDither).ApplyQuantizationDither, TPixel>(ref palette, default, default, default); + + var wu = default(WuQuantizer); + default(TDither).ApplyQuantizationDither, TPixel>(ref wu, default, default, default); + default(TDither).ApplyPaletteDither.DitherProcessor, TPixel>(default, default, default); + } + + /// + /// This method pre-seeds the all in the AoT compiler. + /// + /// The pixel format. + [Preserve] + private static void AotCompileMemoryManagers() + where TPixel : unmanaged, IPixel + { + AotCompileMemoryManager(); + AotCompileMemoryManager(); + } + + /// + /// This method pre-seeds the in the AoT compiler. + /// + /// The pixel format. + /// The buffer. + [Preserve] + private static void AotCompileMemoryManager() + where TPixel : unmanaged, IPixel + where TBuffer : MemoryAllocator + { + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + default(TBuffer).Allocate(default, default); + } } } diff --git a/src/ImageSharp/Advanced/PreserveAttribute.cs b/src/ImageSharp/Advanced/PreserveAttribute.cs new file mode 100644 index 0000000000..a16b30e235 --- /dev/null +++ b/src/ImageSharp/Advanced/PreserveAttribute.cs @@ -0,0 +1,14 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Advanced +{ + /// + /// This is necessary to avoid being excluded from compilation in environments that do AOT builds, such as Unity's IL2CPP and Xamarin. + /// The only thing that matters is the class name. + /// There is no need to use or inherit from the PreserveAttribute class in each environment. + /// + internal sealed class PreserveAttribute : System.Attribute + { + } +} diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index 789d02046e..4631cd4229 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -72,7 +72,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Used to allow inlining of calls to /// . /// - private readonly struct DitherProcessor : IPaletteDitherImageProcessor + /// Internal for AOT + internal readonly struct DitherProcessor : IPaletteDitherImageProcessor { private readonly EuclideanPixelMap pixelMap;