diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index 5b0e803f3..0b93cf01f 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Image decoder for generating an image out of a Windows bitmap stream. /// - public class BmpDecoder : ImageDecoder, IImageDecoderSpecialized + public class BmpDecoder : IImageDecoderSpecialized { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -22,29 +22,28 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); /// - public Image DecodeSpecialized(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + Image IImageDecoderSpecialized.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); - Resize(options.GeneralOptions, image); + ImageDecoderUtilities.Resize(options.GeneralOptions, image); return image; } /// - public Image DecodeSpecialized(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(options, stream, cancellationToken); + Image IImageDecoderSpecialized.Decode(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(options, stream, cancellationToken); } } diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index 3729e4208..a737ce74e 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Decoder for generating an image out of a gif encoded stream. /// - public sealed class GifDecoder : ImageDecoder + public sealed class GifDecoder : IImageDecoder { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -30,13 +30,13 @@ namespace SixLabors.ImageSharp.Formats.Gif GifDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - Resize(options, image); + ImageDecoderUtilities.Resize(options, image); return image; } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode(options, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoder)this).Decode(options, stream, cancellationToken); } } diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs index b0363ccf9..949e2133a 100644 --- a/src/ImageSharp/Formats/IImageDecoder.cs +++ b/src/ImageSharp/Formats/IImageDecoder.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats /// /// Encapsulates properties and methods required for decoding an image from a stream. /// - public interface IImageDecoder + public interface IImageDecoder : IImageInfoDetector { /// /// Decodes the image from the specified stream to an of a specific pixel type. diff --git a/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs b/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs index 46ad284da..93a3abb7a 100644 --- a/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs +++ b/src/ImageSharp/Formats/IImageDecoderSpecialized{T}.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.IO; @@ -17,23 +17,29 @@ namespace SixLabors.ImageSharp.Formats /// /// 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 DecodeSpecialized(T options, Stream stream, CancellationToken cancellationToken) + 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 DecodeSpecialized(T options, Stream stream, CancellationToken cancellationToken); + public Image Decode(T options, Stream stream, CancellationToken cancellationToken); } } diff --git a/src/ImageSharp/Formats/ImageDecoder.cs b/src/ImageSharp/Formats/ImageDecoder.cs deleted file mode 100644 index 4863f5b67..000000000 --- a/src/ImageSharp/Formats/ImageDecoder.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System.IO; -using System.Threading; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// The base class for all image decoders. - /// - public abstract class ImageDecoder : IImageInfoDetector, IImageDecoder - { - /// - public abstract IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken); - - /// - public abstract Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel; - - /// - public abstract Image Decode(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 = KnownResamplers.Box, - 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; - } - } -} diff --git a/src/ImageSharp/Formats/ImageDecoderExtensions.cs b/src/ImageSharp/Formats/ImageDecoderExtensions.cs new file mode 100644 index 000000000..0e3bcdf9a --- /dev/null +++ b/src/ImageSharp/Formats/ImageDecoderExtensions.cs @@ -0,0 +1,182 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Formats +{ + /// + /// Extensions methods for and . + /// + public static class ImageDecoderExtensions + { + /// + /// Reads the raw image information from the specified stream. + /// + /// The decoder. + /// The general decoder options. + /// The containing image data. + /// The object. + /// Thrown if the encoded image contains errors. + public static IImageInfo Identify(this IImageDecoder decoder, DecoderOptions options, Stream stream) + => Image.WithSeekableStream( + options, + stream, + s => decoder.Identify(options, s, default)); + + /// + /// Reads the raw image information from the specified stream. + /// + /// The decoder. + /// The general decoder options. + /// The containing image data. + /// 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) + => Image.WithSeekableStreamAsync( + options, + stream, + (s, ct) => decoder.Identify(options, s, ct), + cancellationToken); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The pixel format. + /// The decoder. + /// The general decoder options. + /// The containing image data. + /// The . + /// Thrown if the encoded image contains errors. + public static Image Decode(this IImageDecoder decoder, DecoderOptions options, Stream stream) + where TPixel : unmanaged, IPixel + => Image.WithSeekableStream( + options, + stream, + s => decoder.Decode(options, s, default)); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The decoder. + /// The general decoder options. + /// The containing image data. + /// The . + /// Thrown if the encoded image contains errors. + public static Image Decode(this IImageDecoder decoder, DecoderOptions options, Stream stream) + => Image.WithSeekableStream( + options, + stream, + s => decoder.Decode(options, s, default)); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The pixel format. + /// The decoder. + /// The general decoder options. + /// The containing image data. + /// 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) + where TPixel : unmanaged, IPixel + => Image.WithSeekableStreamAsync( + options, + stream, + (s, ct) => decoder.Decode(options, s, ct), + cancellationToken); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The decoder. + /// The general decoder options. + /// The containing image data. + /// 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) + => Image.WithSeekableStreamAsync( + options, + stream, + (s, ct) => decoder.Decode(options, s, ct), + cancellationToken); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The type of specialized options. + /// The pixel format. + /// The decoder. + /// The specialized decoder options. + /// The containing image data. + /// The . + /// Thrown if the encoded image contains errors. + public static Image Decode(this IImageDecoderSpecialized decoder, T options, Stream stream) + where T : ISpecializedDecoderOptions + where TPixel : unmanaged, IPixel + => Image.WithSeekableStream( + options.GeneralOptions, + stream, + s => decoder.Decode(options, s, default)); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The type of specialized options. + /// The decoder. + /// The specialized decoder options. + /// The containing image data. + /// The . + /// Thrown if the encoded image contains errors. + public static Image Decode(this IImageDecoderSpecialized decoder, T options, Stream stream) + where T : ISpecializedDecoderOptions + => Image.WithSeekableStream( + options.GeneralOptions, + stream, + s => decoder.Decode(options, s, default)); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The type of specialized options. + /// The pixel format. + /// The decoder. + /// The specialized decoder options. + /// The containing image data. + /// 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) + where T : ISpecializedDecoderOptions + where TPixel : unmanaged, IPixel + => Image.WithSeekableStreamAsync( + options.GeneralOptions, + stream, + (s, ct) => decoder.Decode(options, s, ct), + cancellationToken); + + /// + /// Decodes the image from the specified stream to an of a specific pixel type. + /// + /// The type of specialized options. + /// The decoder. + /// The specialized decoder options. + /// The containing image data. + /// 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) + where T : ISpecializedDecoderOptions + => Image.WithSeekableStreamAsync( + options.GeneralOptions, + stream, + (s, ct) => decoder.Decode(options, s, ct), + cancellationToken); + } +} diff --git a/src/ImageSharp/Formats/ImageDecoderSpecializedExtensions.cs b/src/ImageSharp/Formats/ImageDecoderSpecializedExtensions.cs deleted file mode 100644 index d23f088aa..000000000 --- a/src/ImageSharp/Formats/ImageDecoderSpecializedExtensions.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// Extensions methods for . - /// - public static class ImageDecoderSpecializedExtensions - { - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// The type of specialized options. - /// The pixel format. - /// The decoder. - /// The specialized decoder options. - /// The containing image data. - /// The . - /// Thrown if the encoded image contains errors. - public static Image DecodeSpecialized(this IImageDecoderSpecialized decoder, T options, Stream stream) - where T : ISpecializedDecoderOptions - where TPixel : unmanaged, IPixel - => decoder.DecodeSpecialized(options, stream, default); - - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// The type of specialized options. - /// The decoder. - /// The specialized decoder options. - /// The containing image data. - /// The . - /// Thrown if the encoded image contains errors. - public static Image DecodeSpecialized(this IImageDecoderSpecialized decoder, T options, Stream stream) - where T : ISpecializedDecoderOptions - => decoder.DecodeSpecialized(options, stream, default); - - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// The type of specialized options. - /// The pixel format. - /// The decoder. - /// The specialized decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// A representing the asynchronous operation. - /// Thrown if the encoded image contains errors. - public static Task> DecodeSpecializedAsync(this IImageDecoderSpecialized decoder, T options, Stream stream, CancellationToken cancellationToken = default) - where T : ISpecializedDecoderOptions - where TPixel : unmanaged, IPixel - => Image.WithSeekableStreamAsync( - options.GeneralOptions, - stream, - (s, ct) => decoder.DecodeSpecialized(options, s, ct), - cancellationToken); - - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// The type of specialized options. - /// The decoder. - /// The specialized decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// A representing the asynchronous operation. - /// Thrown if the encoded image contains errors. - public static Task DecodeSpecializedAsync(this IImageDecoderSpecialized decoder, T options, Stream stream, CancellationToken cancellationToken = default) - where T : ISpecializedDecoderOptions - => Image.WithSeekableStreamAsync( - options.GeneralOptions, - stream, - (s, ct) => decoder.DecodeSpecialized(options, s, ct), - cancellationToken); - } -} diff --git a/src/ImageSharp/Formats/ImageDecoderUtilities.cs b/src/ImageSharp/Formats/ImageDecoderUtilities.cs index b6cefd2c8..2c0482034 100644 --- a/src/ImageSharp/Formats/ImageDecoderUtilities.cs +++ b/src/ImageSharp/Formats/ImageDecoderUtilities.cs @@ -7,12 +7,55 @@ using System.Threading; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Formats { + /// + /// Utility methods for . + /// internal static class ImageDecoderUtilities { - public static IImageInfo Identify( + /// + /// 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 = KnownResamplers.Box, + 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, Stream stream, @@ -30,7 +73,7 @@ namespace SixLabors.ImageSharp.Formats } } - public static Image Decode( + internal static Image Decode( this IImageDecoderInternals decoder, Configuration configuration, Stream stream, @@ -38,7 +81,7 @@ namespace SixLabors.ImageSharp.Formats where TPixel : unmanaged, IPixel => decoder.Decode(configuration, stream, DefaultLargeImageExceptionFactory, cancellationToken); - public static Image Decode( + internal static Image Decode( this IImageDecoderInternals decoder, Configuration configuration, Stream stream, diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index a655acbce..09b034c79 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Decoder for generating an image out of a jpeg encoded stream. /// - public sealed class JpegDecoder : ImageDecoder, IImageDecoderSpecialized + public sealed class JpegDecoder : IImageDecoderSpecialized { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(stream, nameof(stream)); @@ -22,16 +22,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); /// - public Image DecodeSpecialized(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + Image IImageDecoderSpecialized.Decode(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -41,14 +40,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (options.ResizeMode != JpegDecoderResizeMode.IdctOnly) { - Resize(options.GeneralOptions, image); + ImageDecoderUtilities.Resize(options.GeneralOptions, image); } return image; } /// - public Image DecodeSpecialized(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(options, stream, cancellationToken); + Image IImageDecoderSpecialized.Decode(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(options, stream, cancellationToken); } } diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs index 1127f8e09..394da0a60 100644 --- a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs +++ b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs @@ -26,10 +26,10 @@ namespace SixLabors.ImageSharp.Formats.Pbm /// /// The specification of these images is found at . /// - public sealed class PbmDecoder : ImageDecoder + public sealed class PbmDecoder : IImageDecoder { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -46,13 +46,13 @@ namespace SixLabors.ImageSharp.Formats.Pbm PbmDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - Resize(options, image); + ImageDecoderUtilities.Resize(options, image); return image; } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode(options, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoder)this).Decode(options, stream, cancellationToken); } } diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs index 9f23982d0..2aa563435 100644 --- a/src/ImageSharp/Formats/Png/PngDecoder.cs +++ b/src/ImageSharp/Formats/Png/PngDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Decoder for generating an image out of a png encoded stream. /// - public sealed class PngDecoder : ImageDecoder + public sealed class PngDecoder : IImageDecoder { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Png } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -30,13 +30,13 @@ namespace SixLabors.ImageSharp.Formats.Png PngDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - Resize(options, image); + ImageDecoderUtilities.Resize(options, image); return image; } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -48,47 +48,49 @@ namespace SixLabors.ImageSharp.Formats.Png PngMetadata meta = info.Metadata.GetPngMetadata(); 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 - ? this.Decode(options, stream, cancellationToken) - : this.Decode(options, stream, cancellationToken); + ? imageDecoder.Decode(options, stream, cancellationToken) + : imageDecoder.Decode(options, stream, cancellationToken); } return !meta.HasTransparency - ? this.Decode(options, stream, cancellationToken) - : this.Decode(options, stream, cancellationToken); + ? imageDecoder.Decode(options, stream, cancellationToken) + : imageDecoder.Decode(options, stream, cancellationToken); case PngColorType.Rgb: if (bits == PngBitDepth.Bit16) { return !meta.HasTransparency - ? this.Decode(options, stream, cancellationToken) - : this.Decode(options, stream, cancellationToken); + ? imageDecoder.Decode(options, stream, cancellationToken) + : imageDecoder.Decode(options, stream, cancellationToken); } return !meta.HasTransparency - ? this.Decode(options, stream, cancellationToken) - : this.Decode(options, stream, cancellationToken); + ? imageDecoder.Decode(options, stream, cancellationToken) + : imageDecoder.Decode(options, stream, cancellationToken); case PngColorType.Palette: - return this.Decode(options, stream, cancellationToken); + return imageDecoder.Decode(options, stream, cancellationToken); case PngColorType.GrayscaleWithAlpha: return (bits == PngBitDepth.Bit16) - ? this.Decode(options, stream, cancellationToken) - : this.Decode(options, stream, cancellationToken); + ? imageDecoder.Decode(options, stream, cancellationToken) + : imageDecoder.Decode(options, stream, cancellationToken); case PngColorType.RgbWithAlpha: return (bits == PngBitDepth.Bit16) - ? this.Decode(options, stream, cancellationToken) - : this.Decode(options, stream, cancellationToken); + ? imageDecoder.Decode(options, stream, cancellationToken) + : imageDecoder.Decode(options, stream, cancellationToken); default: - return this.Decode(options, stream, cancellationToken); + return imageDecoder.Decode(options, stream, cancellationToken); } } } diff --git a/src/ImageSharp/Formats/Tga/TgaDecoder.cs b/src/ImageSharp/Formats/Tga/TgaDecoder.cs index 2ad845adb..ac99271cb 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoder.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Tga /// /// Image decoder for Truevision TGA images. /// - public sealed class TgaDecoder : ImageDecoder + public sealed class TgaDecoder : IImageDecoder { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Tga } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -30,13 +30,13 @@ namespace SixLabors.ImageSharp.Formats.Tga TgaDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - Resize(options, image); + ImageDecoderUtilities.Resize(options, image); return image; } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode(options, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoder)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 d2461bfa2..db93406a0 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors /// protected override void Decompress(BufferedReadStream stream, int byteCount, int stripHeight, Span buffer, CancellationToken cancellationToken) { - using Image image = new WebpDecoder().Decode(this.options, stream, cancellationToken); + using Image image = ((IImageDecoder)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 012adc586..dfbee19a0 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// Image decoder for generating an image out of a TIFF stream. /// - public class TiffDecoder : ImageDecoder + public class TiffDecoder : IImageDecoder { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -30,13 +30,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff TiffDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - Resize(options, image); + ImageDecoderUtilities.Resize(options, image); return image; } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode(options, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoder)this).Decode(options, stream, cancellationToken); } } diff --git a/src/ImageSharp/Formats/Webp/WebpDecoder.cs b/src/ImageSharp/Formats/Webp/WebpDecoder.cs index b2dbbcba9..9b05de5ea 100644 --- a/src/ImageSharp/Formats/Webp/WebpDecoder.cs +++ b/src/ImageSharp/Formats/Webp/WebpDecoder.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Webp /// /// Image decoder for generating an image out of a webp stream. /// - public sealed class WebpDecoder : ImageDecoder + public sealed class WebpDecoder : IImageDecoder { /// - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Formats.Webp } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); @@ -31,13 +31,13 @@ namespace SixLabors.ImageSharp.Formats.Webp using WebpDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); - Resize(options, image); + ImageDecoderUtilities.Resize(options, image); return image; } /// - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode(options, stream, cancellationToken); + Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoder)this).Decode(options, stream, cancellationToken); } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs index 5df226770..1fee65fa0 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg private void GenericBechmark() { this.preloadedImageStream.Position = 0; - using Image img = this.decoder.Decode(DecoderOptions.Default, this.preloadedImageStream, default); + using Image img = this.decoder.Decode(DecoderOptions.Default, this.preloadedImageStream); } [GlobalSetup(Target = nameof(JpegBaselineInterleaved444))] diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs index d1e1f0e77..a9cbb418a 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg public IImageInfo Identify() { using var memoryStream = new MemoryStream(this.jpegBytes); - var decoder = new JpegDecoder(); + IImageDecoder decoder = new JpegDecoder(); return decoder.Identify(DecoderOptions.Default, memoryStream, default); } } diff --git a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs index bee55600f..81884ae3d 100644 --- a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs +++ b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs @@ -215,7 +215,7 @@ namespace SixLabors.ImageSharp.Benchmarks.LoadResizeSave }; var decoder = new JpegDecoder(); - using ImageSharpImage image = decoder.Decode(options, inputStream, default); + using ImageSharpImage image = decoder.Decode(options, inputStream); this.LogImageProcessed(image.Width, image.Height); // Reduce the size of the file diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 8a5892e02..e303cb516 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -497,7 +497,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new BmpDecoder(); - using Image image = decoder.Decode(DecoderOptions.Default, stream, default); + using Image image = decoder.Decode(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 7c0447a98..cf6abe23c 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif fixed (byte* data = testFile.Bytes.AsSpan(0, length)) { using var stream = new UnmanagedMemoryStream(data, length); - using Image image = GifDecoder.Decode(DecoderOptions.Default, stream, default); + using Image image = GifDecoder.Decode(DecoderOptions.Default, stream); Assert.Equal((200, 200), (image.Width, image.Height)); } } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs index 23de14b63..56b991a02 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs @@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif input.Save(memoryStream, new GifEncoder()); memoryStream.Position = 0; - using Image image = decoder.Decode(DecoderOptions.Default, memoryStream, default); + using Image image = decoder.Decode(DecoderOptions.Default, memoryStream); GifMetadata metadata = image.Metadata.GetGifMetadata(); Assert.Equal(2, metadata.Comments.Count); Assert.Equal(new string('c', 349), metadata.Comments[0]); @@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new GifDecoder(); - IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default); + IImageInfo image = decoder.Identify(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new GifDecoder(); - using Image image = decoder.Decode(DecoderOptions.Default, stream, default); + using Image image = decoder.Decode(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new GifDecoder(); - IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default); + IImageInfo image = decoder.Identify(DecoderOptions.Default, stream); GifMetadata meta = image.Metadata.GetGifMetadata(); Assert.Equal(repeatCount, meta.RepeatCount); } @@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new GifDecoder(); - using Image image = decoder.Decode(DecoderOptions.Default, stream, default); + using Image image = decoder.Decode(DecoderOptions.Default, stream); GifMetadata meta = image.Metadata.GetGifMetadata(); Assert.Equal(repeatCount, meta.RepeatCount); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs index 9046ca14d..d9b07f9b5 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new JpegDecoder(); - using Image image = decoder.Decode(DecoderOptions.Default, stream, default); + using Image image = decoder.Decode(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new JpegDecoder(); - IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default); + IImageInfo image = decoder.Identify(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); @@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new JpegDecoder(); - IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default); + IImageInfo image = decoder.Identify(DecoderOptions.Default, stream); JpegMetadata meta = image.Metadata.GetJpegMetadata(); Assert.Equal(quality, meta.Quality); } @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); - using Image image = JpegDecoder.Decode(DecoderOptions.Default, stream, default); + using Image image = JpegDecoder.Decode(DecoderOptions.Default, stream); JpegMetadata meta = image.Metadata.GetJpegMetadata(); Assert.Equal(quality, meta.Quality); } @@ -139,7 +139,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); - IImageInfo image = JpegDecoder.Identify(DecoderOptions.Default, stream, default); + IImageInfo image = JpegDecoder.Identify(DecoderOptions.Default, stream); JpegMetadata meta = image.Metadata.GetJpegMetadata(); Assert.Equal(expectedColorType, meta.ColorType); } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs index 16627dd34..9de9f32ec 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var decoder = new PngDecoder(); ImageFormatException exception = - Assert.Throws(() => decoder.Decode(DecoderOptions.Default, memStream, default)); + Assert.Throws(() => decoder.Decode(DecoderOptions.Default, memStream)); Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message); } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index a35f8037c..5e41530cd 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -289,7 +289,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var decoder = new PngDecoder(); - Image image = decoder.Decode(DecoderOptions.Default, stream, default); + Image image = decoder.Decode(DecoderOptions.Default, stream); PngMetadata metadata = image.Metadata.GetPngMetadata(); Assert.Equal(pngColorType, metadata.ColorType); @@ -597,7 +597,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png // occurs within the encoder itself leaving the input image unaffected. // This means we are benefiting from testing our decoder also. using FileStream fileStream = File.OpenRead(actualOutputFile); - using Image imageSharpImage = new PngDecoder().Decode(DecoderOptions.Default, fileStream, default); + using Image imageSharpImage = new PngDecoder().Decode(DecoderOptions.Default, fileStream); fileStream.Position = 0; diff --git a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs index fe74c0b8c..74217c982 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png input.Save(memoryStream, new PngEncoder()); memoryStream.Position = 0; - using Image image = decoder.Decode(DecoderOptions.Default, memoryStream, default); + using Image image = decoder.Decode(DecoderOptions.Default, memoryStream); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); VerifyTextDataIsPresent(meta); } @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png }); memoryStream.Position = 0; - using Image image = decoder.Decode(DecoderOptions.Default, memoryStream, default); + using Image image = decoder.Decode(DecoderOptions.Default, memoryStream); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); Assert.Contains(meta.TextData, m => m.Equals(expectedText)); Assert.Contains(meta.TextData, m => m.Equals(expectedTextNoneLatin)); @@ -195,7 +195,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new PngDecoder(); - using Image image = decoder.Decode(DecoderOptions.Default, stream, default); + using Image image = decoder.Decode(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); @@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var testFile = TestFile.Create(imagePath); using var stream = new MemoryStream(testFile.Bytes, false); var decoder = new PngDecoder(); - IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default); + IImageInfo image = decoder.Identify(DecoderOptions.Default, stream); ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs index 934b57b03..58843227d 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs @@ -26,76 +26,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png // image.Save(provider.Utility.GetTestOutputFileName("bmp")); image.Save(ms, new PngEncoder()); ms.Position = 0; - using Image img2 = new PngDecoder().Decode(DecoderOptions.Default, ms, default); + using Image img2 = new PngDecoder().Decode(DecoderOptions.Default, ms); ImageComparer.Tolerant().VerifySimilarity(image, img2); // img2.Save(provider.Utility.GetTestOutputFileName("bmp", "_loaded"), new BmpEncoder()); } - /* JJS: Disabled for now as the decoder now correctly decodes the full pixel components if the - paletted image has alpha of 0 - [Theory] - [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] - public void CanSaveIndexedPng(TestImageProvider provider) - where TPixel : unmanaged, IPixel - { - // does saving a file then reopening mean both files are identical??? - using (Image image = provider.GetImage()) - using (MemoryStream ms = new MemoryStream()) - { - // image.Save(provider.Utility.GetTestOutputFileName("bmp")); - image.Save(ms, new PngEncoder() { PaletteSize = 256 }); - ms.Position = 0; - using (Image img2 = Image.Load(ms, new PngDecoder())) - { - ImageComparer.VerifySimilarity(image, img2, 0.03f); - } - } - }*/ - - /* JJS: Commented out for now since the test does not take into lossy nature of indexing. - [Theory] - [WithTestPatternImages(100, 100, PixelTypes.Color)] - public void CanSaveIndexedPngTwice(TestImageProvider provider) - where TPixel : unmanaged, IPixel - { - // does saving a file then reopening mean both files are identical??? - using (Image source = provider.GetImage()) - using (MemoryStream ms = new MemoryStream()) - { - source.Metadata.Quality = 256; - source.Save(ms, new PngEncoder(), new PngEncoderOptions { - Threshold = 200 - }); - ms.Position = 0; - using (Image img1 = Image.Load(ms, new PngDecoder())) - { - using (MemoryStream ms2 = new MemoryStream()) - { - img1.Save(ms2, new PngEncoder(), new PngEncoderOptions - { - Threshold = 200 - }); - ms2.Position = 0; - using (Image img2 = Image.Load(ms2, new PngDecoder())) - { - using (PixelAccessor pixels1 = img1.Lock()) - using (PixelAccessor pixels2 = img2.Lock()) - { - for (int y = 0; y < img1.Height; y++) - { - for (int x = 0; x < img1.Width; x++) - { - Assert.Equal(pixels1[x, y], pixels2[x, y]); - } - } - } - } - } - } - } - }*/ - [Theory] [WithTestPatternImages(300, 300, PixelTypes.Rgba32)] public void Resize(TestImageProvider provider) @@ -111,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png // image.Save(provider.Utility.GetTestOutputFileName("png", "resize")); image.Save(ms, new PngEncoder()); ms.Position = 0; - using Image img2 = new PngDecoder().Decode(DecoderOptions.Default, ms, default); + using Image img2 = new PngDecoder().Decode(DecoderOptions.Default, ms); ImageComparer.Tolerant().VerifySimilarity(image, img2); } } diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 96fcb6afd..9ec7d8f0b 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.Tests public TestHeader(TestFormat testFormat) => this.testFormat = testFormat; } - public class TestDecoder : ImageDecoder, IImageDecoderSpecialized + public class TestDecoder : IImageDecoderSpecialized { private readonly TestFormat testFormat; @@ -208,16 +208,17 @@ namespace SixLabors.ImageSharp.Tests public bool IsSupportedFileFormat(Span header) => this.testFormat.IsSupportedFileFormat(header); - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = 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 override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken); - public Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { Configuration configuration = options.GeneralOptions.Configuration; @@ -235,8 +236,8 @@ namespace SixLabors.ImageSharp.Tests return this.testFormat.Sample(); } - public Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(options, stream, cancellationToken); + public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); } public class TestDecoderOptions : ISpecializedDecoderOptions diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index 6cc96dede..733e3a31f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.Tests // TODO: Check Path here. Why combined? string path = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.FilePath); using Stream stream = System.IO.File.OpenRead(path); - return Task.FromResult(decoder.DecodeSpecialized(options, stream, default)); + return Task.FromResult(decoder.Decode(options, stream, default)); } public override void Deserialize(IXunitSerializationInfo info) @@ -286,7 +286,7 @@ namespace SixLabors.ImageSharp.Tests var testFile = TestFile.Create(this.FilePath); using Stream stream = new MemoryStream(testFile.Bytes); - return decoder.DecodeSpecialized(options, stream, default); + return decoder.Decode(options, stream, default); } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 92b7aeac9..1f1d7febe 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -15,7 +15,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { - public class MagickReferenceDecoder : ImageDecoder + public class MagickReferenceDecoder : IImageDecoder { private readonly bool validate; @@ -28,7 +28,8 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs public static MagickReferenceDecoder Instance { get; } = new(); - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { Configuration configuration = options.Configuration; var bmpReadDefines = new BmpReadDefines @@ -70,10 +71,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs return new Image(configuration, new ImageMetadata(), framesList); } - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index ddf09ebdd..e14866f81 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -11,18 +11,19 @@ using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { - public class SystemDrawingReferenceDecoder : ImageDecoder + public class SystemDrawingReferenceDecoder : IImageDecoder { public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder(); - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { using var sourceBitmap = new SDBitmap(stream); PixelTypeInfo pixelType = new(SDImage.GetPixelFormatSize(sourceBitmap.PixelFormat)); return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata()); } - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + where TPixel : unmanaged, IPixel { using var sourceBitmap = new SDBitmap(stream); if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) @@ -47,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(convertedBitmap); } - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) => this.Decode(options, stream, cancellationToken); } } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 9255d5d9f..46e8b34bc 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -351,7 +351,7 @@ namespace SixLabors.ImageSharp.Tests } } - private class TestDecoder : ImageDecoder, IImageDecoderSpecialized + private class TestDecoder : IImageDecoderSpecialized { // Couldn't make xUnit happy without this hackery: private static readonly ConcurrentDictionary InvocationCounts = new(); @@ -368,24 +368,25 @@ namespace SixLabors.ImageSharp.Tests } } - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode((TestDecoderOptions)(new() { GeneralOptions = options }), stream, cancellationToken); - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = 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 override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode((TestDecoderOptions)(new() { GeneralOptions = options }), stream, cancellationToken); - public Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { InvocationCounts[this.callerName]++; return new Image(42, 42); } - public Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(options, stream, cancellationToken); + public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName]; @@ -396,7 +397,7 @@ namespace SixLabors.ImageSharp.Tests } } - private class TestDecoderWithParameters : ImageDecoder, IImageDecoderSpecialized + private class TestDecoderWithParameters : IImageDecoderSpecialized { private static readonly ConcurrentDictionary InvocationCounts = new(); @@ -412,24 +413,25 @@ namespace SixLabors.ImageSharp.Tests } } - public override IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode((TestDecoderWithParametersOptions)(new() { GeneralOptions = options }), stream, cancellationToken); - public override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = 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 override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(new() { GeneralOptions = options }, stream, cancellationToken); + public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode((TestDecoderWithParametersOptions)(new() { GeneralOptions = options }), stream, cancellationToken); - public Image DecodeSpecialized(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) + public Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { InvocationCounts[this.callerName]++; return new Image(42, 42); } - public Image DecodeSpecialized(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) - => this.DecodeSpecialized(options, stream, cancellationToken); + public Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) + => this.Decode(options, stream, cancellationToken); internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName];