Browse Source

Merge pull request #1574 from UltraNamahage/js/aot-experiments

Seed more methods with AotCompilerTools.
pull/1575/head
James Jackson-South 5 years ago
committed by GitHub
parent
commit
bf957c615c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 574
      src/ImageSharp/Advanced/AotCompilerTools.cs
  2. 14
      src/ImageSharp/Advanced/PreserveAttribute.cs
  3. 3
      src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs

574
src/ImageSharp/Advanced/AotCompilerTools.cs

@ -3,14 +3,29 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats; 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.Jpeg.Components;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; 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.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.Quantization;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
namespace SixLabors.ImageSharp.Advanced namespace SixLabors.ImageSharp.Advanced
{ {
@ -25,193 +40,510 @@ namespace SixLabors.ImageSharp.Advanced
[ExcludeFromCodeCoverage] [ExcludeFromCodeCoverage]
internal static class AotCompilerTools internal static class AotCompilerTools
{ {
static AotCompilerTools()
{
Unsafe.SizeOf<long>();
Unsafe.SizeOf<short>();
Unsafe.SizeOf<float>();
Unsafe.SizeOf<double>();
Unsafe.SizeOf<byte>();
Unsafe.SizeOf<int>();
Unsafe.SizeOf<Block8x8>();
Unsafe.SizeOf<Vector4>();
}
/// <summary> /// <summary>
/// This is the method that seeds the AoT compiler. /// This is the method that seeds the AoT compiler.
/// None of these seed methods needs to actually be called to seed the 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. /// The calls just need to be present when the code is compiled, and each implementation will be built.
/// </summary> /// </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() private static void SeedEverything()
{ {
Seed<A8>(); try
Seed<Argb32>(); {
Seed<Bgr24>(); Unsafe.SizeOf<long>();
Seed<Bgr565>(); Unsafe.SizeOf<short>();
Seed<Bgra32>(); Unsafe.SizeOf<float>();
Seed<Bgra4444>(); Unsafe.SizeOf<double>();
Seed<Bgra5551>(); Unsafe.SizeOf<byte>();
Seed<Byte4>(); Unsafe.SizeOf<int>();
Seed<L16>(); Unsafe.SizeOf<bool>();
Seed<L8>(); Unsafe.SizeOf<Block8x8>();
Seed<La16>(); Unsafe.SizeOf<Vector4>();
Seed<La32>();
Seed<HalfSingle>(); Seed<A8>();
Seed<HalfVector2>(); Seed<Argb32>();
Seed<HalfVector4>(); Seed<Bgr24>();
Seed<NormalizedByte2>(); Seed<Bgr565>();
Seed<NormalizedByte4>(); Seed<Bgra32>();
Seed<NormalizedShort2>(); Seed<Bgra4444>();
Seed<NormalizedShort4>(); Seed<Bgra5551>();
Seed<Rg32>(); Seed<Byte4>();
Seed<Rgb24>(); Seed<L16>();
Seed<Rgb48>(); Seed<L8>();
Seed<Rgba1010102>(); Seed<La16>();
Seed<Rgba32>(); Seed<La32>();
Seed<Rgba64>(); Seed<HalfSingle>();
Seed<RgbaVector>(); Seed<HalfVector2>();
Seed<Short2>(); Seed<HalfVector4>();
Seed<Short4>(); 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> /// <summary>
/// Seeds the compiler using the given pixel format. /// Seeds the compiler using the given pixel format.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void Seed<TPixel>() private static void Seed<TPixel>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// This is we actually call all the individual methods you need to seed. // This is we actually call all the individual methods you need to seed.
AotPixelInterface<TPixel>(); AotCompileImage<TPixel>();
AotCompileOctreeQuantizer<TPixel>(); AotCompileImageProcessingContextFactory<TPixel>();
AotCompileWuQuantizer<TPixel>(); AotCompileImageEncoderInternals<TPixel>();
AotCompilePaletteQuantizer<TPixel>(); AotCompileImageDecoderInternals<TPixel>();
AotCompileDithering<TPixel>(); AotCompileImageEncoders<TPixel>();
AotCompilePixelOperations<TPixel>(); AotCompileImageDecoders<TPixel>();
AotCompileImageProcessors<TPixel>();
AotCompileGenericImageProcessors<TPixel>();
AotCompileResamplers<TPixel>();
AotCompileQuantizers<TPixel>();
AotCompilePixelSamplingStrategys<TPixel>();
AotCompileDithers<TPixel>();
AotCompileMemoryManagers<TPixel>();
Unsafe.SizeOf<TPixel>(); Unsafe.SizeOf<TPixel>();
AotCodecs<TPixel>();
// TODO: Do the discovery work to figure out what works and what doesn't. // TODO: Do the discovery work to figure out what works and what doesn't.
} }
private static void AotPixelInterface<TPixel>() /// <summary>
/// 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>
[Preserve]
private static unsafe void AotCompileImage<TPixel>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
TPixel pixel = default; Image<TPixel> img = default;
Rgba32 rgba32 = default; img.CloneAs<A8>(default);
pixel.ToRgba32(ref rgba32); img.CloneAs<Argb32>(default);
pixel.FromRgba32(rgba32); img.CloneAs<Bgr24>(default);
pixel.FromScaledVector4(pixel.ToScaledVector4()); img.CloneAs<Bgr565>(default);
pixel.FromVector4(pixel.ToVector4()); 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);
pixel.FromArgb32(default); ImageFrame.LoadPixelData<TPixel>(default, default(ReadOnlySpan<TPixel>), default, default);
pixel.FromBgr24(default); ImageFrame.LoadPixelData<TPixel>(default, default(ReadOnlySpan<byte>), default, 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);
} }
/// <summary> /// <summary>
/// This method doesn't actually do anything but serves an important purpose... /// This method pre-seeds the all <see cref="IImageProcessingContextFactory"/> in the AoT compiler.
/// If you are running ImageSharp on iOS and try to call SaveAsGif, it will throw an exception: /// </summary>
/// "Attempting to JIT compile method... OctreeFrameQuantizer.ConstructPalette... while running in aot-only mode." /// <typeparam name="TPixel">The pixel format.</typeparam>
/// The reason this happens is the SaveAsGif method makes heavy use of generics, which are too confusing for the AoT [Preserve]
/// compiler used on Xamarin.iOS. It spins up the JIT compiler to try and figure it out, but that is an illegal op on private static void AotCompileImageProcessingContextFactory<TPixel>()
/// iOS so it bombs out. where TPixel : unmanaged, IPixel<TPixel>
/// If you are getting the above error, you need to call this method, which will pre-seed the AoT compiler with the => default(DefaultImageOperationsProviderFactory).CreateImageProcessingContext<TPixel>(default, default, default);
/// necessary methods to complete the SaveAsGif call. That's it, otherwise you should NEVER need this method!!!
/// <summary>
/// This method pre-seeds the all <see cref="IImageEncoderInternals"/> in the AoT compiler.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompileOctreeQuantizer<TPixel>() [Preserve]
where TPixel : unmanaged, IPixel<TPixel> private static void AotCompileImageEncoderInternals<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{ {
using var test = new OctreeQuantizer<TPixel>(Configuration.Default, new OctreeQuantizer().Options); default(BmpEncoderCore).Encode<TPixel>(default, default, default);
var frame = new ImageFrame<TPixel>(Configuration.Default, 1, 1); default(GifEncoderCore).Encode<TPixel>(default, default, default);
test.QuantizeFrame(frame, frame.Bounds()); default(JpegEncoderCore).Encode<TPixel>(default, default, default);
default(PngEncoderCore).Encode<TPixel>(default, default, default);
default(TgaEncoderCore).Encode<TPixel>(default, default, default);
} }
/// <summary> /// <summary>
/// This method pre-seeds the WuQuantizer in the AoT compiler for iOS. /// This method pre-seeds the all <see cref="IImageDecoderInternals"/> in the AoT compiler.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompileWuQuantizer<TPixel>() [Preserve]
private static void AotCompileImageDecoderInternals<TPixel>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using var test = new WuQuantizer<TPixel>(Configuration.Default, new WuQuantizer().Options); default(BmpDecoderCore).Decode<TPixel>(default, default, default);
var frame = new ImageFrame<TPixel>(Configuration.Default, 1, 1); default(GifDecoderCore).Decode<TPixel>(default, default, default);
test.QuantizeFrame(frame, frame.Bounds()); default(JpegDecoderCore).Decode<TPixel>(default, default, default);
default(PngDecoderCore).Decode<TPixel>(default, default, default);
default(TgaDecoderCore).Decode<TPixel>(default, default, default);
} }
/// <summary> /// <summary>
/// This method pre-seeds the PaletteQuantizer in the AoT compiler for iOS. /// This method pre-seeds the all <see cref="IImageEncoder"/> in the AoT compiler.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompilePaletteQuantizer<TPixel>() [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 all <see cref="IImageDecoder"/> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompileImageDecoders<TPixel>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using var test = (PaletteQuantizer<TPixel>)new PaletteQuantizer(Array.Empty<Color>()).CreatePixelSpecificQuantizer<TPixel>(Configuration.Default); AotCompileImageDecoder<TPixel, BmpDecoder>();
var frame = new ImageFrame<TPixel>(Configuration.Default, 1, 1); AotCompileImageDecoder<TPixel, GifDecoder>();
test.QuantizeFrame(frame, frame.Bounds()); AotCompileImageDecoder<TPixel, JpegDecoder>();
AotCompileImageDecoder<TPixel, PngDecoder>();
AotCompileImageDecoder<TPixel, TgaDecoder>();
} }
/// <summary> /// <summary>
/// This method pre-seeds the default dithering engine (FloydSteinbergDiffuser) in the AoT compiler for iOS. /// This method pre-seeds the <see cref="IImageEncoder"/> in the AoT compiler.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCompileDithering<TPixel>() /// <typeparam name="TEncoder">The encoder.</typeparam>
[Preserve]
private static void AotCompileImageEncoder<TPixel, TEncoder>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
where TEncoder : class, IImageEncoder
{ {
ErrorDither errorDither = ErrorDither.FloydSteinberg; default(TEncoder).Encode<TPixel>(default, default);
OrderedDither orderedDither = OrderedDither.Bayer2x2; default(TEncoder).EncodeAsync<TPixel>(default, default, default);
TPixel pixel = default; }
using (var image = new ImageFrame<TPixel>(Configuration.Default, 1, 1))
{ /// <summary>
errorDither.Dither(image, image.Bounds(), pixel, pixel, 0, 0, 0); /// This method pre-seeds the <see cref="IImageDecoder"/> in the AoT compiler.
orderedDither.Dither(pixel, 0, 0, 0, 0); /// </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> /// <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 all <see cref="IImageProcessor" /> in the AoT compiler.
/// </summary> /// </summary>
/// <remarks>
/// There is no structure that implements ISwizzler.
/// </remarks>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCodecs<TPixel>() [Preserve]
private static void AotCompileImageProcessors<TPixel>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Configuration configuration = Configuration.Default; AotCompileImageProcessor<TPixel, CloningImageProcessor>();
ImageFormatManager formatsManager = configuration.ImageFormatsManager; AotCompileImageProcessor<TPixel, CropProcessor>();
foreach (IImageFormat imageFormat in configuration.ImageFormats) AotCompileImageProcessor<TPixel, AffineTransformProcessor>();
{ AotCompileImageProcessor<TPixel, ProjectiveTransformProcessor>();
using var ms = new MemoryStream(); AotCompileImageProcessor<TPixel, RotateProcessor>();
using (var encoded = new Image<TPixel>(1, 1)) AotCompileImageProcessor<TPixel, SkewProcessor>();
{ AotCompileImageProcessor<TPixel, ResizeProcessor>();
encoded.Save(ms, formatsManager.FindEncoder(imageFormat)); AotCompileImageProcessor<TPixel, EntropyCropProcessor>();
ms.Position = 0; AotCompileImageProcessor<TPixel, AutoOrientProcessor>();
} AotCompileImageProcessor<TPixel, FlipProcessor>();
AotCompileImageProcessor<TPixel, QuantizeProcessor>();
using var decoded = Image.Load<TPixel>(ms); AotCompileImageProcessor<TPixel, BackgroundColorProcessor>();
Span<TPixel> span = decoded.GetPixelRowSpan(0); 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> /// <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> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <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 TPixel : unmanaged, IPixel<TPixel>
where TBuffer : MemoryAllocator
{ {
var pixelOp = new PixelOperations<TPixel>(); default(TBuffer).Allocate<long>(default, default);
pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear); 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
{
}
}

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

Loading…
Cancel
Save