Browse Source

Merge remote-tracking branch 'origin/master' into webp

# Conflicts:
#	src/ImageSharp/Advanced/AotCompilerTools.cs
pull/1552/head
Brian Popow 5 years ago
parent
commit
61b3da14fe
  1. 567
      src/ImageSharp/Advanced/AotCompilerTools.cs
  2. 14
      src/ImageSharp/Advanced/PreserveAttribute.cs
  3. 6
      src/ImageSharp/Image.FromBytes.cs
  4. 4
      src/ImageSharp/ImageSharp.csproj
  5. 5
      src/ImageSharp/Processing/KnownDitherings.cs
  6. 1
      src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs
  7. 5
      src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs
  8. 57
      src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
  9. 3
      src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs
  10. 2
      tests/Directory.Build.targets
  11. 4
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  12. 1
      tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs
  13. 2
      tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs
  14. 2
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
  15. 2
      tests/ImageSharp.Tests/TestUtilities/TestUtils.cs
  16. 4
      tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png
  17. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png
  18. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png
  19. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png
  20. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png
  21. 3
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png
  22. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png
  23. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png
  24. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png
  25. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png
  26. 3
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png
  27. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png
  28. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png
  29. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png
  30. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png
  31. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png
  32. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png
  33. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png
  34. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png
  35. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png
  36. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png
  37. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png
  38. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png
  39. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png
  40. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png
  41. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png
  42. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png
  43. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png
  44. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png
  45. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png
  46. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png
  47. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png
  48. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png
  49. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png
  50. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png
  51. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png
  52. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png
  53. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png
  54. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png
  55. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png
  56. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png
  57. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png
  58. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png
  59. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png
  60. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png
  61. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png
  62. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png

567
src/ImageSharp/Advanced/AotCompilerTools.cs

