diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 0cf28c6bb..4ac95be9a 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -248,7 +248,7 @@ internal static class AotCompilerTools } /// - /// This method pre-seeds the all in the AoT compiler. + /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. [Preserve] @@ -280,14 +280,14 @@ internal static class AotCompilerTools } /// - /// This method pre-seeds the in the AoT compiler. + /// This method pre-seeds the in the AoT compiler. /// /// The pixel format. /// The decoder. [Preserve] private static void AotCompileImageDecoder() where TPixel : unmanaged, IPixel - where TDecoder : class, IImageDecoder + where TDecoder : ImageDecoder => default(TDecoder).Decode(default, default, default); /// diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index 35d5690c7..d56aaa1ac 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp; /// /// Image decoder for generating an image out of a Windows bitmap stream. /// -public class BmpDecoder : IImageDecoderSpecialized +public sealed class BmpDecoder : SpecializedImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -20,27 +20,23 @@ public class BmpDecoder : IImageDecoderSpecialized } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - - /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - - /// - Image IImageDecoderSpecialized.Decode(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); Image image = new BmpDecoderCore(options).Decode(options.GeneralOptions.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options.GeneralOptions, image); + Resize(options.GeneralOptions, image); return image; } /// - Image IImageDecoderSpecialized.Decode(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); + + /// + protected internal override BmpDecoderOptions CreateDefaultSpecializedOptions(DecoderOptions options) + => new() { GeneralOptions = options }; } diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index cf8f4637e..6ae877516 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Gif; /// /// Decoder for generating an image out of a gif encoded stream. /// -public sealed class GifDecoder : IImageDecoder +public sealed class GifDecoder : ImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -20,7 +20,7 @@ public sealed class GifDecoder : IImageDecoder } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -28,12 +28,12 @@ public sealed class GifDecoder : IImageDecoder GifDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options, image); + Resize(options, image); return image; } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoder)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); } diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs deleted file mode 100644 index 7052bc49f..000000000 --- a/src/ImageSharp/Formats/IImageDecoder.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Formats; - -/// -/// Encapsulates properties and methods required for decoding an image from a stream. -/// -public interface IImageDecoder : IImageInfoDetector -{ - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// - /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. - /// - /// The pixel format. - /// The general decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The . - /// Thrown if the encoded image contains errors. - Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel; - - /// - /// Decodes the image from the specified stream to an . - /// - /// - /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. - /// - /// The general decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The . - /// Thrown if the encoded image contains errors. - Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken); -} diff --git a/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs b/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs deleted file mode 100644 index 77cffe34c..000000000 --- a/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Formats; - -/// -/// The base class for all specialized image decoders. -/// -/// The type of specialized options. -public interface IImageDecoderSpecialized : IImageDecoder - where T : ISpecializedDecoderOptions -{ - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// - /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. - /// - /// The pixel format. - /// The specialized decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The . - /// Thrown if the encoded image contains errors. - public Image Decode(T options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel; - - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// - /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. - /// - /// The specialized decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The . - /// Thrown if the encoded image contains errors. - public Image Decode(T options, Stream stream, CancellationToken cancellationToken); -} diff --git a/src/ImageSharp/Formats/ImageDecoder.cs b/src/ImageSharp/Formats/ImageDecoder.cs new file mode 100644 index 000000000..000cb9923 --- /dev/null +++ b/src/ImageSharp/Formats/ImageDecoder.cs @@ -0,0 +1,145 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +namespace SixLabors.ImageSharp.Formats; + +/// +/// The base class for all image decoders. +/// +public abstract class ImageDecoder +{ + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// + /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. + /// + /// The pixel format. + /// The general decoder options. + /// The containing image data. + /// The token to monitor for cancellation requests. + /// The . + /// Thrown if the encoded image contains errors. + protected internal abstract Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + where TPixel : unmanaged, IPixel; + + /// + /// Decodes the image from the specified stream to an . + /// + /// + /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. + /// + /// The general decoder options. + /// The containing image data. + /// The token to monitor for cancellation requests. + /// The . + /// Thrown if the encoded image contains errors. + protected internal abstract Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken); + + /// + /// Reads the raw image information from the specified stream. + /// + /// + /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. + /// + /// The general decoder options. + /// The containing image data. + /// The token to monitor for cancellation requests. + /// The object. + /// Thrown if the encoded image contains errors. + protected internal abstract IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken); + + /// + /// Performs a resize operation against the decoded image. If the target size is not set, or the image size + /// already matches the target size, the image is untouched. + /// + /// The decoder options. + /// The decoded image. + protected static void Resize(DecoderOptions options, Image image) + { + if (ShouldResize(options, image)) + { + ResizeOptions resizeOptions = new() + { + Size = options.TargetSize.Value, + Sampler = options.Sampler, + Mode = ResizeMode.Max + }; + + image.Mutate(x => x.Resize(resizeOptions)); + } + } + + /// + /// Determines whether the decoded image should be resized. + /// + /// The decoder options. + /// The decoded image. + /// if the image should be resized, otherwise; . + private static bool ShouldResize(DecoderOptions options, Image image) + { + if (options.TargetSize is null) + { + return false; + } + + Size targetSize = options.TargetSize.Value; + Size currentSize = image.Size(); + return currentSize.Width != targetSize.Width && currentSize.Height != targetSize.Height; + } +} + +/// +/// The base class for all specialized image decoders. +/// Specialized decoders allow for additional options to be passed to the decoder. +/// +/// The type of specialized options. +public abstract class SpecializedImageDecoder : ImageDecoder + where T : ISpecializedDecoderOptions +{ + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// + /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. + /// + /// The pixel format. + /// The specialized decoder options. + /// The containing image data. + /// The token to monitor for cancellation requests. + /// The . + /// Thrown if the encoded image contains errors. + protected internal abstract Image Decode(T options, Stream stream, CancellationToken cancellationToken) + where TPixel : unmanaged, IPixel; + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// + /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use. + /// + /// The specialized decoder options. + /// The containing image data. + /// The token to monitor for cancellation requests. + /// The . + /// Thrown if the encoded image contains errors. + protected internal abstract Image Decode(T options, Stream stream, CancellationToken cancellationToken); + + /// + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); + + /// + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); + + /// + /// A factory method for creating the default specialized options. + /// + /// The general decoder options. + /// The new . + protected internal abstract T CreateDefaultSpecializedOptions(DecoderOptions options); +} diff --git a/src/ImageSharp/Formats/ImageDecoderExtensions.cs b/src/ImageSharp/Formats/ImageDecoderExtensions.cs index a18974bbd..26ceec3f6 100644 --- a/src/ImageSharp/Formats/ImageDecoderExtensions.cs +++ b/src/ImageSharp/Formats/ImageDecoderExtensions.cs @@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats; /// -/// Extensions methods for and . +/// Extensions methods for and . /// public static class ImageDecoderExtensions { @@ -18,7 +18,7 @@ public static class ImageDecoderExtensions /// The containing image data. /// The object. /// Thrown if the encoded image contains errors. - public static IImageInfo Identify(this IImageDecoder decoder, DecoderOptions options, Stream stream) + public static IImageInfo Identify(this ImageDecoder decoder, DecoderOptions options, Stream stream) => Image.WithSeekableStream( options, stream, @@ -33,7 +33,7 @@ public static class ImageDecoderExtensions /// The token to monitor for cancellation requests. /// The object. /// Thrown if the encoded image contains errors. - public static Task IdentifyAsync(this IImageDecoder decoder, DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) + public static Task IdentifyAsync(this ImageDecoder decoder, DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) => Image.WithSeekableStreamAsync( options, stream, @@ -49,7 +49,7 @@ public static class ImageDecoderExtensions /// The containing image data. /// The . /// Thrown if the encoded image contains errors. - public static Image Decode(this IImageDecoder decoder, DecoderOptions options, Stream stream) + public static Image Decode(this ImageDecoder decoder, DecoderOptions options, Stream stream) where TPixel : unmanaged, IPixel => Image.WithSeekableStream( options, @@ -64,7 +64,7 @@ public static class ImageDecoderExtensions /// The containing image data. /// The . /// Thrown if the encoded image contains errors. - public static Image Decode(this IImageDecoder decoder, DecoderOptions options, Stream stream) + public static Image Decode(this ImageDecoder decoder, DecoderOptions options, Stream stream) => Image.WithSeekableStream( options, stream, @@ -80,7 +80,7 @@ public static class ImageDecoderExtensions /// The token to monitor for cancellation requests. /// A representing the asynchronous operation. /// Thrown if the encoded image contains errors. - public static Task> DecodeAsync(this IImageDecoder decoder, DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) + public static Task> DecodeAsync(this ImageDecoder decoder, DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel => Image.WithSeekableStreamAsync( options, @@ -97,7 +97,7 @@ public static class ImageDecoderExtensions /// The token to monitor for cancellation requests. /// A representing the asynchronous operation. /// Thrown if the encoded image contains errors. - public static Task DecodeAsync(this IImageDecoder decoder, DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) + public static Task DecodeAsync(this ImageDecoder decoder, DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) => Image.WithSeekableStreamAsync( options, stream, @@ -114,7 +114,7 @@ public static class ImageDecoderExtensions /// The containing image data. /// The . /// Thrown if the encoded image contains errors. - public static Image Decode(this IImageDecoderSpecialized decoder, T options, Stream stream) + public static Image Decode(this SpecializedImageDecoder decoder, T options, Stream stream) where T : ISpecializedDecoderOptions where TPixel : unmanaged, IPixel => Image.WithSeekableStream( @@ -131,7 +131,7 @@ public static class ImageDecoderExtensions /// The containing image data. /// The . /// Thrown if the encoded image contains errors. - public static Image Decode(this IImageDecoderSpecialized decoder, T options, Stream stream) + public static Image Decode(this SpecializedImageDecoder decoder, T options, Stream stream) where T : ISpecializedDecoderOptions => Image.WithSeekableStream( options.GeneralOptions, @@ -149,7 +149,7 @@ public static class ImageDecoderExtensions /// The token to monitor for cancellation requests. /// A representing the asynchronous operation. /// Thrown if the encoded image contains errors. - public static Task> DecodeAsync(this IImageDecoderSpecialized decoder, T options, Stream stream, CancellationToken cancellationToken = default) + public static Task> DecodeAsync(this SpecializedImageDecoder decoder, T options, Stream stream, CancellationToken cancellationToken = default) where T : ISpecializedDecoderOptions where TPixel : unmanaged, IPixel => Image.WithSeekableStreamAsync( @@ -168,7 +168,7 @@ public static class ImageDecoderExtensions /// The token to monitor for cancellation requests. /// A representing the asynchronous operation. /// Thrown if the encoded image contains errors. - public static Task DecodeAsync(this IImageDecoderSpecialized decoder, T options, Stream stream, CancellationToken cancellationToken = default) + public static Task DecodeAsync(this SpecializedImageDecoder decoder, T options, Stream stream, CancellationToken cancellationToken = default) where T : ISpecializedDecoderOptions => Image.WithSeekableStreamAsync( options.GeneralOptions, diff --git a/src/ImageSharp/Formats/ImageDecoderUtilities.cs b/src/ImageSharp/Formats/ImageDecoderUtilities.cs index c05e0d83c..288f72eac 100644 --- a/src/ImageSharp/Formats/ImageDecoderUtilities.cs +++ b/src/ImageSharp/Formats/ImageDecoderUtilities.cs @@ -4,54 +4,14 @@ using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Formats; /// -/// Utility methods for . +/// Utility methods for . /// internal static class ImageDecoderUtilities { - /// - /// Performs a resize operation against the decoded image. If the target size is not set, or the image size - /// already matches the target size, the image is untouched. - /// - /// The decoder options. - /// The decoded image. - public static void Resize(DecoderOptions options, Image image) - { - if (ShouldResize(options, image)) - { - ResizeOptions resizeOptions = new() - { - Size = options.TargetSize.Value, - Sampler = options.Sampler, - Mode = ResizeMode.Max - }; - - image.Mutate(x => x.Resize(resizeOptions)); - } - } - - /// - /// Determines whether the decoded image should be resized. - /// - /// The decoder options. - /// The decoded image. - /// if the image should be resized, otherwise; . - private static bool ShouldResize(DecoderOptions options, Image image) - { - if (options.TargetSize is null) - { - return false; - } - - Size targetSize = options.TargetSize.Value; - Size currentSize = image.Size(); - return currentSize.Width != targetSize.Width && currentSize.Height != targetSize.Height; - } - internal static IImageInfo Identify( this IImageDecoderInternals decoder, Configuration configuration, diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs index 9f22c6229..922018456 100644 --- a/src/ImageSharp/Formats/ImageFormatManager.cs +++ b/src/ImageSharp/Formats/ImageFormatManager.cs @@ -22,9 +22,9 @@ public class ImageFormatManager private readonly ConcurrentDictionary mimeTypeEncoders = new(); /// - /// The list of supported keyed to mime types. + /// The list of supported keyed to mime types. /// - private readonly ConcurrentDictionary mimeTypeDecoders = new(); + private readonly ConcurrentDictionary mimeTypeDecoders = new(); /// /// The list of supported s. @@ -59,9 +59,9 @@ public class ImageFormatManager internal IEnumerable FormatDetectors => this.imageFormatDetectors; /// - /// Gets the currently registered s. + /// Gets the currently registered s. /// - internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; + internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; /// /// Gets the currently registered s. @@ -122,7 +122,7 @@ public class ImageFormatManager Guard.NotNull(imageFormat, nameof(imageFormat)); Guard.NotNull(encoder, nameof(encoder)); this.AddImageFormat(imageFormat); - this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); + this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (_, _) => encoder); } /// @@ -130,12 +130,12 @@ public class ImageFormatManager /// /// The image format to register the encoder for. /// The decoder to use, - public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) + public void SetDecoder(IImageFormat imageFormat, ImageDecoder decoder) { Guard.NotNull(imageFormat, nameof(imageFormat)); Guard.NotNull(decoder, nameof(decoder)); this.AddImageFormat(imageFormat); - this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); + this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (_, _) => decoder); } /// @@ -158,12 +158,12 @@ public class ImageFormatManager /// For the specified mime type find the decoder. /// /// The format to discover - /// The if found otherwise null - public IImageDecoder FindDecoder(IImageFormat format) + /// The if found otherwise null + public ImageDecoder FindDecoder(IImageFormat format) { Guard.NotNull(format, nameof(format)); - return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder) + return this.mimeTypeDecoders.TryGetValue(format, out ImageDecoder decoder) ? decoder : null; } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index 7e85ddad5..25ace3b8e 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg; /// /// Decoder for generating an image out of a jpeg encoded stream. /// -public sealed class JpegDecoder : IImageDecoderSpecialized +public sealed class JpegDecoder : SpecializedImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -21,15 +21,7 @@ public sealed class JpegDecoder : IImageDecoderSpecialized } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - - /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - - /// - Image IImageDecoderSpecialized.Decode(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -39,13 +31,17 @@ public sealed class JpegDecoder : IImageDecoderSpecialized if (options.ResizeMode != JpegDecoderResizeMode.IdctOnly) { - ImageDecoderUtilities.Resize(options.GeneralOptions, image); + Resize(options.GeneralOptions, image); } return image; } /// - Image IImageDecoderSpecialized.Decode(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); + + /// + protected internal override JpegDecoderOptions CreateDefaultSpecializedOptions(DecoderOptions options) + => new() { GeneralOptions = options }; } diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs index 2caf8ecc1..acfebdc84 100644 --- a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs +++ b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs @@ -24,10 +24,10 @@ namespace SixLabors.ImageSharp.Formats.Pbm; /// /// The specification of these images is found at . /// -public sealed class PbmDecoder : IImageDecoder +public sealed class PbmDecoder : ImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -36,7 +36,7 @@ public sealed class PbmDecoder : IImageDecoder } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -44,12 +44,12 @@ public sealed class PbmDecoder : IImageDecoder PbmDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options, image); + Resize(options, image); return image; } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoder)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); } diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs index bcc193f0b..617ca1c17 100644 --- a/src/ImageSharp/Formats/Png/PngDecoder.cs +++ b/src/ImageSharp/Formats/Png/PngDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Png; /// /// Decoder for generating an image out of a png encoded stream. /// -public sealed class PngDecoder : IImageDecoder +public sealed class PngDecoder : ImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -20,7 +20,7 @@ public sealed class PngDecoder : IImageDecoder } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -28,13 +28,13 @@ public sealed class PngDecoder : IImageDecoder PngDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options, image); + Resize(options, image); return image; } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -47,48 +47,47 @@ public sealed class PngDecoder : IImageDecoder PngColorType color = meta.ColorType.GetValueOrDefault(); PngBitDepth bits = meta.BitDepth.GetValueOrDefault(); - var imageDecoder = (IImageDecoder)this; switch (color) { case PngColorType.Grayscale: if (bits == PngBitDepth.Bit16) { return !meta.HasTransparency - ? imageDecoder.Decode(options, stream, cancellationToken) - : imageDecoder.Decode(options, stream, cancellationToken); + ? this.Decode(options, stream, cancellationToken) + : this.Decode(options, stream, cancellationToken); } return !meta.HasTransparency - ? imageDecoder.Decode(options, stream, cancellationToken) - : imageDecoder.Decode(options, stream, cancellationToken); + ? this.Decode(options, stream, cancellationToken) + : this.Decode(options, stream, cancellationToken); case PngColorType.Rgb: if (bits == PngBitDepth.Bit16) { return !meta.HasTransparency - ? imageDecoder.Decode(options, stream, cancellationToken) - : imageDecoder.Decode(options, stream, cancellationToken); + ? this.Decode(options, stream, cancellationToken) + : this.Decode(options, stream, cancellationToken); } return !meta.HasTransparency - ? imageDecoder.Decode(options, stream, cancellationToken) - : imageDecoder.Decode(options, stream, cancellationToken); + ? this.Decode(options, stream, cancellationToken) + : this.Decode(options, stream, cancellationToken); case PngColorType.Palette: - return imageDecoder.Decode(options, stream, cancellationToken); + return this.Decode(options, stream, cancellationToken); case PngColorType.GrayscaleWithAlpha: return (bits == PngBitDepth.Bit16) - ? imageDecoder.Decode(options, stream, cancellationToken) - : imageDecoder.Decode(options, stream, cancellationToken); + ? this.Decode(options, stream, cancellationToken) + : this.Decode(options, stream, cancellationToken); case PngColorType.RgbWithAlpha: return (bits == PngBitDepth.Bit16) - ? imageDecoder.Decode(options, stream, cancellationToken) - : imageDecoder.Decode(options, stream, cancellationToken); + ? this.Decode(options, stream, cancellationToken) + : this.Decode(options, stream, cancellationToken); default: - return imageDecoder.Decode(options, stream, cancellationToken); + return this.Decode(options, stream, cancellationToken); } } } diff --git a/src/ImageSharp/Formats/Tga/TgaDecoder.cs b/src/ImageSharp/Formats/Tga/TgaDecoder.cs index 362daa77d..b6ae9bd57 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoder.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Tga; /// /// Image decoder for Truevision TGA images. /// -public sealed class TgaDecoder : IImageDecoder +public sealed class TgaDecoder : ImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -20,7 +20,7 @@ public sealed class TgaDecoder : IImageDecoder } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -28,12 +28,12 @@ public sealed class TgaDecoder : IImageDecoder TgaDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options, image); + Resize(options, image); return image; } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoder)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs index 4e1c9c2f8..04b57e297 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs @@ -32,7 +32,7 @@ internal class WebpTiffCompression : TiffBaseDecompressor /// protected override void Decompress(BufferedReadStream stream, int byteCount, int stripHeight, Span buffer, CancellationToken cancellationToken) { - using Image image = ((IImageDecoder)new WebpDecoder()).Decode(this.options, stream, cancellationToken); + using Image image = new WebpDecoder().Decode(this.options, stream, cancellationToken); CopyImageBytesToBuffer(buffer, image.Frames.RootFrame.PixelBuffer); } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs index b433222a0..a2d585a4c 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff; /// /// Image decoder for generating an image out of a TIFF stream. /// -public class TiffDecoder : IImageDecoder +public class TiffDecoder : ImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -20,7 +20,7 @@ public class TiffDecoder : IImageDecoder } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -28,12 +28,12 @@ public class TiffDecoder : IImageDecoder TiffDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options, image); + Resize(options, image); return image; } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoder)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); } diff --git a/src/ImageSharp/Formats/Webp/WebpDecoder.cs b/src/ImageSharp/Formats/Webp/WebpDecoder.cs index 86c868d7e..aa62ee709 100644 --- a/src/ImageSharp/Formats/Webp/WebpDecoder.cs +++ b/src/ImageSharp/Formats/Webp/WebpDecoder.cs @@ -8,10 +8,10 @@ namespace SixLabors.ImageSharp.Formats.Webp; /// /// Image decoder for generating an image out of a webp stream. /// -public sealed class WebpDecoder : IImageDecoder +public sealed class WebpDecoder : ImageDecoder { /// - IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -21,7 +21,7 @@ public sealed class WebpDecoder : IImageDecoder } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -29,12 +29,12 @@ public sealed class WebpDecoder : IImageDecoder using WebpDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - ImageDecoderUtilities.Resize(options, image); + Resize(options, image); return image; } /// - Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoder)this).Decode(options, stream, cancellationToken); + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); } diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 6953da1ce..9e902c7bb 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -99,7 +99,7 @@ public abstract partial class Image /// The image stream to read the header from. /// The IImageFormat. /// The image format or null if none found. - private static IImageDecoder DiscoverDecoder(DecoderOptions options, Stream stream, out IImageFormat format) + private static ImageDecoder DiscoverDecoder(DecoderOptions options, Stream stream, out IImageFormat format) { format = InternalDetectFormat(options.Configuration, stream); @@ -121,7 +121,7 @@ public abstract partial class Image private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); + ImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); if (decoder is null) { return (null, null); @@ -133,7 +133,7 @@ public abstract partial class Image private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); + ImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); if (decoder is null) { return (null, null); @@ -154,14 +154,8 @@ public abstract partial class Image /// private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); - - if (decoder is not IImageInfoDetector detector) - { - return (null, null); - } - - IImageInfo info = detector?.Identify(options, stream, cancellationToken); + ImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); + IImageInfo info = decoder?.Identify(options, stream, cancellationToken); return (info, format); } } diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index eefb08776..8cf7e0fe2 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -610,7 +610,7 @@ public abstract partial class Image StringBuilder sb = new(); sb.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) + foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) { sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs index 0b977bfbc..fc8beb687 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs @@ -19,19 +19,13 @@ public class IdentifyJpeg public string TestImage { get; set; } [GlobalSetup] - public void ReadImages() - { - if (this.jpegBytes == null) - { - this.jpegBytes = File.ReadAllBytes(this.TestImageFullPath); - } - } + public void ReadImages() => this.jpegBytes ??= File.ReadAllBytes(this.TestImageFullPath); [Benchmark] public IImageInfo Identify() { - using var memoryStream = new MemoryStream(this.jpegBytes); - IImageDecoder decoder = new JpegDecoder(); + using MemoryStream memoryStream = new(this.jpegBytes); + JpegDecoder decoder = new(); return decoder.Identify(DecoderOptions.Default, memoryStream, default); } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 8743e77bd..14eff7ba9 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -278,7 +278,7 @@ public class BmpEncoderTests // Use the default decoder to test our encoded image. This verifies the content. // We do not verify the reference image though as some are invalid. - IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + ImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using FileStream stream = File.OpenRead(actualOutputFile); using Image referenceImage = referenceDecoder.Decode(DecoderOptions.Default, stream, default); referenceImage.CompareToReferenceOutput( @@ -309,7 +309,7 @@ public class BmpEncoderTests // Use the default decoder to test our encoded image. This verifies the content. // We do not verify the reference image though as some are invalid. - IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + ImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using FileStream stream = File.OpenRead(actualOutputFile); using Image referenceImage = referenceDecoder.Decode(DecoderOptions.Default, stream, default); referenceImage.CompareToReferenceOutput( @@ -378,7 +378,7 @@ public class BmpEncoderTests bool supportTransparency = true, // if set to true, will write a V4 header, otherwise a V3 header. IQuantizer quantizer = null, ImageComparer customComparer = null, - IImageDecoder referenceDecoder = null) + ImageDecoder referenceDecoder = null) where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(); diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs index 06fe2601c..c982979ff 100644 --- a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs +++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs @@ -64,7 +64,7 @@ public class ImageFormatManagerTests [Fact] public void RegisterNullSetDecoder() { - Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(null, new Mock().Object)); + Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(null, new Mock().Object)); Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null)); Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(null, null)); } @@ -87,14 +87,14 @@ public class ImageFormatManagerTests [Fact] public void RegisterMimeTypeDecoderReplacesLast() { - IImageDecoder decoder1 = new Mock().Object; + ImageDecoder decoder1 = new Mock().Object; this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); - IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + ImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); Assert.Equal(decoder1, found); - IImageDecoder decoder2 = new Mock().Object; + ImageDecoder decoder2 = new Mock().Object; this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); - IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + ImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); Assert.Equal(decoder2, found2); Assert.NotEqual(found, found2); } @@ -102,8 +102,8 @@ public class ImageFormatManagerTests [Fact] public void AddFormatCallsConfig() { - var provider = new Mock(); - var config = new Configuration(); + Mock provider = new(); + Configuration config = new(); config.Configure(provider.Object); provider.Verify(x => x.Configure(config)); @@ -113,9 +113,9 @@ public class ImageFormatManagerTests public void DetectFormatAllocatesCleanBuffer() { byte[] jpegImage; - using (var buffer = new MemoryStream()) + using (MemoryStream buffer = new()) { - using var image = new Image(100, 100); + using Image image = new(100, 100); image.SaveAsJpeg(buffer); jpegImage = buffer.ToArray(); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs index 3603000f6..f88431be7 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs @@ -178,7 +178,7 @@ public partial class JpegDecoderTests Assert.Equal(expectedColorType, meta.ColorType); } - private static void TestImageInfo(string imagePath, IImageDecoder decoder, bool useIdentify, Action test) + private static void TestImageInfo(string imagePath, ImageDecoder decoder, bool useIdentify, Action test) { var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); @@ -196,7 +196,7 @@ public partial class JpegDecoderTests private static void TestMetadataImpl( bool useIdentify, - IImageDecoder decoder, + ImageDecoder decoder, string imagePath, int expectedPixelSize, bool exifProfilePresent, diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 2656144d3..0f33f2231 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -588,7 +588,7 @@ public partial class PngEncoderTests string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType); // Compare to the Magick reference decoder. - IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + ImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); // We compare using both our decoder and the reference decoder as pixel transformation // occurs within the encoder itself leaving the input image unaffected. diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderBaseTester.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderBaseTester.cs index 95f37ba40..456604d8b 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderBaseTester.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderBaseTester.cs @@ -16,7 +16,7 @@ public abstract class TiffDecoderBaseTester protected static MagickReferenceDecoder ReferenceDecoder => new(); - protected static void TestTiffDecoder(TestImageProvider provider, IImageDecoder referenceDecoder = null, bool useExactComparer = true, float compareTolerance = 0.001f) + protected static void TestTiffDecoder(TestImageProvider provider, ImageDecoder referenceDecoder = null, bool useExactComparer = true, float compareTolerance = 0.001f) where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(TiffDecoder); diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs index 6da0d4fd8..0b4016dd5 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff; [Trait("Format", "Tiff")] public abstract class TiffEncoderBaseTester { - protected static readonly IImageDecoder ReferenceDecoder = new MagickReferenceDecoder(); + protected static readonly ImageDecoder ReferenceDecoder = new MagickReferenceDecoder(); protected static void TestStripLength( TestImageProvider provider, @@ -85,7 +85,7 @@ public abstract class TiffEncoderBaseTester TiffPredictor predictor = TiffPredictor.None, bool useExactComparer = true, float compareTolerance = 0.001f, - IImageDecoder imageDecoder = null) + ImageDecoder imageDecoder = null) where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(); diff --git a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.Fakes.cs b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.Fakes.cs new file mode 100644 index 000000000..10d834235 --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.Fakes.cs @@ -0,0 +1,14 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SixLabors.ImageSharp.Tests; + +public partial class ImageTests +{ +} diff --git a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs index cace719bd..3f51f1967 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs @@ -19,7 +19,7 @@ public partial class ImageTests protected Image localStreamReturnImageAgnostic; - protected Mock localDecoder; + protected Mock localDecoder; protected IImageFormatDetector localMimeTypeDetector; @@ -59,11 +59,10 @@ public partial class ImageTests this.localImageInfoMock = new Mock(); this.localImageFormatMock = new Mock(); - var detector = new Mock(); - detector.Setup(x => x.Identify(It.IsAny(), It.IsAny(), It.IsAny())) + this.localDecoder = new Mock(); + this.localDecoder.Setup(x => x.Identify(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(this.localImageInfoMock.Object); - this.localDecoder = detector.As(); this.localDecoder .Setup(x => x.Decode(It.IsAny(), It.IsAny(), It.IsAny())) .Callback((c, s, ct) => diff --git a/tests/ImageSharp.Tests/TestFile.cs b/tests/ImageSharp.Tests/TestFile.cs index 9d920d718..fc95d5fa8 100644 --- a/tests/ImageSharp.Tests/TestFile.cs +++ b/tests/ImageSharp.Tests/TestFile.cs @@ -143,19 +143,22 @@ public sealed class TestFile /// /// Creates a new image. /// + /// The image decoder. /// /// The . /// - public Image CreateRgba32Image(IImageDecoder decoder) + public Image CreateRgba32Image(ImageDecoder decoder) => this.CreateRgba32Image(decoder, new()); /// /// Creates a new image. /// + /// The image decoder. + /// The general decoder options. /// /// The . /// - public Image CreateRgba32Image(IImageDecoder decoder, DecoderOptions options) + public Image CreateRgba32Image(ImageDecoder decoder, DecoderOptions options) { options.Configuration = this.Image.GetConfiguration(); using MemoryStream stream = new(this.Bytes); diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 127ccd32d..cecde5ddb 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -187,7 +187,7 @@ public class TestFormat : IConfigurationModule, IImageFormat public TestHeader(TestFormat testFormat) => this.testFormat = testFormat; } - public class TestDecoder : IImageDecoderSpecialized + public class TestDecoder : SpecializedImageDecoder { private readonly TestFormat testFormat; @@ -201,18 +201,13 @@ public class TestFormat : IConfigurationModule, IImageFormat public bool IsSupportedFileFormat(Span header) => this.testFormat.IsSupportedFileFormat(header); - public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); + protected internal override TestDecoderOptions CreateDefaultSpecializedOptions(DecoderOptions options) + => new() { GeneralOptions = options }; - public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + protected internal override Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Configuration configuration = options.GeneralOptions.Configuration; var ms = new MemoryStream(); @@ -229,7 +224,7 @@ public class TestFormat : IConfigurationModule, IImageFormat return this.testFormat.Sample(); } - public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index a0f544b2f..e9b7b8407 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -27,7 +27,7 @@ public abstract partial class TestImageProvider : IXunitSerializable public Key( PixelTypes pixelType, string filePath, - IImageDecoder customDecoder, + ImageDecoder customDecoder, DecoderOptions options, ISpecializedDecoderOptions specialized) { @@ -175,11 +175,11 @@ public abstract partial class TestImageProvider : IXunitSerializable public override Image GetImage() { - IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(this.FilePath); + ImageDecoder decoder = TestEnvironment.GetReferenceDecoder(this.FilePath); return this.GetImage(decoder); } - public override Image GetImage(IImageDecoder decoder, DecoderOptions options) + public override Image GetImage(ImageDecoder decoder, DecoderOptions options) { Guard.NotNull(decoder, nameof(decoder)); Guard.NotNull(options, nameof(options)); @@ -202,7 +202,7 @@ public abstract partial class TestImageProvider : IXunitSerializable return cachedImage.Clone(this.Configuration); } - public override Task> GetImageAsync(IImageDecoder decoder, DecoderOptions options) + public override Task> GetImageAsync(ImageDecoder decoder, DecoderOptions options) { Guard.NotNull(decoder, nameof(decoder)); Guard.NotNull(options, nameof(options)); @@ -216,7 +216,7 @@ public abstract partial class TestImageProvider : IXunitSerializable return Task.FromResult(decoder.Decode(options, stream, default)); } - public override Image GetImage(IImageDecoderSpecialized decoder, T options) + public override Image GetImage(SpecializedImageDecoder decoder, T options) { Guard.NotNull(decoder, nameof(decoder)); Guard.NotNull(options, nameof(options)); @@ -239,7 +239,7 @@ public abstract partial class TestImageProvider : IXunitSerializable return cachedImage.Clone(this.Configuration); } - public override Task> GetImageAsync(IImageDecoderSpecialized decoder, T options) + public override Task> GetImageAsync(SpecializedImageDecoder decoder, T options) { Guard.NotNull(decoder, nameof(decoder)); Guard.NotNull(options, nameof(options)); @@ -266,7 +266,7 @@ public abstract partial class TestImageProvider : IXunitSerializable info.AddValue("path", this.FilePath); } - private Image DecodeImage(IImageDecoder decoder, DecoderOptions options) + private Image DecodeImage(ImageDecoder decoder, DecoderOptions options) { options.Configuration = this.Configuration; @@ -275,7 +275,7 @@ public abstract partial class TestImageProvider : IXunitSerializable return decoder.Decode(options, stream, default); } - private Image DecodeImage(IImageDecoderSpecialized decoder, T options) + private Image DecodeImage(SpecializedImageDecoder decoder, T options) where T : class, ISpecializedDecoderOptions, new() { options.GeneralOptions.Configuration = this.Configuration; diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index 8cd04f1cd..48e63bdca 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -87,29 +87,30 @@ public abstract partial class TestImageProvider : ITestImageProvider, IX /// A test image. public abstract Image GetImage(); - public Image GetImage(IImageDecoder decoder) + public Image GetImage(ImageDecoder decoder) => this.GetImage(decoder, new()); - public Task> GetImageAsync(IImageDecoder decoder) + public Task> GetImageAsync(ImageDecoder decoder) => this.GetImageAsync(decoder, new()); - public virtual Image GetImage(IImageDecoder decoder, DecoderOptions options) + public virtual Image GetImage(ImageDecoder decoder, DecoderOptions options) => throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!"); - public virtual Task> GetImageAsync(IImageDecoder decoder, DecoderOptions options) + public virtual Task> GetImageAsync(ImageDecoder decoder, DecoderOptions options) => throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!"); - public virtual Image GetImage(IImageDecoderSpecialized decoder, T options) + public virtual Image GetImage(SpecializedImageDecoder decoder, T options) where T : class, ISpecializedDecoderOptions, new() => throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!"); - public virtual Task> GetImageAsync(IImageDecoderSpecialized decoder, T options) + public virtual Task> GetImageAsync(SpecializedImageDecoder decoder, T options) where T : class, ISpecializedDecoderOptions, new() => throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!"); /// /// Returns an instance to the test case with the necessary traits. /// + /// The operation to apply to the image before returning. /// A test image. public Image GetImage(Action operationsToApply) { diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 3392d6814..0096a29d8 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -11,7 +11,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; -public class MagickReferenceDecoder : IImageDecoder +public class MagickReferenceDecoder : ImageDecoder { private readonly bool validate; @@ -24,24 +24,23 @@ public class MagickReferenceDecoder : IImageDecoder public static MagickReferenceDecoder Instance { get; } = new(); - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Configuration configuration = options.Configuration; - var bmpReadDefines = new BmpReadDefines + BmpReadDefines bmpReadDefines = new() { IgnoreFileSize = !this.validate }; - var settings = new MagickReadSettings(); + MagickReadSettings settings = new(); settings.FrameCount = (int)options.MaxFrames; settings.SetDefines(bmpReadDefines); - using var magickImageCollection = new MagickImageCollection(stream, settings); - var framesList = new List>(); + using MagickImageCollection magickImageCollection = new(stream, settings); + List> framesList = new(); foreach (IMagickImage magicFrame in magickImageCollection) { - var frame = new ImageFrame(configuration, magicFrame.Width, magicFrame.Height); + ImageFrame frame = new(configuration, magicFrame.Width, magicFrame.Height); framesList.Add(frame); MemoryGroup framePixels = frame.PixelBuffer.FastMemoryGroup; @@ -68,10 +67,10 @@ public class MagickReferenceDecoder : IImageDecoder return new Image(configuration, new ImageMetadata(), framesList); } - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); - public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) @@ -83,9 +82,9 @@ public class MagickReferenceDecoder : IImageDecoder Span destBuffer = m.Span; PixelOperations.Instance.FromRgba32( configuration, - sourcePixels.Slice(0, destBuffer.Length), + sourcePixels[..destBuffer.Length], destBuffer); - sourcePixels = sourcePixels.Slice(destBuffer.Length); + sourcePixels = sourcePixels[destBuffer.Length..]; } } @@ -100,7 +99,7 @@ public class MagickReferenceDecoder : IImageDecoder rgbaBytes, destBuffer, destBuffer.Length); - rgbaBytes = rgbaBytes.Slice(destBuffer.Length * 8); + rgbaBytes = rgbaBytes[(destBuffer.Length * 8)..]; } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index 53d9410c5..6d8104059 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -9,31 +9,30 @@ using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; -public class SystemDrawingReferenceDecoder : IImageDecoder +public class SystemDrawingReferenceDecoder : ImageDecoder { public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder(); - public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { - using var sourceBitmap = new SDBitmap(stream); + using SDBitmap sourceBitmap = new(stream); PixelTypeInfo pixelType = new(SDImage.GetPixelFormatSize(sourceBitmap.PixelFormat)); return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata()); } - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { - using var sourceBitmap = new SDBitmap(stream); + using SDBitmap sourceBitmap = new(stream); if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) { return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(sourceBitmap); } - using var convertedBitmap = new SDBitmap( + using SDBitmap convertedBitmap = new( sourceBitmap.Width, sourceBitmap.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - using (var g = System.Drawing.Graphics.FromImage(convertedBitmap)) + using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(convertedBitmap)) { g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; @@ -46,6 +45,6 @@ public class SystemDrawingReferenceDecoder : IImageDecoder return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(convertedBitmap); } - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 89b43a066..dbbf16ef2 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -20,7 +20,7 @@ public static partial class TestEnvironment internal static Configuration Configuration => ConfigurationLazy.Value; - internal static IImageDecoder GetReferenceDecoder(string filePath) + internal static ImageDecoder GetReferenceDecoder(string filePath) { IImageFormat format = GetImageFormat(filePath); return Configuration.ImageFormatsManager.FindDecoder(format); @@ -42,7 +42,7 @@ public static partial class TestEnvironment private static void ConfigureCodecs( this Configuration cfg, IImageFormat imageFormat, - IImageDecoder decoder, + ImageDecoder decoder, IImageEncoder encoder, IImageFormatDetector detector) { @@ -53,7 +53,7 @@ public static partial class TestEnvironment private static Configuration CreateDefaultConfiguration() { - var cfg = new Configuration( + Configuration cfg = new( new JpegConfigurationModule(), new GifConfigurationModule(), new PbmConfigurationModule(), diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index cd16fe4b2..92314ffb2 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -213,7 +213,7 @@ public static class TestImageExtensions bool grayscale = false, bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, - IImageDecoder decoder = null) + ImageDecoder decoder = null) where TPixel : unmanaged, IPixel { using (Image referenceImage = GetReferenceOutputImage( @@ -306,7 +306,7 @@ public static class TestImageExtensions string extension = "png", bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, - IImageDecoder decoder = null) + ImageDecoder decoder = null) where TPixel : unmanaged, IPixel { string referenceOutputFile = provider.Utility.GetReferenceOutputFileName( @@ -342,7 +342,7 @@ public static class TestImageExtensions var temporaryFrameImages = new List>(); - IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0]); + ImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0]); foreach (string path in frameFiles) { @@ -510,7 +510,7 @@ public static class TestImageExtensions public static Image CompareToOriginal( this Image image, ITestImageProvider provider, - IImageDecoder referenceDecoder = null) + ImageDecoder referenceDecoder = null) where TPixel : unmanaged, IPixel => CompareToOriginal(image, provider, ImageComparer.Tolerant(), referenceDecoder); @@ -518,7 +518,7 @@ public static class TestImageExtensions this Image image, ITestImageProvider provider, ImageComparer comparer, - IImageDecoder referenceDecoder = null, + ImageDecoder referenceDecoder = null, DecoderOptions referenceDecoderOptions = null) where TPixel : unmanaged, IPixel { @@ -545,7 +545,7 @@ public static class TestImageExtensions this Image image, ITestImageProvider provider, ImageComparer comparer, - IImageDecoder referenceDecoder = null) + ImageDecoder referenceDecoder = null) where TPixel : unmanaged, IPixel { string path = TestImageProvider.GetFilePathOrNull(provider); @@ -667,7 +667,7 @@ public static class TestImageExtensions ImageComparer customComparer = null, bool appendPixelTypeToFileName = true, string referenceImageExtension = null, - IImageDecoder referenceDecoder = null) + ImageDecoder referenceDecoder = null) where TPixel : unmanaged, IPixel { string actualOutputFile = provider.Utility.SaveTestOutputFile( diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs index 3a3fcefdb..f150b6e3c 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs @@ -74,7 +74,7 @@ public class ReferenceDecoderBenchmarks this.BenchmarkDecoderImpl(BmpBenchmarkFiles, new SystemDrawingReferenceDecoder(), "System.Drawing Decode Bmp"); } - private void BenchmarkDecoderImpl(IEnumerable testFiles, IImageDecoder decoder, string info, int times = DefaultExecutionCount) + private void BenchmarkDecoderImpl(IEnumerable testFiles, ImageDecoder decoder, string info, int times = DefaultExecutionCount) { var measure = new MeasureFixture(this.Output); measure.Measure( diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs index 36c078dc0..f6b6757c4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs @@ -79,7 +79,7 @@ public class TestEnvironmentTests return; } - IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(fileName); + ImageDecoder decoder = TestEnvironment.GetReferenceDecoder(fileName); Assert.IsType(expectedDecoderType, decoder); } @@ -113,7 +113,7 @@ public class TestEnvironmentTests return; } - IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(fileName); + ImageDecoder decoder = TestEnvironment.GetReferenceDecoder(fileName); Assert.IsType(expectedDecoderType, decoder); } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 5889907f0..2806091dd 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -346,7 +346,7 @@ public class TestImageProviderTests } } - private class TestDecoder : IImageDecoderSpecialized + private class TestDecoder : SpecializedImageDecoder { // Couldn't make xUnit happy without this hackery: private static readonly ConcurrentDictionary InvocationCounts = new(); @@ -363,26 +363,21 @@ public class TestImageProviderTests } } - public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderOptions)new() { GeneralOptions = options }, stream, cancellationToken); + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel - => this.Decode((TestDecoderOptions)new() { GeneralOptions = options }, stream, cancellationToken); - - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderOptions)new() { GeneralOptions = options }, stream, cancellationToken); - - public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + protected internal override Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) { InvocationCounts[this.callerName]++; return new Image(42, 42); } - public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); + protected internal override TestDecoderOptions CreateDefaultSpecializedOptions(DecoderOptions options) + => new() { GeneralOptions = options }; + internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName]; internal void InitCaller(string name) @@ -392,7 +387,7 @@ public class TestImageProviderTests } } - private class TestDecoderWithParameters : IImageDecoderSpecialized + private class TestDecoderWithParameters : SpecializedImageDecoder { private static readonly ConcurrentDictionary InvocationCounts = new(); @@ -408,26 +403,21 @@ public class TestImageProviderTests } } - public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderWithParametersOptions)new() { GeneralOptions = options }, stream, cancellationToken); + protected internal override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel - => this.Decode((TestDecoderWithParametersOptions)new() { GeneralOptions = options }, stream, cancellationToken); - - public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderWithParametersOptions)new() { GeneralOptions = options }, stream, cancellationToken); - - public Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + protected internal override Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) { InvocationCounts[this.callerName]++; return new Image(42, 42); } - public Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) + protected internal override Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); + protected internal override TestDecoderWithParametersOptions CreateDefaultSpecializedOptions(DecoderOptions options) + => new() { GeneralOptions = options }; + internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName]; internal void InitCaller(string name)