diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index f7fb0948fc..10267c8ef7 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -21,8 +21,8 @@ public static class AdvancedImageExtensions
/// The target file path to save the image to.
/// The file path is null.
/// No encoder available for provided path.
- /// The matching .
- public static ImageEncoder DetectEncoder(this Image source, string filePath)
+ /// The matching .
+ public static IImageEncoder DetectEncoder(this Image source, string filePath)
{
Guard.NotNull(filePath, nameof(filePath));
@@ -40,13 +40,13 @@ public static class AdvancedImageExtensions
throw new NotSupportedException(sb.ToString());
}
- ImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
+ IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null)
{
StringBuilder sb = new();
sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
- foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
+ foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
}
diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs
index 00f7b1c3b5..a0f70e640c 100644
--- a/src/ImageSharp/Advanced/AotCompilerTools.cs
+++ b/src/ImageSharp/Advanced/AotCompilerTools.cs
@@ -230,7 +230,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]
@@ -266,14 +266,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 encoder.
[Preserve]
private static void AotCompileImageEncoder()
where TPixel : unmanaged, IPixel
- where TEncoder : ImageEncoder
+ where TEncoder : IImageEncoder
{
default(TEncoder).Encode(default, default);
default(TEncoder).EncodeAsync(default, default, default);
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
index 9e20da170a..156e2f9610 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
@@ -24,16 +24,9 @@ public sealed class BmpEncoder : QuantizingImageEncoder
public bool SupportTransparency { get; init; }
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
BmpEncoderCore encoder = new(this, image.GetMemoryAllocator());
- encoder.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- BmpEncoderCore encoder = new(this, image.GetMemoryAllocator());
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifEncoder.cs b/src/ImageSharp/Formats/Gif/GifEncoder.cs
index 351554eb07..386b1bd1c3 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoder.cs
@@ -16,16 +16,9 @@ public sealed class GifEncoder : QuantizingImageEncoder
public GifColorTableMode? ColorTableMode { get; init; }
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
GifEncoderCore encoder = new(image.GetConfiguration(), this);
- encoder.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- GifEncoderCore encoder = new(image.GetConfiguration(), this);
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/ImageEncoder.cs b/src/ImageSharp/Formats/IImageEncoder.cs
similarity index 58%
rename from src/ImageSharp/Formats/ImageEncoder.cs
rename to src/ImageSharp/Formats/IImageEncoder.cs
index c887e7b0b2..42d04a54dc 100644
--- a/src/ImageSharp/Formats/ImageEncoder.cs
+++ b/src/ImageSharp/Formats/IImageEncoder.cs
@@ -2,15 +2,13 @@
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Formats;
///
-/// The base class for all image encoders.
+/// Defines the contract for all image encoders.
///
-public abstract class ImageEncoder
+public interface IImageEncoder
{
///
/// Gets a value indicating whether to ignore decoded metadata when encoding.
@@ -23,7 +21,7 @@ public abstract class ImageEncoder
/// The pixel format.
/// The to encode from.
/// The to encode the image data to.
- public abstract void Encode(Image image, Stream stream)
+ public void Encode(Image image, Stream stream)
where TPixel : unmanaged, IPixel;
///
@@ -34,22 +32,6 @@ public abstract class ImageEncoder
/// The to encode the image data to.
/// The token to monitor for cancellation requests.
/// A representing the asynchronous operation.
- public abstract Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
+ public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel;
}
-
-///
-/// The base class for all image encoders that allow color palette generation via quantization.
-///
-public abstract class QuantizingImageEncoder : ImageEncoder
-{
- ///
- /// Gets the quantizer used to generate the color palette.
- ///
- public IQuantizer Quantizer { get; init; } = KnownQuantizers.Octree;
-
- ///
- /// Gets the used for quantization when building color palettes.
- ///
- public IPixelSamplingStrategy PixelSamplingStrategy { get; init; } = new DefaultPixelSamplingStrategy();
-}
diff --git a/src/ImageSharp/Formats/IImageEncoderInternals.cs b/src/ImageSharp/Formats/IImageEncoderInternals.cs
index ca9c474e13..131949c968 100644
--- a/src/ImageSharp/Formats/IImageEncoderInternals.cs
+++ b/src/ImageSharp/Formats/IImageEncoderInternals.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.PixelFormats;
@@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats;
///
-/// Abstraction for shared internals for ***DecoderCore implementations to be used with .
+/// Abstraction for shared internals for ***DecoderCore implementations.
///
internal interface IImageEncoderInternals
{
diff --git a/src/ImageSharp/Formats/ImageDecoder.cs b/src/ImageSharp/Formats/ImageDecoder.cs
index 42d476e925..b9bcd97e9c 100644
--- a/src/ImageSharp/Formats/ImageDecoder.cs
+++ b/src/ImageSharp/Formats/ImageDecoder.cs
@@ -13,6 +13,53 @@ namespace SixLabors.ImageSharp.Formats;
///
public abstract class ImageDecoder : IImageDecoder
{
+ ///
+ public Image Decode(DecoderOptions options, Stream stream)
+ where TPixel : unmanaged, IPixel
+ => WithSeekableStream(
+ options,
+ stream,
+ s => this.Decode(options, s, default));
+
+ ///
+ public Image Decode(DecoderOptions options, Stream stream)
+ => WithSeekableStream(
+ options,
+ stream,
+ s => this.Decode(options, s, default));
+
+ ///
+ public Task> DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel
+ => WithSeekableStreamAsync(
+ options,
+ stream,
+ (s, ct) => this.Decode(options, s, ct),
+ cancellationToken);
+
+ ///
+ public Task DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ => WithSeekableStreamAsync(
+ options,
+ stream,
+ (s, ct) => this.Decode(options, s, ct),
+ cancellationToken);
+
+ ///
+ public IImageInfo Identify(DecoderOptions options, Stream stream)
+ => WithSeekableStream(
+ options,
+ stream,
+ s => this.Identify(options, s, default));
+
+ ///
+ public Task IdentifyAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ => WithSeekableStreamAsync(
+ options,
+ stream,
+ (s, ct) => this.Identify(options, s, ct),
+ cancellationToken);
+
///
/// Decodes the image from the specified stream to an of a specific pixel type.
///
@@ -93,53 +140,6 @@ public abstract class ImageDecoder : IImageDecoder
return currentSize.Width != targetSize.Width && currentSize.Height != targetSize.Height;
}
- ///
- public Image Decode(DecoderOptions options, Stream stream)
- where TPixel : unmanaged, IPixel
- => WithSeekableStream(
- options,
- stream,
- s => this.Decode(options, s, default));
-
- ///
- public Image Decode(DecoderOptions options, Stream stream)
- => WithSeekableStream(
- options,
- stream,
- s => this.Decode(options, s, default));
-
- ///
- public Task> DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
- where TPixel : unmanaged, IPixel
- => WithSeekableStreamAsync(
- options,
- stream,
- (s, ct) => this.Decode(options, s, ct),
- cancellationToken);
-
- ///
- public Task DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
- => WithSeekableStreamAsync(
- options,
- stream,
- (s, ct) => this.Decode(options, s, ct),
- cancellationToken);
-
- ///
- public IImageInfo Identify(DecoderOptions options, Stream stream)
- => WithSeekableStream(
- options,
- stream,
- s => this.Identify(options, s, default));
-
- ///
- public Task IdentifyAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
- => WithSeekableStreamAsync(
- options,
- stream,
- (s, ct) => this.Identify(options, s, ct),
- cancellationToken);
-
internal static T WithSeekableStream(
DecoderOptions options,
Stream stream,
@@ -213,7 +213,7 @@ public abstract class ImageDecoder : IImageDecoder
// code below to copy the stream to an in-memory buffer before invoking the action.
// TODO: Avoid the existing double copy caused by calling IdentifyAsync followed by DecodeAsync.
- // Perhaps we can make overloads accepting the chunked memorystream?
+ // Perhaps we can make overloads accepting the chunked memorystream? Or maybe AOT is good with pattern matching against types?
Configuration configuration = options.Configuration;
using ChunkedMemoryStream memoryStream = new(configuration.MemoryAllocator);
await stream.CopyToAsync(memoryStream, configuration.StreamProcessingBufferSize, cancellationToken).ConfigureAwait(false);
diff --git a/src/ImageSharp/Formats/ImageEncoderUtilities.cs b/src/ImageSharp/Formats/ImageEncoderUtilities.cs
deleted file mode 100644
index 665431c952..0000000000
--- a/src/ImageSharp/Formats/ImageEncoderUtilities.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp.Formats;
-
-internal static class ImageEncoderUtilities
-{
- public static async Task EncodeAsync(
- this IImageEncoderInternals encoder,
- Image image,
- Stream stream,
- CancellationToken cancellationToken)
- where TPixel : unmanaged, IPixel
- {
- Configuration configuration = image.GetConfiguration();
- if (stream.CanSeek)
- {
- await DoEncodeAsync(stream).ConfigureAwait(false);
- }
- else
- {
- using MemoryStream ms = new();
- await DoEncodeAsync(ms);
- ms.Position = 0;
- await ms.CopyToAsync(stream, configuration.StreamProcessingBufferSize, cancellationToken)
- .ConfigureAwait(false);
- }
-
- Task DoEncodeAsync(Stream innerStream)
- {
- try
- {
- encoder.Encode(image, innerStream, cancellationToken);
- return Task.CompletedTask;
- }
- catch (OperationCanceledException)
- {
- return Task.FromCanceled(cancellationToken);
- }
- catch (Exception ex)
- {
- return Task.FromException(ex);
- }
- }
- }
-
- public static void Encode(
- this IImageEncoderInternals encoder,
- Image image,
- Stream stream)
- where TPixel : unmanaged, IPixel
- => encoder.Encode(image, stream, default);
-}
diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs
index 23229703c0..b13f3e8d8d 100644
--- a/src/ImageSharp/Formats/ImageFormatManager.cs
+++ b/src/ImageSharp/Formats/ImageFormatManager.cs
@@ -17,9 +17,9 @@ public class ImageFormatManager
private static readonly object HashLock = new();
///
- /// The list of supported keyed to mime types.
+ /// The list of supported keyed to mime types.
///
- private readonly ConcurrentDictionary mimeTypeEncoders = new();
+ private readonly ConcurrentDictionary mimeTypeEncoders = new();
///
/// The list of supported keyed to mime types.
@@ -64,9 +64,9 @@ public class ImageFormatManager
internal IEnumerable> ImageDecoders => this.mimeTypeDecoders;
///
- /// Gets the currently registered s.
+ /// Gets the currently registered s.
///
- internal IEnumerable> ImageEncoders => this.mimeTypeEncoders;
+ internal IEnumerable> ImageEncoders => this.mimeTypeEncoders;
///
/// Registers a new format provider.
@@ -117,7 +117,7 @@ public class ImageFormatManager
///
/// The image format to register the encoder for.
/// The encoder to use,
- public void SetEncoder(IImageFormat imageFormat, ImageEncoder encoder)
+ public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder)
{
Guard.NotNull(imageFormat, nameof(imageFormat));
Guard.NotNull(encoder, nameof(encoder));
@@ -172,12 +172,12 @@ public class ImageFormatManager
/// For the specified mime type find the encoder.
///
/// The format to discover
- /// The if found otherwise null
- public ImageEncoder FindEncoder(IImageFormat format)
+ /// The if found otherwise null
+ public IImageEncoder FindEncoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
- return this.mimeTypeEncoders.TryGetValue(format, out ImageEncoder encoder)
+ return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)
? encoder
: null;
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
index 2ddd829f87..63f477ffc6 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
@@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg;
///
/// Encoder for writing the data image to a stream in jpeg format.
///
-public sealed class JpegEncoder : ImageEncoder
+public sealed class JpegEncoder : SynchronousImageEncoder
{
///
/// Backing field for .
@@ -48,16 +48,9 @@ public sealed class JpegEncoder : ImageEncoder
public JpegEncodingColor? ColorType { get; init; }
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
JpegEncoderCore encoder = new(this);
- encoder.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- JpegEncoderCore encoder = new(this);
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Pbm/PbmEncoder.cs b/src/ImageSharp/Formats/Pbm/PbmEncoder.cs
index 6b25347c04..b812e76480 100644
--- a/src/ImageSharp/Formats/Pbm/PbmEncoder.cs
+++ b/src/ImageSharp/Formats/Pbm/PbmEncoder.cs
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm;
///
/// The specification of these images is found at .
///
-public sealed class PbmEncoder : ImageEncoder
+public sealed class PbmEncoder : SynchronousImageEncoder
{
///
/// Gets the encoding of the pixels.
@@ -42,21 +42,14 @@ public sealed class PbmEncoder : ImageEncoder
public PbmColorType? ColorType { get; init; }
///
- /// Gets the Data Type of the pixel components.
+ /// Gets the data type of the pixel components.
///
public PbmComponentType? ComponentType { get; init; }
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
PbmEncoderCore encoder = new(image.GetConfiguration(), this);
- encoder.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- PbmEncoderCore encoder = new(image.GetConfiguration(), this);
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs
index 2daa136c3d..29562d2f8f 100644
--- a/src/ImageSharp/Formats/Png/PngEncoder.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoder.cs
@@ -74,19 +74,9 @@ public class PngEncoder : QuantizingImageEncoder
public PngTransparentColorMode TransparentColorMode { get; init; }
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
using PngEncoderCore encoder = new(image.GetMemoryAllocator(), image.GetConfiguration(), this);
- encoder.Encode(image, stream);
- }
-
- ///
- public override async Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- // The introduction of a local variable that refers to an object the implements
- // IDisposable means you must use async/await, where the compiler generates the
- // state machine and a continuation.
- using PngEncoderCore encoder = new(image.GetMemoryAllocator(), image.GetConfiguration(), this);
- await encoder.EncodeAsync(image, stream, cancellationToken).ConfigureAwait(false);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/QuantizingImageEncoder.cs b/src/ImageSharp/Formats/QuantizingImageEncoder.cs
new file mode 100644
index 0000000000..a885e5550b
--- /dev/null
+++ b/src/ImageSharp/Formats/QuantizingImageEncoder.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.Processing;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
+
+namespace SixLabors.ImageSharp.Formats;
+
+///
+/// Acts as a base class for all image encoders that allow color palette generation via quantization.
+///
+public abstract class QuantizingImageEncoder : SynchronousImageEncoder
+{
+ ///
+ /// Gets the quantizer used to generate the color palette.
+ ///
+ public IQuantizer Quantizer { get; init; } = KnownQuantizers.Octree;
+
+ ///
+ /// Gets the used for quantization when building color palettes.
+ ///
+ public IPixelSamplingStrategy PixelSamplingStrategy { get; init; } = new DefaultPixelSamplingStrategy();
+}
diff --git a/src/ImageSharp/Formats/SynchronousImageEncoder.cs b/src/ImageSharp/Formats/SynchronousImageEncoder.cs
new file mode 100644
index 0000000000..741a206df2
--- /dev/null
+++ b/src/ImageSharp/Formats/SynchronousImageEncoder.cs
@@ -0,0 +1,94 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.IO;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Formats;
+
+///
+/// Acts as a base class for image encoders.
+/// Types that inherit this encoder are required to implement cancellable synchronous encoding operations only.
+///
+public abstract class SynchronousImageEncoder : IImageEncoder
+{
+ ///
+ public bool SkipMetadata { get; init; }
+
+ ///
+ public void Encode(Image image, Stream stream)
+ where TPixel : unmanaged, IPixel
+ => this.EncodeWithSeekableStream(image, stream, default);
+
+ ///
+ public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel
+ => this.EncodeWithSeekableStreamAsync(image, stream, cancellationToken);
+
+ ///
+ /// Encodes the image to the specified stream from the .
+ ///
+ ///
+ /// This method is designed to support the ImageSharp internal infrastructure and is not recommended for direct use.
+ ///
+ /// The pixel format.
+ /// The to encode from.
+ /// The to encode the image data to.
+ /// The token to monitor for cancellation requests.
+ protected abstract void Encode(Image image, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel;
+
+ private void EncodeWithSeekableStream(Image image, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel
+ {
+ Configuration configuration = image.GetConfiguration();
+ if (stream.CanSeek)
+ {
+ this.Encode(image, stream, cancellationToken);
+ }
+ else
+ {
+ using ChunkedMemoryStream ms = new(configuration.MemoryAllocator);
+ this.Encode(image, stream, cancellationToken);
+ ms.Position = 0;
+ ms.CopyTo(stream, configuration.StreamProcessingBufferSize);
+ }
+ }
+
+ private async Task EncodeWithSeekableStreamAsync(Image image, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel
+ {
+ Configuration configuration = image.GetConfiguration();
+ if (stream.CanSeek)
+ {
+ await DoEncodeAsync(stream).ConfigureAwait(false);
+ }
+ else
+ {
+ using ChunkedMemoryStream ms = new(configuration.MemoryAllocator);
+ await DoEncodeAsync(ms);
+ ms.Position = 0;
+ await ms.CopyToAsync(stream, configuration.StreamProcessingBufferSize, cancellationToken)
+ .ConfigureAwait(false);
+ }
+
+ Task DoEncodeAsync(Stream innerStream)
+ {
+ try
+ {
+ // TODO: Are synchronous IO writes OK? We avoid reads.
+ this.Encode(image, innerStream, cancellationToken);
+ return Task.CompletedTask;
+ }
+ catch (OperationCanceledException)
+ {
+ return Task.FromCanceled(cancellationToken);
+ }
+ catch (Exception ex)
+ {
+ return Task.FromException(ex);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Tga/TgaEncoder.cs b/src/ImageSharp/Formats/Tga/TgaEncoder.cs
index e0a3932355..da22935812 100644
--- a/src/ImageSharp/Formats/Tga/TgaEncoder.cs
+++ b/src/ImageSharp/Formats/Tga/TgaEncoder.cs
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Tga;
///
/// Image encoder for writing an image to a stream as a targa truevision image.
///
-public sealed class TgaEncoder : ImageEncoder
+public sealed class TgaEncoder : SynchronousImageEncoder
{
///
/// Gets the number of bits per pixel.
@@ -21,16 +21,9 @@ public sealed class TgaEncoder : ImageEncoder
public TgaCompression Compression { get; init; } = TgaCompression.RunLength;
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
TgaEncoderCore encoder = new(this, image.GetMemoryAllocator());
- encoder.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- TgaEncoderCore encoder = new(this, image.GetMemoryAllocator());
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
index e7bb08cdc3..24cca41dc2 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
@@ -40,16 +40,9 @@ public class TiffEncoder : QuantizingImageEncoder
public TiffPredictor? HorizontalPredictor { get; init; }
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
TiffEncoderCore encode = new(this, image.GetMemoryAllocator());
- encode.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- TiffEncoderCore encoder = new(this, image.GetMemoryAllocator());
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encode.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Webp/WebpEncoder.cs b/src/ImageSharp/Formats/Webp/WebpEncoder.cs
index 359128254f..650afc4dd7 100644
--- a/src/ImageSharp/Formats/Webp/WebpEncoder.cs
+++ b/src/ImageSharp/Formats/Webp/WebpEncoder.cs
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Webp;
///
/// Image encoder for writing an image to a stream in the Webp format.
///
-public sealed class WebpEncoder : ImageEncoder
+public sealed class WebpEncoder : SynchronousImageEncoder
{
///
/// Gets the webp file format used. Either lossless or lossy.
@@ -80,16 +80,9 @@ public sealed class WebpEncoder : ImageEncoder
public int NearLosslessQuality { get; init; } = 100;
///
- public override void Encode(Image image, Stream stream)
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
WebpEncoderCore encoder = new(this, image.GetMemoryAllocator());
- encoder.Encode(image, stream);
- }
-
- ///
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- WebpEncoderCore encoder = new(this, image.GetMemoryAllocator());
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs
index 7094bd047c..2df86b1097 100644
--- a/src/ImageSharp/Image.cs
+++ b/src/ImageSharp/Image.cs
@@ -101,7 +101,7 @@ public abstract partial class Image : IImage, IConfigurationProvider
/// The stream to save the image to.
/// The encoder to save the image with.
/// Thrown if the stream or encoder is null.
- public void Save(Stream stream, ImageEncoder encoder)
+ public void Save(Stream stream, IImageEncoder encoder)
{
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder));
@@ -118,7 +118,7 @@ public abstract partial class Image : IImage, IConfigurationProvider
/// The token to monitor for cancellation requests.
/// Thrown if the stream or encoder is null.
/// A representing the asynchronous operation.
- public Task SaveAsync(Stream stream, ImageEncoder encoder, CancellationToken cancellationToken = default)
+ public Task SaveAsync(Stream stream, IImageEncoder encoder, CancellationToken cancellationToken = default)
{
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder));
@@ -189,11 +189,11 @@ public abstract partial class Image : IImage, IConfigurationProvider
private class EncodeVisitor : IImageVisitor, IImageVisitorAsync
{
- private readonly ImageEncoder encoder;
+ private readonly IImageEncoder encoder;
private readonly Stream stream;
- public EncodeVisitor(ImageEncoder encoder, Stream stream)
+ public EncodeVisitor(IImageEncoder encoder, Stream stream)
{
this.encoder = encoder;
this.stream = stream;
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index d12c483450..2174a0eb94 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -43,14 +43,12 @@ public static partial class ImageExtensions
/// The encoder to save the image with.
/// The path is null.
/// The encoder is null.
- public static void Save(this Image source, string path, ImageEncoder encoder)
+ public static void Save(this Image source, string path, IImageEncoder encoder)
{
Guard.NotNull(path, nameof(path));
Guard.NotNull(encoder, nameof(encoder));
- using (Stream fs = source.GetConfiguration().FileSystem.Create(path))
- {
- source.Save(fs, encoder);
- }
+ using Stream fs = source.GetConfiguration().FileSystem.Create(path);
+ source.Save(fs, encoder);
}
///
@@ -66,7 +64,7 @@ public static partial class ImageExtensions
public static async Task SaveAsync(
this Image source,
string path,
- ImageEncoder encoder,
+ IImageEncoder encoder,
CancellationToken cancellationToken = default)
{
Guard.NotNull(path, nameof(path));
@@ -96,14 +94,14 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream.");
}
- ImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
+ IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null)
{
StringBuilder sb = new();
sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:");
- foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
+ foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
@@ -140,14 +138,14 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream.");
}
- ImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
+ IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null)
{
StringBuilder sb = new();
sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:");
- foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
+ foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
index cb2611c405..cd1180a9bf 100644
--- a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
+++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
@@ -56,7 +56,7 @@ public class ImageFormatManagerTests
[Fact]
public void RegisterNullMimeTypeEncoder()
{
- Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(null, new Mock().Object));
+ Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(null, new Mock().Object));
Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null));
Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(null, null));
}
@@ -72,14 +72,14 @@ public class ImageFormatManagerTests
[Fact]
public void RegisterMimeTypeEncoderReplacesLast()
{
- ImageEncoder encoder1 = new Mock().Object;
+ IImageEncoder encoder1 = new Mock().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1);
- ImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
+ IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder1, found);
- ImageEncoder encoder2 = new Mock().Object;
+ IImageEncoder encoder2 = new Mock().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2);
- ImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
+ IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder2, found2);
Assert.NotEqual(found, found2);
}
diff --git a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs
index e59f4337a4..a3f03bed5a 100644
--- a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs
+++ b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs
@@ -16,8 +16,8 @@ public class ImageSaveTests : IDisposable
{
private readonly Image image;
private readonly Mock fileSystem;
- private readonly Mock encoder;
- private readonly Mock encoderNotInFormat;
+ private readonly Mock encoder;
+ private readonly Mock encoderNotInFormat;
private IImageFormatDetector localMimeTypeDetector;
private Mock localImageFormat;
@@ -27,9 +27,9 @@ public class ImageSaveTests : IDisposable
this.localImageFormat.Setup(x => x.FileExtensions).Returns(new[] { "png" });
this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormat.Object);
- this.encoder = new Mock();
+ this.encoder = new Mock();
- this.encoderNotInFormat = new Mock();
+ this.encoderNotInFormat = new Mock();
this.fileSystem = new Mock();
var config = new Configuration
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Save.cs b/tests/ImageSharp.Tests/Image/ImageTests.Save.cs
index 576af74fa5..88a6b5890b 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.Save.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.Save.cs
@@ -68,7 +68,7 @@ public partial class ImageTests
{
using var image = new Image(5, 5);
image.Dispose();
- ImageEncoder encoder = Mock.Of();
+ IImageEncoder encoder = Mock.Of();
using (var stream = new MemoryStream())
{
Assert.Throws(() => image.Save(stream, encoder));
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs b/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
index ec16225744..1ceadb964d 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
@@ -102,7 +102,7 @@ public partial class ImageTests
{
var image = new Image(5, 5);
image.Dispose();
- ImageEncoder encoder = Mock.Of();
+ IImageEncoder encoder = Mock.Of();
using (var stream = new MemoryStream())
{
await Assert.ThrowsAsync(async () => await image.SaveAsync(stream, encoder));
@@ -120,7 +120,7 @@ public partial class ImageTests
{
using (var image = new Image(5, 5))
{
- ImageEncoder encoder = image.DetectEncoder(filename);
+ IImageEncoder encoder = image.DetectEncoder(filename);
using (var stream = new MemoryStream())
{
var asyncStream = new AsyncStreamWrapper(stream, () => false);
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs
index def1403fda..02ccfb713b 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.cs
@@ -328,7 +328,7 @@ public partial class ImageTests
public void KnownExtension_ReturnsEncoder()
{
using var image = new Image(1, 1);
- ImageEncoder encoder = image.DetectEncoder("dummy.png");
+ IImageEncoder encoder = image.DetectEncoder("dummy.png");
Assert.NotNull(encoder);
Assert.IsType(encoder);
}
diff --git a/tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs b/tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
index 2bbf12bdf8..b65719228c 100644
--- a/tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
+++ b/tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
@@ -55,7 +55,7 @@ public class LargeImageIntegrationTests
Configuration configuration = Configuration.Default.Clone();
configuration.PreferContiguousImageBuffers = true;
- ImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder(
+ IImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder(
configuration.ImageFormatsManager.FindFormatByFileExtension(formatInner));
string dir = TestEnvironment.CreateOutputDirectory(".Temp");
string path = Path.Combine(dir, $"{Guid.NewGuid()}.{formatInner}");
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs
index 092698cb26..8ef31a2af2 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs
@@ -242,7 +242,7 @@ public class XmpProfileTests
return profile;
}
- private static Image WriteAndRead(Image image, ImageEncoder encoder)
+ private static Image WriteAndRead(Image image, IImageEncoder encoder)
{
using (var memStream = new MemoryStream())
{
diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs
index eaf0a5df9c..59eafe17d6 100644
--- a/tests/ImageSharp.Tests/TestFormat.cs
+++ b/tests/ImageSharp.Tests/TestFormat.cs
@@ -233,7 +233,7 @@ public class TestFormat : IConfigurationModule, IImageFormat
public DecoderOptions GeneralOptions { get; init; } = DecoderOptions.Default;
}
- public class TestEncoder : ImageEncoder
+ public class TestEncoder : IImageEncoder
{
private readonly TestFormat testFormat;
@@ -243,13 +243,17 @@ public class TestFormat : IConfigurationModule, IImageFormat
public IEnumerable FileExtensions => this.testFormat.SupportedExtensions;
- public override void Encode(Image image, Stream stream)
+ public bool SkipMetadata { get; init; }
+
+ public void Encode(Image image, Stream stream)
+ where TPixel : unmanaged, IPixel
{
// TODO record this happened so we can verify it.
}
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- => Task.CompletedTask; // TODO record this happened so we can verify it.
+ public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel
+ => Task.CompletedTask; // TODO record this happened so we can verify it.
}
public struct TestPixelForAgnosticDecode : IPixel
diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
index c4f26b0f61..460ecac85a 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
@@ -158,7 +158,7 @@ public class ImagingTestCaseUtility
public string SaveTestOutputFile(
Image image,
string extension = null,
- ImageEncoder encoder = null,
+ IImageEncoder encoder = null,
object testOutputDetails = null,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
@@ -203,7 +203,7 @@ public class ImagingTestCaseUtility
public string[] SaveTestOutputFileMultiFrame(
Image image,
string extension = "png",
- ImageEncoder encoder = null,
+ IImageEncoder encoder = null,
object testOutputDetails = null,
bool appendPixelTypeToFileName = true)
where TPixel : unmanaged, IPixel
diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs
index 8d7b5042f2..a4d305d97f 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Memory;
@@ -13,38 +12,13 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
///
public sealed class ImageSharpPngEncoderWithDefaultConfiguration : PngEncoder
{
- ///
- /// Encodes the image to the specified stream from the .
- ///
- /// The pixel format.
- /// The to encode from.
- /// The to encode the image data to.
- public override void Encode(Image image, Stream stream)
+ ///
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
Configuration configuration = Configuration.Default;
MemoryAllocator allocator = configuration.MemoryAllocator;
using PngEncoderCore encoder = new(allocator, configuration, this);
- encoder.Encode(image, stream);
- }
-
- ///
- /// Encodes the image to the specified stream from the .
- ///
- /// The pixel format.
- /// The to encode from.
- /// The to encode the image data to.
- /// The token to monitor for cancellation requests.
- /// A representing the asynchronous operation.
- public override async Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- {
- Configuration configuration = Configuration.Default;
- MemoryAllocator allocator = configuration.MemoryAllocator;
-
- // The introduction of a local variable that refers to an object the implements
- // IDisposable means you must use async/await, where the compiler generates the
- // state machine and a continuation.
- using PngEncoderCore encoder = new(allocator, configuration, this);
- await encoder.EncodeAsync(image, stream, cancellationToken);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs
index 954ec2ffae..d8dda2eea8 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs
@@ -3,10 +3,11 @@
using System.Drawing.Imaging;
using SixLabors.ImageSharp.Formats;
+using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
-public class SystemDrawingReferenceEncoder : ImageEncoder
+public class SystemDrawingReferenceEncoder : IImageEncoder
{
private readonly ImageFormat imageFormat;
@@ -17,13 +18,17 @@ public class SystemDrawingReferenceEncoder : ImageEncoder
public static SystemDrawingReferenceEncoder Bmp { get; } = new SystemDrawingReferenceEncoder(ImageFormat.Bmp);
- public override void Encode(Image image, Stream stream)
+ public bool SkipMetadata { get; init; }
+
+ public void Encode(Image image, Stream stream)
+ where TPixel : unmanaged, IPixel
{
using System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image);
sdBitmap.Save(stream, this.imageFormat);
}
- public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
+ public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
+ where TPixel : unmanaged, IPixel
{
using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image))
{
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
index 41b6259595..68c1664a8f 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
@@ -26,7 +26,7 @@ public static partial class TestEnvironment
return Configuration.ImageFormatsManager.FindDecoder(format);
}
- internal static ImageEncoder GetReferenceEncoder(string filePath)
+ internal static IImageEncoder GetReferenceEncoder(string filePath)
{
IImageFormat format = GetImageFormat(filePath);
return Configuration.ImageFormatsManager.FindEncoder(format);
@@ -43,7 +43,7 @@ public static partial class TestEnvironment
this Configuration cfg,
IImageFormat imageFormat,
IImageDecoder decoder,
- ImageEncoder encoder,
+ IImageEncoder encoder,
IImageFormatDetector detector)
{
cfg.ImageFormatsManager.SetDecoder(imageFormat, decoder);
@@ -61,8 +61,8 @@ public static partial class TestEnvironment
new WebpConfigurationModule(),
new TiffConfigurationModule());
- ImageEncoder pngEncoder = IsWindows ? SystemDrawingReferenceEncoder.Png : new ImageSharpPngEncoderWithDefaultConfiguration();
- ImageEncoder bmpEncoder = IsWindows ? SystemDrawingReferenceEncoder.Bmp : new BmpEncoder();
+ IImageEncoder pngEncoder = IsWindows ? SystemDrawingReferenceEncoder.Png : new ImageSharpPngEncoderWithDefaultConfiguration();
+ IImageEncoder bmpEncoder = IsWindows ? SystemDrawingReferenceEncoder.Bmp : new BmpEncoder();
// Magick codecs should work on all platforms
cfg.ConfigureCodecs(
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
index 8843204763..31c9f541ea 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
@@ -30,7 +30,7 @@ public static class TestImageExtensions
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true,
- ImageEncoder encoder = null)
+ IImageEncoder encoder = null)
=> image.DebugSave(
provider,
(object)testOutputDetails,
@@ -57,7 +57,7 @@ public static class TestImageExtensions
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true,
- ImageEncoder encoder = null)
+ IImageEncoder encoder = null)
{
if (TestEnvironment.RunsWithCodeCoverage)
{
@@ -77,7 +77,7 @@ public static class TestImageExtensions
public static void DebugSave(
this Image image,
ITestImageProvider provider,
- ImageEncoder encoder,
+ IImageEncoder encoder,
FormattableString testOutputDetails,
bool appendPixelTypeToFileName = true)
=> image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName);
@@ -93,7 +93,7 @@ public static class TestImageExtensions
public static void DebugSave(
this Image image,
ITestImageProvider provider,
- ImageEncoder encoder,
+ IImageEncoder encoder,
object testOutputDetails = null,
bool appendPixelTypeToFileName = true)
=> provider.Utility.SaveTestOutputFile(
@@ -664,7 +664,7 @@ public static class TestImageExtensions
ITestImageProvider provider,
string extension,
object testOutputDetails,
- ImageEncoder encoder,
+ IImageEncoder encoder,
ImageComparer customComparer = null,
bool appendPixelTypeToFileName = true,
string referenceImageExtension = null,
diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
index b879ec649f..36c078dc0e 100644
--- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
@@ -62,7 +62,7 @@ public class TestEnvironmentTests
return;
}
- ImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
+ IImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
Assert.IsType(expectedEncoderType, encoder);
}
@@ -96,7 +96,7 @@ public class TestEnvironmentTests
return;
}
- ImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
+ IImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
Assert.IsType(expectedEncoderType, encoder);
}