@ -6,11 +6,26 @@ using System.Diagnostics.CodeAnalysis;
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.Memory;
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
{
@ -25,182 +40,510 @@ namespace SixLabors.ImageSharp.Advanced
[ExcludeFromCodeCoverage]
internal static class AotCompilerTools
{
static AotCompilerTools()
{
System.Runtime.CompilerServices.Unsafe.SizeOf<long>();
System.Runtime.CompilerServices.Unsafe.SizeOf<short>();
System.Runtime.CompilerServices.Unsafe.SizeOf<float>();
System.Runtime.CompilerServices.Unsafe.SizeOf<double>();
System.Runtime.CompilerServices.Unsafe.SizeOf<byte>();
System.Runtime.CompilerServices.Unsafe.SizeOf<int>();
System.Runtime.CompilerServices.Unsafe.SizeOf<Block8x8>();
System.Runtime.CompilerServices.Unsafe.SizeOf<Vector4>();
}
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// 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!!!
/// </remarks>
[Preserve]
private static void SeedEverything()
{
Seed<A8>();
Seed<Argb32>();
Seed<Bgr24>();
Seed<Bgr565>();
Seed<Bgra32>();
Seed<Bgra4444>();
Seed<Bgra5551>();
Seed<Byte4>();
Seed<L16>();
Seed<L8>();
Seed<La16>();
Seed<La32>();
Seed<HalfSingle>();
Seed<HalfVector2>();
Seed<HalfVector4>();
Seed<NormalizedByte2>();
Seed<NormalizedByte4>();
Seed<NormalizedShort2>();
Seed<NormalizedShort4>();
Seed<Rg32>();
Seed<Rgb24>();
Seed<Rgb48>();
Seed<Rgba1010102>();
Seed<Rgba32>();
Seed<Rgba64>();
Seed<RgbaVector>();
Seed<Short2>();
Seed<Short4>();
try
{
Unsafe.SizeOf<long>();
Unsafe.SizeOf<short>();
Unsafe.SizeOf<float>();
Unsafe.SizeOf<double>();
Unsafe.SizeOf<byte>();
Unsafe.SizeOf<int>();
Unsafe.SizeOf<bool>();
Unsafe.SizeOf<Block8x8>();
Unsafe.SizeOf<Vector4>();
Seed<A8>();
Seed<Argb32>();
Seed<Bgr24>();
Seed<Bgr565>();
Seed<Bgra32>();
Seed<Bgra4444>();
Seed<Bgra5551>();
Seed<Byte4>();
Seed<L16>();
Seed<L8>();
Seed<La16>();
Seed<La32>();
Seed<HalfSingle>();
Seed<HalfVector2>();
Seed<HalfVector4>();
Seed<NormalizedByte2>();
Seed<NormalizedByte4>();
Seed<NormalizedShort2>();
Seed<NormalizedShort4>();
Seed<Rg32>();
Seed<Rgb24>();
Seed<Rgb48>();
Seed<Rgba1010102>();
Seed<Rgba32>();
Seed<Rgba64>();
Seed<RgbaVector>();
Seed<Short2>();
Seed<Short4>();
}
catch
{
// nop
}
throw new InvalidOperationException("This method is used for AOT code generation only. Do not call it at runtime.");
}
/// <summary>
/// Seeds the compiler using the given pixel format.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void Seed<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
// This is we actually call all the individual methods you need to seed.
AotCompileOctreeQuantizer<TPixel>();
AotCompileWuQuantizer<TPixel>();
AotCompilePaletteQuantizer<TPixel>();
AotCompileDithering<TPixel>();
AotCompilePixelOperations<TPixel>();
AotCompileImage<TPixel>();
AotCompileImageProcessingContextFactory<TPixel>();
AotCompileImageEncoderInternals<TPixel>();
AotCompileImageDecoderInternals<TPixel>();
AotCompileImageEncoders<TPixel>();
AotCompileImageDecoders<TPixel>();
AotCompileImageProcessors<TPixel>();
AotCompileGenericImageProcessors<TPixel>();
AotCompileResamplers<TPixel>();
AotCompileQuantizers<TPixel>();
AotCompilePixelSamplingStrategys<TPixel>();
AotCompileDithers<TPixel>();
AotCompileMemoryManagers<TPixel>();
Unsafe.SizeOf<TPixel>();
AotCodec<TPixel>(new Formats.Png.PngDecoder(), new Formats.Png.PngEncoder());
AotCodec<TPixel>(new Formats.Bmp.BmpDecoder(), new Formats.Bmp.BmpEncoder());
AotCodec<TPixel>(new Formats.Gif.GifDecoder(), new Formats.Gif.GifEncoder());
AotCodec<TPixel>(new Formats.Jpeg.JpegDecoder(), new Formats.Jpeg.JpegEncoder());
AotCodec<TPixel>(new Formats.Tga.TgaDecoder(), new Formats.Tga.TgaEncoder());
AotCodec<TPixel>(new Formats.Experimental.Webp.WebpDecoder(), new Formats.Experimental.Webp.WebpEncoder());
// TODO: Do the discovery work to figure out what works and what doesn't.
}
/// <summary>
/// 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!!!
/// This method pre-seeds the <see cref="Image{TPixel}"/> for a given pixel format in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompileOctreeQuantizer<TPixel>()
[Preserve]
private static unsafe void AotCompileImage<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
using (var test = new OctreeQuantizer<TPixel>(Configuration.Default, new OctreeQuantizer().Options))
{
var frame = new ImageFrame<TPixel>(Configuration.Default, 1, 1);
test.QuantizeFrame(frame, frame.Bounds());
}
Image<TPixel> img = default;
img.CloneAs<A8>(default);
img.CloneAs<Argb32>(default);
img.CloneAs<Bgr24>(default);
img.CloneAs<Bgr565>(default);
img.CloneAs<Bgra32>(default);
img.CloneAs<Bgra4444>(default);
img.CloneAs<Bgra5551>(default);
img.CloneAs<Byte4>(default);
img.CloneAs<L16>(default);
img.CloneAs<L8>(default);
img.CloneAs<La16>(default);
img.CloneAs<La32>(default);
img.CloneAs<HalfSingle>(default);
img.CloneAs<HalfVector2>(default);
img.CloneAs<HalfVector4>(default);
img.CloneAs<NormalizedByte2>(default);
img.CloneAs<NormalizedByte4>(default);
img.CloneAs<NormalizedShort2>(default);
img.CloneAs<NormalizedShort4>(default);
img.CloneAs<Rg32>(default);
img.CloneAs<Rgb24>(default);
img.CloneAs<Rgb48>(default);
img.CloneAs<Rgba1010102>(default);
img.CloneAs<Rgba32>(default);
img.CloneAs<Rgba64>(default);
img.CloneAs<RgbaVector>(default);
img.CloneAs<Short2>(default);
img.CloneAs<Short4>(default);
ImageFrame.LoadPixelData<TPixel>(default, default(ReadOnlySpan<TPixel>), default, default);
ImageFrame.LoadPixelData<TPixel>(default, default(ReadOnlySpan<byte>), default, default);
}
/// <summary>
/// This method pre-seeds the WuQuantizer in the AoT compiler for iOS.
/// This method pre-seeds the all <see cref="IImageProcessingContextFactory"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompileWuQuantizer<TPixel>()
[Preserve]
private static void AotCompileImageProcessingContextFactory<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
=> default(DefaultImageOperationsProviderFactory).CreateImageProcessingContext<TPixel>(default, default, default);
/// <summary>
/// This method pre-seeds the all <see cref="IImageEncoderInternals"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileImageEncoderInternals<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
using (var test = new WuQuantizer<TPixel>(Configuration.Default, new WuQuantizer().Options))
{
var frame = new ImageFrame<TPixel>(Configuration.Default, 1, 1);
test.QuantizeFrame(frame, frame.Bounds());
}
default(BmpEncoderCore).Encode<TPixel>(default, default, default);
default(GifEncoderCore).Encode<TPixel>(default, default, default);
default(JpegEncoderCore).Encode<TPixel>(default, default, default);
default(PngEncoderCore).Encode<TPixel>(default, default, default);
default(TgaEncoderCore).Encode<TPixel>(default, default, default);
}
/// <summary>
/// This method pre-seeds the PaletteQuantizer in the AoT compiler for iOS.
/// This method pre-seeds the all <see cref="IImageDecoderInternals"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompilePaletteQuantizer<TPixel>()
[Preserve]
private static void AotCompileImageDecoderInternals<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
using (var test = (PaletteQuantizer<TPixel>)new PaletteQuantizer(Array.Empty<Color>()).CreatePixelSpecificQuantizer<TPixel>(Configuration.Default))
{
var frame = new ImageFrame<TPixel>(Configuration.Default, 1, 1);
test.QuantizeFrame(frame, frame.Bounds());
}
default(BmpDecoderCore).Decode<TPixel>(default, default, default);
default(GifDecoderCore).Decode<TPixel>(default, default, default);
default(JpegDecoderCore).Decode<TPixel>(default, default, default);
default(PngDecoderCore).Decode<TPixel>(default, default, default);
default(TgaDecoderCore).Decode<TPixel>(default, default, default);
}
/// <summary>
/// This method pre-seeds the all <see cref="IImageEncoder"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileImageEncoders<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileImageEncoder<TPixel, BmpEncoder>();
AotCompileImageEncoder<TPixel, GifEncoder>();
AotCompileImageEncoder<TPixel, JpegEncoder>();
AotCompileImageEncoder<TPixel, PngEncoder>();
AotCompileImageEncoder<TPixel, TgaEncoder>();
}
/// <summary>
/// This method pre-seeds the default dithering engine (FloydSteinbergDiffuser) in the AoT compiler for iOS.
/// This method pre-seeds the all <see cref="IImageDecoder"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompileDithering<TPixel>()
[Preserve]
private static void AotCompileImageDecoders<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
ErrorDither errorDither = ErrorDither.FloydSteinberg;
OrderedDither orderedDither = OrderedDither.Bayer2x2;
TPixel pixel = default;
using (var image = new ImageFrame<TPixel>(Configuration.Default, 1, 1))
{
errorDither.Dither(image, image.Bounds(), pixel, pixel, 0, 0, 0);
orderedDither.Dither(pixel, 0, 0, 0, 0);
}
AotCompileImageDecoder<TPixel, BmpDecoder>();
AotCompileImageDecoder<TPixel, GifDecoder>();
AotCompileImageDecoder<TPixel, JpegDecoder>();
AotCompileImageDecoder<TPixel, PngDecoder>();
AotCompileImageDecoder<TPixel, TgaDecoder>();
}
/// <summary>
/// This method pre-seeds the decoder and encoder for a given pixel format in the AoT compiler for iOS.
/// This method pre-seeds the <see cref="IImageEncoder"/> in the AoT compiler.
/// </summary>
/// <param name="decoder">The image decoder to seed.</param>
/// <param name="encoder">The image encoder to seed.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCodec<TPixel>(IImageDecoder decoder, IImageEncoder encoder)
/// <typeparam name="TEncoder">The encoder.</typeparam>
[Preserve]
private static void AotCompileImageEncoder<TPixel, TEncoder>()
where TPixel : unmanaged, IPixel<TPixel>
where TEncoder : class, IImageEncoder
{
try
{
decoder.Decode<TPixel>(Configuration.Default, null);
}
catch
{
}
default(TEncoder).Encode<TPixel>(default, default);
default(TEncoder).EncodeAsync<TPixel>(default, default, default);
}
try
{
encoder.Encode<TPixel>(null, null);
}
catch
{
}
/// <summary>
/// This method pre-seeds the <see cref="IImageDecoder"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TDecoder">The decoder.</typeparam>
[Preserve]
private static void AotCompileImageDecoder<TPixel, TDecoder>()
where TPixel : unmanaged, IPixel<TPixel>
where TDecoder : class, IImageDecoder
{
default(TDecoder).Decode<TPixel>(default, default);
default(TDecoder).DecodeAsync<TPixel>(default, default, default);
}
/// <summary>
/// This method pre-seeds the all <see cref="IImageProcessor" /> in the AoT compiler.
/// </summary>
/// <remarks>
/// There is no structure that implements ISwizzler.
/// </remarks>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileImageProcessors<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileImageProcessor<TPixel, CloningImageProcessor>();
AotCompileImageProcessor<TPixel, CropProcessor>();
AotCompileImageProcessor<TPixel, AffineTransformProcessor>();
AotCompileImageProcessor<TPixel, ProjectiveTransformProcessor>();
AotCompileImageProcessor<TPixel, RotateProcessor>();
AotCompileImageProcessor<TPixel, SkewProcessor>();
AotCompileImageProcessor<TPixel, ResizeProcessor>();
AotCompileImageProcessor<TPixel, EntropyCropProcessor>();
AotCompileImageProcessor<TPixel, AutoOrientProcessor>();
AotCompileImageProcessor<TPixel, FlipProcessor>();
AotCompileImageProcessor<TPixel, QuantizeProcessor>();
AotCompileImageProcessor<TPixel, BackgroundColorProcessor>();
AotCompileImageProcessor<TPixel, GlowProcessor>();
AotCompileImageProcessor<TPixel, VignetteProcessor>();
AotCompileImageProcessor<TPixel, AdaptiveHistogramEqualizationProcessor>();
AotCompileImageProcessor<TPixel, AdaptiveHistogramEqualizationSlidingWindowProcessor>();
AotCompileImageProcessor<TPixel, GlobalHistogramEqualizationProcessor>();
AotCompileImageProcessor<TPixel, AchromatomalyProcessor>();
AotCompileImageProcessor<TPixel, AchromatopsiaProcessor>();
AotCompileImageProcessor<TPixel, BlackWhiteProcessor>();
AotCompileImageProcessor<TPixel, BrightnessProcessor>();
AotCompileImageProcessor<TPixel, ContrastProcessor>();
AotCompileImageProcessor<TPixel, DeuteranomalyProcessor>();
AotCompileImageProcessor<TPixel, DeuteranopiaProcessor>();
AotCompileImageProcessor<TPixel, FilterProcessor>();
AotCompileImageProcessor<TPixel, GrayscaleBt601Processor>();
AotCompileImageProcessor<TPixel, GrayscaleBt709Processor>();
AotCompileImageProcessor<TPixel, HueProcessor>();
AotCompileImageProcessor<TPixel, InvertProcessor>();
AotCompileImageProcessor<TPixel, KodachromeProcessor>();
AotCompileImageProcessor<TPixel, LightnessProcessor>();
AotCompileImageProcessor<TPixel, LomographProcessor>();
AotCompileImageProcessor<TPixel, OpacityProcessor>();
AotCompileImageProcessor<TPixel, PolaroidProcessor>();
AotCompileImageProcessor<TPixel, ProtanomalyProcessor>();
AotCompileImageProcessor<TPixel, ProtanopiaProcessor>();
AotCompileImageProcessor<TPixel, SaturateProcessor>();
AotCompileImageProcessor<TPixel, SepiaProcessor>();
AotCompileImageProcessor<TPixel, TritanomalyProcessor>();
AotCompileImageProcessor<TPixel, TritanopiaProcessor>();
AotCompileImageProcessor<TPixel, OilPaintingProcessor>();
AotCompileImageProcessor<TPixel, PixelateProcessor>();
AotCompileImageProcessor<TPixel, PixelRowDelegateProcessor>();
AotCompileImageProcessor<TPixel, PositionAwarePixelRowDelegateProcessor>();
AotCompileImageProcessor<TPixel, DrawImageProcessor>();
AotCompileImageProcessor<TPixel, PaletteDitherProcessor>();
AotCompileImageProcessor<TPixel, BokehBlurProcessor>();
AotCompileImageProcessor<TPixel, BoxBlurProcessor>();
AotCompileImageProcessor<TPixel, EdgeDetector2DProcessor>();
AotCompileImageProcessor<TPixel, EdgeDetectorCompassProcessor>();
AotCompileImageProcessor<TPixel, EdgeDetectorProcessor>();
AotCompileImageProcessor<TPixel, GaussianBlurProcessor>();
AotCompileImageProcessor<TPixel, GaussianSharpenProcessor>();
AotCompileImageProcessor<TPixel, AdaptiveThresholdProcessor>();
AotCompileImageProcessor<TPixel, BinaryThresholdProcessor>();
AotCompilerCloningImageProcessor<TPixel, CloningImageProcessor>();
AotCompilerCloningImageProcessor<TPixel, CropProcessor>();
AotCompilerCloningImageProcessor<TPixel, AffineTransformProcessor>();
AotCompilerCloningImageProcessor<TPixel, ProjectiveTransformProcessor>();
AotCompilerCloningImageProcessor<TPixel, RotateProcessor>();
AotCompilerCloningImageProcessor<TPixel, SkewProcessor>();
AotCompilerCloningImageProcessor<TPixel, ResizeProcessor>();
}
/// <summary>
/// This method pre-seeds the <see cref="IImageProcessor" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TProc">The processor type</typeparam>
[Preserve]
private static void AotCompileImageProcessor<TPixel, TProc>()
where TPixel : unmanaged, IPixel<TPixel>
where TProc : class, IImageProcessor
=> default(TProc).CreatePixelSpecificProcessor<TPixel>(default, default, default);
/// <summary>
/// This method pre-seeds the <see cref="ICloningImageProcessor" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TProc">The processor type</typeparam>
[Preserve]
private static void AotCompilerCloningImageProcessor<TPixel, TProc>()
where TPixel : unmanaged, IPixel<TPixel>
where TProc : class, ICloningImageProcessor
=> default(TProc).CreatePixelSpecificCloningProcessor<TPixel>(default, default, default);
/// <summary>
/// This method pre-seeds the all <see cref="IImageProcessor"/> in the AoT compiler.
/// </summary>
/// <remarks>
/// There is no structure that implements ISwizzler.
/// </remarks>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileGenericImageProcessors<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileGenericCloningImageProcessor<TPixel, CropProcessor<TPixel>>();
AotCompileGenericCloningImageProcessor<TPixel, AffineTransformProcessor<TPixel>>();
AotCompileGenericCloningImageProcessor<TPixel, ProjectiveTransformProcessor<TPixel>>();
AotCompileGenericCloningImageProcessor<TPixel, ResizeProcessor<TPixel>>();
AotCompileGenericCloningImageProcessor<TPixel, RotateProcessor<TPixel>>();
}
/// <summary>
/// This method pre-seeds the <see cref="ICloningImageProcessor{TPixel}" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TProc">The processor type</typeparam>
[Preserve]
private static void AotCompileGenericCloningImageProcessor<TPixel, TProc>()
where TPixel : unmanaged, IPixel<TPixel>
where TProc : class, ICloningImageProcessor<TPixel>
=> default(TProc).CloneAndExecute();
/// <summary>
/// This method pre-seeds the all<see cref="IResampler" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileResamplers<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileResampler<TPixel, BicubicResampler>();
AotCompileResampler<TPixel, BoxResampler>();
AotCompileResampler<TPixel, CubicResampler>();
AotCompileResampler<TPixel, LanczosResampler>();
AotCompileResampler<TPixel, NearestNeighborResampler>();
AotCompileResampler<TPixel, TriangleResampler>();
AotCompileResampler<TPixel, WelchResampler>();
}
/// <summary>
/// This method pre-seeds the <see cref="IResampler" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TResampler">The processor type</typeparam>
[Preserve]
private static void AotCompileResampler<TPixel, TResampler>()
where TPixel : unmanaged, IPixel<TPixel>
where TResampler : struct, IResampler
{
default(TResampler).ApplyTransform<TPixel>(default);
default(AffineTransformProcessor<TPixel>).ApplyTransform<TResampler>(default);
default(ProjectiveTransformProcessor<TPixel>).ApplyTransform<TResampler>(default);
default(ResizeProcessor<TPixel>).ApplyTransform<TResampler>(default);
default(RotateProcessor<TPixel>).ApplyTransform<TResampler>(default);
}
/// <summary>
/// This method pre-seeds the all <see cref="IQuantizer" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileQuantizers<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileQuantizer<TPixel, OctreeQuantizer>();
AotCompileQuantizer<TPixel, PaletteQuantizer>();
AotCompileQuantizer<TPixel, WebSafePaletteQuantizer>();
AotCompileQuantizer<TPixel, WernerPaletteQuantizer>();
AotCompileQuantizer<TPixel, WuQuantizer>();
}
/// <summary>
/// This method pre-seeds the <see cref="IQuantizer" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TQuantizer">The quantizer type</typeparam>
[Preserve]
private static void AotCompileQuantizer<TPixel, TQuantizer>()
where TPixel : unmanaged, IPixel<TPixel>
where TQuantizer : class, IQuantizer
{
default(TQuantizer).CreatePixelSpecificQuantizer<TPixel>(default);
default(TQuantizer).CreatePixelSpecificQuantizer<TPixel>(default, default);
}
/// <summary>
/// This method pre-seeds the <see cref="IPixelSamplingStrategy" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompilePixelSamplingStrategys<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
default(DefaultPixelSamplingStrategy).EnumeratePixelRegions<TPixel>(default);
default(ExtensivePixelSamplingStrategy).EnumeratePixelRegions<TPixel>(default);
}
/// <summary>
/// This method pre-seeds the all <see cref="IDither" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileDithers<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileDither<TPixel, ErrorDither>();
AotCompileDither<TPixel, OrderedDither>();
}
/// <summary>
/// This method pre-seeds the <see cref="IDither" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TDither">The dither.</typeparam>
[Preserve]
private static void AotCompileDither<TPixel, TDither>()
where TPixel : unmanaged, IPixel<TPixel>
where TDither : struct, IDither
{
var octree = default(OctreeQuantizer<TPixel>);
default(TDither).ApplyQuantizationDither<OctreeQuantizer<TPixel>, TPixel>(ref octree, default, default, default);
var palette = default(PaletteQuantizer<TPixel>);
default(TDither).ApplyQuantizationDither<PaletteQuantizer<TPixel>, TPixel>(ref palette, default, default, default);
var wu = default(WuQuantizer<TPixel>);
default(TDither).ApplyQuantizationDither<WuQuantizer<TPixel>, TPixel>(ref wu, default, default, default);
default(TDither).ApplyPaletteDither<PaletteDitherProcessor<TPixel>.DitherProcessor, TPixel>(default, default, default);
}
/// <summary>
/// This method pre-seeds the all <see cref="MemoryAllocator" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileMemoryManagers<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
AotCompileMemoryManager<TPixel, ArrayPoolMemoryAllocator>();
AotCompileMemoryManager<TPixel, SimpleGcMemoryAllocator>();
}
/// <summary>
/// This method pre-seeds the PixelOperations engine for the AoT compiler on iOS.
/// This method pre-seeds the <see cref="MemoryAllocator" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompilePixelOperations<TPixel>()
/// <typeparam name="TBuffer">The buffer.</typeparam>
[Preserve]
private static void AotCompileMemoryManager<TPixel, TBuffer>()
where TPixel : unmanaged, IPixel<TPixel>
where TBuffer : MemoryAllocator
{
var pixelOp = new PixelOperations<TPixel>();
pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear);
default(TBuffer).Allocate<long>(default, default);
default(TBuffer).Allocate<short>(default, default);
default(TBuffer).Allocate<float>(default, default);
default(TBuffer).Allocate<double>(default, default);
default(TBuffer).Allocate<byte>(default, default);
default(TBuffer).Allocate<int>(default, default);
default(TBuffer).Allocate<bool>(default, default);
default(TBuffer).Allocate<decimal>(default, default);
default(TBuffer).Allocate<Block8x8>(default, default);
default(TBuffer).Allocate<Vector4>(default, default);
default(TBuffer).Allocate<TPixel>(default, default);
}
}
}

14
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
{
/// <summary>
/// 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.
/// </summary>
internal sealed class PreserveAttribute : System.Attribute
{
}
}

6
src/ImageSharp/Image.FromBytes.cs

@ -91,9 +91,9 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte array containing image data.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <returns>A new <see cref="Image{Rgba32}"/>.</returns>
public static Image<Rgba32> Load(byte[] data)
=> Load<Rgba32>(Configuration.Default, data);
/// <returns>A new <see cref="Image"/>.</returns>
public static Image Load(byte[] data)
=> Load(Configuration.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.

4
src/ImageSharp/ImageSharp.csproj

@ -31,8 +31,8 @@
<None Include="..\..\shared-infrastructure\branding\icons\imagesharp\sixlabors.imagesharp.128.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) OR '$(TargetFramework)' == 'net472'">

5
src/ImageSharp/Processing/KnownDitherings.cs

@ -30,6 +30,11 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
public static IDither Bayer8x8 { get; } = OrderedDither.Bayer8x8;
/// <summary>
/// Gets the order ditherer using the 16x16 Bayer dithering matrix
/// </summary>
public static IDither Bayer16x16 { get; } = OrderedDither.Bayer16x16;
/// <summary>
/// Gets the error Dither that implements the Atkinson algorithm.
/// </summary>

1
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;

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

@ -23,6 +23,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// </summary>
public static OrderedDither Bayer8x8 = new OrderedDither(8);
/// <summary>
/// Applies order dithering using the 16x16 Bayer dithering matrix.
/// </summary>
public static OrderedDither Bayer16x16 = new OrderedDither(16);
/// <summary>
/// Applies order dithering using the 3x3 ordered dithering matrix.
/// </summary>

57
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;
@ -145,24 +144,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
in ditherOperation);
}
// Spread assumes an even colorspace distribution and precision.
// 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.Max(1, Math.Pow(colors, 1.0 / 3) - 1));
[MethodImpl(InliningOptions.ShortMethod)]
internal TPixel Dither<TPixel>(
TPixel source,
int x,
int y,
int bitDepth,
int spread,
float scale)
where TPixel : unmanaged, IPixel<TPixel>
{
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);
@ -203,7 +205,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
private readonly ImageFrame<TPixel> source;
private readonly IndexedImageFrame<TPixel> destination;
private readonly Rectangle bounds;
private readonly int bitDepth;
private readonly int spread;
[MethodImpl(InliningOptions.ShortMethod)]
public QuantizeDitherRowOperation(
@ -218,23 +220,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)]
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<TPixel> sourceRow = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
Span<byte> 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,7 +251,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
private readonly ImageFrame<TPixel> source;
private readonly Rectangle bounds;
private readonly float scale;
private readonly int bitDepth;
private readonly int spread;
[MethodImpl(InliningOptions.ShortMethod)]
public PaletteDitherRowOperation(
@ -262,19 +265,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)]
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<TPixel> 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);
}
}
}

3
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
/// <see cref="IPaletteDitherImageProcessor{TPixel}.GetPaletteColor(TPixel)"/>.
/// </summary>
private readonly struct DitherProcessor : IPaletteDitherImageProcessor<TPixel>
/// <remarks>Internal for AOT</remarks>
internal readonly struct DitherProcessor : IPaletteDitherImageProcessor<TPixel>
{
private readonly EuclideanPixelMap<TPixel> pixelMap;

2
tests/Directory.Build.targets

@ -21,7 +21,7 @@
<PackageReference Update="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Update="BenchmarkDotNet.Diagnostics.Windows" Version="0.12.1" Condition="'$(IsWindows)'=='true'" />
<PackageReference Update="Colourful" Version="2.0.5" />
<PackageReference Update="Magick.NET-Q16-AnyCPU" Version="7.22.0" />
<PackageReference Update="Magick.NET-Q16-AnyCPU" Version="7.23.2.1" />
<PackageReference Update="Microsoft.DotNet.RemoteExecutor" Version="6.0.0-beta.20513.1" />
<PackageReference Update="Microsoft.DotNet.XUnitExtensions" Version="6.0.0-beta.20513.1" />
<PackageReference Update="Moq" Version="4.14.6" />

4
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<Rgba32>(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<Rgba32>(TestFile.Create(TestImages.Gif.Kumin).Bytes))
{
for (int i = 0; i < kumin1.Frames.Count; i++)
{

1
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) }
};

2
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);
}

2
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;

2
tests/ImageSharp.Tests/TestUtilities/TestUtils.cs

@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.Tests
using (Image<TPixel> image = provider.GetImage())
{
FormattableString testOutputDetails = $"";
image.Mutate(ctx => { testOutputDetails = processAndGetTestOutputDetails(ctx); });
image.Mutate(ctx => testOutputDetails = processAndGetTestOutputDetails(ctx));
image.DebugSave(
provider,

4
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

4
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

4
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

4
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

4
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

3
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

4
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

4
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

4
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

4
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

3
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

4
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

Loading…
Cancel
Save