Browse Source

Replace IImageEncoder

pull/2301/head
James Jackson-South 4 years ago
parent
commit
31def5c753
  1. 8
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  2. 6
      src/ImageSharp/Advanced/AotCompilerTools.cs
  3. 32
      src/ImageSharp/Formats/IImageEncoder.cs
  4. 18
      src/ImageSharp/Formats/ImageEncoder.cs
  5. 16
      src/ImageSharp/Formats/ImageFormatManager.cs
  6. 8
      src/ImageSharp/Image.cs
  7. 18
      src/ImageSharp/ImageExtensions.cs
  8. 10
      tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
  9. 8
      tests/ImageSharp.Tests/Image/ImageSaveTests.cs
  10. 2
      tests/ImageSharp.Tests/Image/ImageTests.Save.cs
  11. 4
      tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
  12. 2
      tests/ImageSharp.Tests/Image/ImageTests.cs
  13. 2
      tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
  14. 2
      tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs
  15. 9
      tests/ImageSharp.Tests/TestFormat.cs
  16. 4
      tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
  17. 21
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs
  18. 8
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
  19. 11
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  20. 4
      tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs

8
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -21,8 +21,8 @@ public static class AdvancedImageExtensions
/// <param name="filePath">The target file path to save the image to.</param> /// <param name="filePath">The target file path to save the image to.</param>
/// <exception cref="ArgumentNullException">The file path is null.</exception> /// <exception cref="ArgumentNullException">The file path is null.</exception>
/// <exception cref="NotSupportedException">No encoder available for provided path.</exception> /// <exception cref="NotSupportedException">No encoder available for provided path.</exception>
/// <returns>The matching <see cref="IImageEncoder"/>.</returns> /// <returns>The matching <see cref="ImageEncoder"/>.</returns>
public static IImageEncoder DetectEncoder(this Image source, string filePath) public static ImageEncoder DetectEncoder(this Image source, string filePath)
{ {
Guard.NotNull(filePath, nameof(filePath)); Guard.NotNull(filePath, nameof(filePath));
@ -40,13 +40,13 @@ public static class AdvancedImageExtensions
throw new NotSupportedException(sb.ToString()); throw new NotSupportedException(sb.ToString());
} }
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); ImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null) if (encoder is null)
{ {
StringBuilder sb = new(); StringBuilder sb = new();
sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:"); sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders) foreach (KeyValuePair<IImageFormat, ImageEncoder> enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{ {
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine); sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
} }

6
src/ImageSharp/Advanced/AotCompilerTools.cs

@ -230,7 +230,7 @@ internal static class AotCompilerTools
} }
/// <summary> /// <summary>
/// This method pre-seeds the all <see cref="IImageEncoder"/> in the AoT compiler. /// This method pre-seeds the all <see cref="ImageEncoder"/> in the AoT compiler.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve] [Preserve]
@ -266,14 +266,14 @@ internal static class AotCompilerTools
} }
/// <summary> /// <summary>
/// This method pre-seeds the <see cref="IImageEncoder"/> in the AoT compiler. /// This method pre-seeds the <see cref="ImageEncoder"/> in the AoT compiler.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <typeparam name="TEncoder">The encoder.</typeparam> /// <typeparam name="TEncoder">The encoder.</typeparam>
[Preserve] [Preserve]
private static void AotCompileImageEncoder<TPixel, TEncoder>() private static void AotCompileImageEncoder<TPixel, TEncoder>()
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
where TEncoder : class, IImageEncoder where TEncoder : ImageEncoder
{ {
default(TEncoder).Encode<TPixel>(default, default); default(TEncoder).Encode<TPixel>(default, default);
default(TEncoder).EncodeAsync<TPixel>(default, default, default); default(TEncoder).EncodeAsync<TPixel>(default, default, default);

32
src/ImageSharp/Formats/IImageEncoder.cs

@ -1,32 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats;
/// <summary>
/// Encapsulates properties and methods required for encoding an image to a stream.
/// </summary>
public interface IImageEncoder
{
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>;
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>;
}

18
src/ImageSharp/Formats/ImageEncoder.cs

@ -10,18 +10,30 @@ namespace SixLabors.ImageSharp.Formats;
/// <summary> /// <summary>
/// The base class for all image encoders. /// The base class for all image encoders.
/// </summary> /// </summary>
public abstract class ImageEncoder : IImageEncoder public abstract class ImageEncoder
{ {
/// <summary> /// <summary>
/// Gets a value indicating whether to ignore decoded metadata when encoding. /// Gets a value indicating whether to ignore decoded metadata when encoding.
/// </summary> /// </summary>
public bool SkipMetadata { get; init; } public bool SkipMetadata { get; init; }
/// <inheritdoc/> /// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}" />.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}" /> to encode from.</param>
/// <param name="stream">The <see cref="Stream" /> to encode the image data to.</param>
public abstract void Encode<TPixel>(Image<TPixel> image, Stream stream) public abstract void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>; where TPixel : unmanaged, IPixel<TPixel>;
/// <inheritdoc/> /// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}" />.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}" /> to encode from.</param>
/// <param name="stream">The <see cref="Stream" /> to encode the image data to.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task" /> representing the asynchronous operation.</returns>
public abstract Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) public abstract Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>; where TPixel : unmanaged, IPixel<TPixel>;
} }

16
src/ImageSharp/Formats/ImageFormatManager.cs

@ -17,9 +17,9 @@ public class ImageFormatManager
private static readonly object HashLock = new(); private static readonly object HashLock = new();
/// <summary> /// <summary>
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types. /// The list of supported <see cref="ImageEncoder"/> keyed to mime types.
/// </summary> /// </summary>
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new(); private readonly ConcurrentDictionary<IImageFormat, ImageEncoder> mimeTypeEncoders = new();
/// <summary> /// <summary>
/// The list of supported <see cref="ImageDecoder"/> keyed to mime types. /// The list of supported <see cref="ImageDecoder"/> keyed to mime types.
@ -64,9 +64,9 @@ public class ImageFormatManager
internal IEnumerable<KeyValuePair<IImageFormat, ImageDecoder>> ImageDecoders => this.mimeTypeDecoders; internal IEnumerable<KeyValuePair<IImageFormat, ImageDecoder>> ImageDecoders => this.mimeTypeDecoders;
/// <summary> /// <summary>
/// Gets the currently registered <see cref="IImageEncoder"/>s. /// Gets the currently registered <see cref="ImageEncoder"/>s.
/// </summary> /// </summary>
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders; internal IEnumerable<KeyValuePair<IImageFormat, ImageEncoder>> ImageEncoders => this.mimeTypeEncoders;
/// <summary> /// <summary>
/// Registers a new format provider. /// Registers a new format provider.
@ -117,7 +117,7 @@ public class ImageFormatManager
/// </summary> /// </summary>
/// <param name="imageFormat">The image format to register the encoder for.</param> /// <param name="imageFormat">The image format to register the encoder for.</param>
/// <param name="encoder">The encoder to use,</param> /// <param name="encoder">The encoder to use,</param>
public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) public void SetEncoder(IImageFormat imageFormat, ImageEncoder encoder)
{ {
Guard.NotNull(imageFormat, nameof(imageFormat)); Guard.NotNull(imageFormat, nameof(imageFormat));
Guard.NotNull(encoder, nameof(encoder)); Guard.NotNull(encoder, nameof(encoder));
@ -172,12 +172,12 @@ public class ImageFormatManager
/// For the specified mime type find the encoder. /// For the specified mime type find the encoder.
/// </summary> /// </summary>
/// <param name="format">The format to discover</param> /// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns> /// <returns>The <see cref="ImageEncoder"/> if found otherwise null</returns>
public IImageEncoder FindEncoder(IImageFormat format) public ImageEncoder FindEncoder(IImageFormat format)
{ {
Guard.NotNull(format, nameof(format)); Guard.NotNull(format, nameof(format));
return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder) return this.mimeTypeEncoders.TryGetValue(format, out ImageEncoder encoder)
? encoder ? encoder
: null; : null;
} }

8
src/ImageSharp/Image.cs

@ -96,7 +96,7 @@ public abstract partial class Image : IImage, IConfigurationProvider
/// <param name="stream">The stream to save the image to.</param> /// <param name="stream">The stream to save the image to.</param>
/// <param name="encoder">The encoder to save the image with.</param> /// <param name="encoder">The encoder to save the image with.</param>
/// <exception cref="ArgumentNullException">Thrown if the stream or encoder is null.</exception> /// <exception cref="ArgumentNullException">Thrown if the stream or encoder is null.</exception>
public void Save(Stream stream, IImageEncoder encoder) public void Save(Stream stream, ImageEncoder encoder)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder)); Guard.NotNull(encoder, nameof(encoder));
@ -113,7 +113,7 @@ public abstract partial class Image : IImage, IConfigurationProvider
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">Thrown if the stream or encoder is null.</exception> /// <exception cref="ArgumentNullException">Thrown if the stream or encoder is null.</exception>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public Task SaveAsync(Stream stream, IImageEncoder encoder, CancellationToken cancellationToken = default) public Task SaveAsync(Stream stream, ImageEncoder encoder, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder)); Guard.NotNull(encoder, nameof(encoder));
@ -184,11 +184,11 @@ public abstract partial class Image : IImage, IConfigurationProvider
private class EncodeVisitor : IImageVisitor, IImageVisitorAsync private class EncodeVisitor : IImageVisitor, IImageVisitorAsync
{ {
private readonly IImageEncoder encoder; private readonly ImageEncoder encoder;
private readonly Stream stream; private readonly Stream stream;
public EncodeVisitor(IImageEncoder encoder, Stream stream) public EncodeVisitor(ImageEncoder encoder, Stream stream)
{ {
this.encoder = encoder; this.encoder = encoder;
this.stream = stream; this.stream = stream;

18
src/ImageSharp/ImageExtensions.cs

@ -43,7 +43,7 @@ public static partial class ImageExtensions
/// <param name="encoder">The encoder to save the image with.</param> /// <param name="encoder">The encoder to save the image with.</param>
/// <exception cref="ArgumentNullException">The path is null.</exception> /// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="ArgumentNullException">The encoder is null.</exception> /// <exception cref="ArgumentNullException">The encoder is null.</exception>
public static void Save(this Image source, string path, IImageEncoder encoder) public static void Save(this Image source, string path, ImageEncoder encoder)
{ {
Guard.NotNull(path, nameof(path)); Guard.NotNull(path, nameof(path));
Guard.NotNull(encoder, nameof(encoder)); Guard.NotNull(encoder, nameof(encoder));
@ -66,16 +66,14 @@ public static partial class ImageExtensions
public static async Task SaveAsync( public static async Task SaveAsync(
this Image source, this Image source,
string path, string path,
IImageEncoder encoder, ImageEncoder encoder,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
Guard.NotNull(path, nameof(path)); Guard.NotNull(path, nameof(path));
Guard.NotNull(encoder, nameof(encoder)); Guard.NotNull(encoder, nameof(encoder));
using (Stream fs = source.GetConfiguration().FileSystem.Create(path)) using Stream fs = source.GetConfiguration().FileSystem.Create(path);
{ await source.SaveAsync(fs, encoder, cancellationToken).ConfigureAwait(false);
await source.SaveAsync(fs, encoder, cancellationToken).ConfigureAwait(false);
}
} }
/// <summary> /// <summary>
@ -98,14 +96,14 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream."); throw new NotSupportedException("Cannot write to the stream.");
} }
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); ImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null) if (encoder is null)
{ {
StringBuilder sb = new(); StringBuilder sb = new();
sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:"); sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:");
foreach (KeyValuePair<IImageFormat, IImageEncoder> val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) foreach (KeyValuePair<IImageFormat, ImageEncoder> val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{ {
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
} }
@ -142,14 +140,14 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream."); throw new NotSupportedException("Cannot write to the stream.");
} }
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); ImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null) if (encoder is null)
{ {
StringBuilder sb = new(); StringBuilder sb = new();
sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:"); sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:");
foreach (KeyValuePair<IImageFormat, IImageEncoder> val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) foreach (KeyValuePair<IImageFormat, ImageEncoder> val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{ {
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
} }

10
tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs

@ -56,7 +56,7 @@ public class ImageFormatManagerTests
[Fact] [Fact]
public void RegisterNullMimeTypeEncoder() public void RegisterNullMimeTypeEncoder()
{ {
Assert.Throws<ArgumentNullException>(() => this.DefaultFormatsManager.SetEncoder(null, new Mock<IImageEncoder>().Object)); Assert.Throws<ArgumentNullException>(() => this.DefaultFormatsManager.SetEncoder(null, new Mock<ImageEncoder>().Object));
Assert.Throws<ArgumentNullException>(() => this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null)); Assert.Throws<ArgumentNullException>(() => this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null));
Assert.Throws<ArgumentNullException>(() => this.DefaultFormatsManager.SetEncoder(null, null)); Assert.Throws<ArgumentNullException>(() => this.DefaultFormatsManager.SetEncoder(null, null));
} }
@ -72,14 +72,14 @@ public class ImageFormatManagerTests
[Fact] [Fact]
public void RegisterMimeTypeEncoderReplacesLast() public void RegisterMimeTypeEncoderReplacesLast()
{ {
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object; ImageEncoder encoder1 = new Mock<ImageEncoder>().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1);
IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); ImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder1, found); Assert.Equal(encoder1, found);
IImageEncoder encoder2 = new Mock<IImageEncoder>().Object; ImageEncoder encoder2 = new Mock<ImageEncoder>().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2);
IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); ImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder2, found2); Assert.Equal(encoder2, found2);
Assert.NotEqual(found, found2); Assert.NotEqual(found, found2);
} }

8
tests/ImageSharp.Tests/Image/ImageSaveTests.cs

@ -16,8 +16,8 @@ public class ImageSaveTests : IDisposable
{ {
private readonly Image<Rgba32> image; private readonly Image<Rgba32> image;
private readonly Mock<IFileSystem> fileSystem; private readonly Mock<IFileSystem> fileSystem;
private readonly Mock<IImageEncoder> encoder; private readonly Mock<ImageEncoder> encoder;
private readonly Mock<IImageEncoder> encoderNotInFormat; private readonly Mock<ImageEncoder> encoderNotInFormat;
private IImageFormatDetector localMimeTypeDetector; private IImageFormatDetector localMimeTypeDetector;
private Mock<IImageFormat> localImageFormat; private Mock<IImageFormat> localImageFormat;
@ -27,9 +27,9 @@ public class ImageSaveTests : IDisposable
this.localImageFormat.Setup(x => x.FileExtensions).Returns(new[] { "png" }); this.localImageFormat.Setup(x => x.FileExtensions).Returns(new[] { "png" });
this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormat.Object); this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormat.Object);
this.encoder = new Mock<IImageEncoder>(); this.encoder = new Mock<ImageEncoder>();
this.encoderNotInFormat = new Mock<IImageEncoder>(); this.encoderNotInFormat = new Mock<ImageEncoder>();
this.fileSystem = new Mock<IFileSystem>(); this.fileSystem = new Mock<IFileSystem>();
var config = new Configuration var config = new Configuration

2
tests/ImageSharp.Tests/Image/ImageTests.Save.cs

@ -68,7 +68,7 @@ public partial class ImageTests
{ {
using var image = new Image<Rgba32>(5, 5); using var image = new Image<Rgba32>(5, 5);
image.Dispose(); image.Dispose();
IImageEncoder encoder = Mock.Of<IImageEncoder>(); ImageEncoder encoder = Mock.Of<ImageEncoder>();
using (var stream = new MemoryStream()) using (var stream = new MemoryStream())
{ {
Assert.Throws<ObjectDisposedException>(() => image.Save(stream, encoder)); Assert.Throws<ObjectDisposedException>(() => image.Save(stream, encoder));

4
tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs

@ -102,7 +102,7 @@ public partial class ImageTests
{ {
var image = new Image<Rgba32>(5, 5); var image = new Image<Rgba32>(5, 5);
image.Dispose(); image.Dispose();
IImageEncoder encoder = Mock.Of<IImageEncoder>(); ImageEncoder encoder = Mock.Of<ImageEncoder>();
using (var stream = new MemoryStream()) using (var stream = new MemoryStream())
{ {
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await image.SaveAsync(stream, encoder)); await Assert.ThrowsAsync<ObjectDisposedException>(async () => await image.SaveAsync(stream, encoder));
@ -120,7 +120,7 @@ public partial class ImageTests
{ {
using (var image = new Image<Rgba32>(5, 5)) using (var image = new Image<Rgba32>(5, 5))
{ {
IImageEncoder encoder = image.DetectEncoder(filename); ImageEncoder encoder = image.DetectEncoder(filename);
using (var stream = new MemoryStream()) using (var stream = new MemoryStream())
{ {
var asyncStream = new AsyncStreamWrapper(stream, () => false); var asyncStream = new AsyncStreamWrapper(stream, () => false);

2
tests/ImageSharp.Tests/Image/ImageTests.cs

@ -328,7 +328,7 @@ public partial class ImageTests
public void KnownExtension_ReturnsEncoder() public void KnownExtension_ReturnsEncoder()
{ {
using var image = new Image<L8>(1, 1); using var image = new Image<L8>(1, 1);
IImageEncoder encoder = image.DetectEncoder("dummy.png"); ImageEncoder encoder = image.DetectEncoder("dummy.png");
Assert.NotNull(encoder); Assert.NotNull(encoder);
Assert.IsType<PngEncoder>(encoder); Assert.IsType<PngEncoder>(encoder);
} }

2
tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs

@ -55,7 +55,7 @@ public class LargeImageIntegrationTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.PreferContiguousImageBuffers = true; configuration.PreferContiguousImageBuffers = true;
IImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder( ImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder(
configuration.ImageFormatsManager.FindFormatByFileExtension(formatInner)); configuration.ImageFormatsManager.FindFormatByFileExtension(formatInner));
string dir = TestEnvironment.CreateOutputDirectory(".Temp"); string dir = TestEnvironment.CreateOutputDirectory(".Temp");
string path = Path.Combine(dir, $"{Guid.NewGuid()}.{formatInner}"); string path = Path.Combine(dir, $"{Guid.NewGuid()}.{formatInner}");

2
tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs

@ -242,7 +242,7 @@ public class XmpProfileTests
return profile; return profile;
} }
private static Image<Rgba32> WriteAndRead(Image<Rgba32> image, IImageEncoder encoder) private static Image<Rgba32> WriteAndRead(Image<Rgba32> image, ImageEncoder encoder)
{ {
using (var memStream = new MemoryStream()) using (var memStream = new MemoryStream())
{ {

9
tests/ImageSharp.Tests/TestFormat.cs

@ -233,7 +233,7 @@ public class TestFormat : IConfigurationModule, IImageFormat
public DecoderOptions GeneralOptions { get; set; } = new(); public DecoderOptions GeneralOptions { get; set; } = new();
} }
public class TestEncoder : IImageEncoder public class TestEncoder : ImageEncoder
{ {
private readonly TestFormat testFormat; private readonly TestFormat testFormat;
@ -243,14 +243,13 @@ public class TestFormat : IConfigurationModule, IImageFormat
public IEnumerable<string> FileExtensions => this.testFormat.SupportedExtensions; public IEnumerable<string> FileExtensions => this.testFormat.SupportedExtensions;
public void Encode<TPixel>(Image<TPixel> image, Stream stream) public override void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{ {
// TODO record this happened so we can verify it. // TODO record this happened so we can verify it.
} }
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) public override Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> => Task.CompletedTask; // TODO record this happened so we can verify it. => Task.CompletedTask; // TODO record this happened so we can verify it.
} }
public struct TestPixelForAgnosticDecode : IPixel<TestPixelForAgnosticDecode> public struct TestPixelForAgnosticDecode : IPixel<TestPixelForAgnosticDecode>

4
tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs

@ -158,7 +158,7 @@ public class ImagingTestCaseUtility
public string SaveTestOutputFile( public string SaveTestOutputFile(
Image image, Image image,
string extension = null, string extension = null,
IImageEncoder encoder = null, ImageEncoder encoder = null,
object testOutputDetails = null, object testOutputDetails = null,
bool appendPixelTypeToFileName = true, bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true) bool appendSourceFileOrDescription = true)
@ -203,7 +203,7 @@ public class ImagingTestCaseUtility
public string[] SaveTestOutputFileMultiFrame<TPixel>( public string[] SaveTestOutputFileMultiFrame<TPixel>(
Image<TPixel> image, Image<TPixel> image,
string extension = "png", string extension = "png",
IImageEncoder encoder = null, ImageEncoder encoder = null,
object testOutputDetails = null, object testOutputDetails = null,
bool appendPixelTypeToFileName = true) bool appendPixelTypeToFileName = true)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>

21
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs

@ -3,34 +3,27 @@
using System.Drawing.Imaging; using System.Drawing.Imaging;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
public class SystemDrawingReferenceEncoder : IImageEncoder public class SystemDrawingReferenceEncoder : ImageEncoder
{ {
private readonly System.Drawing.Imaging.ImageFormat imageFormat; private readonly ImageFormat imageFormat;
public SystemDrawingReferenceEncoder(ImageFormat imageFormat) public SystemDrawingReferenceEncoder(ImageFormat imageFormat)
{ => this.imageFormat = imageFormat;
this.imageFormat = imageFormat;
}
public static SystemDrawingReferenceEncoder Png { get; } = new SystemDrawingReferenceEncoder(ImageFormat.Png); public static SystemDrawingReferenceEncoder Png { get; } = new SystemDrawingReferenceEncoder(ImageFormat.Png);
public static SystemDrawingReferenceEncoder Bmp { get; } = new SystemDrawingReferenceEncoder(ImageFormat.Bmp); public static SystemDrawingReferenceEncoder Bmp { get; } = new SystemDrawingReferenceEncoder(ImageFormat.Bmp);
public void Encode<TPixel>(Image<TPixel> image, Stream stream) public override void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{ {
using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image)) using System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image);
{ sdBitmap.Save(stream, this.imageFormat);
sdBitmap.Save(stream, this.imageFormat);
}
} }
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) public override Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{ {
using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image)) using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image))
{ {

8
tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs

@ -26,7 +26,7 @@ public static partial class TestEnvironment
return Configuration.ImageFormatsManager.FindDecoder(format); return Configuration.ImageFormatsManager.FindDecoder(format);
} }
internal static IImageEncoder GetReferenceEncoder(string filePath) internal static ImageEncoder GetReferenceEncoder(string filePath)
{ {
IImageFormat format = GetImageFormat(filePath); IImageFormat format = GetImageFormat(filePath);
return Configuration.ImageFormatsManager.FindEncoder(format); return Configuration.ImageFormatsManager.FindEncoder(format);
@ -43,7 +43,7 @@ public static partial class TestEnvironment
this Configuration cfg, this Configuration cfg,
IImageFormat imageFormat, IImageFormat imageFormat,
ImageDecoder decoder, ImageDecoder decoder,
IImageEncoder encoder, ImageEncoder encoder,
IImageFormatDetector detector) IImageFormatDetector detector)
{ {
cfg.ImageFormatsManager.SetDecoder(imageFormat, decoder); cfg.ImageFormatsManager.SetDecoder(imageFormat, decoder);
@ -61,8 +61,8 @@ public static partial class TestEnvironment
new WebpConfigurationModule(), new WebpConfigurationModule(),
new TiffConfigurationModule()); new TiffConfigurationModule());
IImageEncoder pngEncoder = IsWindows ? SystemDrawingReferenceEncoder.Png : new ImageSharpPngEncoderWithDefaultConfiguration(); ImageEncoder pngEncoder = IsWindows ? SystemDrawingReferenceEncoder.Png : new ImageSharpPngEncoderWithDefaultConfiguration();
IImageEncoder bmpEncoder = IsWindows ? SystemDrawingReferenceEncoder.Bmp : new BmpEncoder(); ImageEncoder bmpEncoder = IsWindows ? SystemDrawingReferenceEncoder.Bmp : new BmpEncoder();
// Magick codecs should work on all platforms // Magick codecs should work on all platforms
cfg.ConfigureCodecs( cfg.ConfigureCodecs(

11
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -19,6 +19,7 @@ public static class TestImageExtensions
/// <summary> /// <summary>
/// TODO: Consider adding this private processor to the library /// TODO: Consider adding this private processor to the library
/// </summary> /// </summary>
/// <param name="ctx">The image processing context.</param>
public static void MakeOpaque(this IImageProcessingContext ctx) => public static void MakeOpaque(this IImageProcessingContext ctx) =>
ctx.ApplyProcessor(new MakeOpaqueProcessor()); ctx.ApplyProcessor(new MakeOpaqueProcessor());
@ -29,7 +30,7 @@ public static class TestImageExtensions
string extension = "png", string extension = "png",
bool appendPixelTypeToFileName = true, bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true, bool appendSourceFileOrDescription = true,
IImageEncoder encoder = null) ImageEncoder encoder = null)
=> image.DebugSave( => image.DebugSave(
provider, provider,
(object)testOutputDetails, (object)testOutputDetails,
@ -56,7 +57,7 @@ public static class TestImageExtensions
string extension = "png", string extension = "png",
bool appendPixelTypeToFileName = true, bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true, bool appendSourceFileOrDescription = true,
IImageEncoder encoder = null) ImageEncoder encoder = null)
{ {
if (TestEnvironment.RunsWithCodeCoverage) if (TestEnvironment.RunsWithCodeCoverage)
{ {
@ -76,7 +77,7 @@ public static class TestImageExtensions
public static void DebugSave( public static void DebugSave(
this Image image, this Image image,
ITestImageProvider provider, ITestImageProvider provider,
IImageEncoder encoder, ImageEncoder encoder,
FormattableString testOutputDetails, FormattableString testOutputDetails,
bool appendPixelTypeToFileName = true) bool appendPixelTypeToFileName = true)
=> image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); => image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName);
@ -92,7 +93,7 @@ public static class TestImageExtensions
public static void DebugSave( public static void DebugSave(
this Image image, this Image image,
ITestImageProvider provider, ITestImageProvider provider,
IImageEncoder encoder, ImageEncoder encoder,
object testOutputDetails = null, object testOutputDetails = null,
bool appendPixelTypeToFileName = true) bool appendPixelTypeToFileName = true)
=> provider.Utility.SaveTestOutputFile( => provider.Utility.SaveTestOutputFile(
@ -663,7 +664,7 @@ public static class TestImageExtensions
ITestImageProvider provider, ITestImageProvider provider,
string extension, string extension,
object testOutputDetails, object testOutputDetails,
IImageEncoder encoder, ImageEncoder encoder,
ImageComparer customComparer = null, ImageComparer customComparer = null,
bool appendPixelTypeToFileName = true, bool appendPixelTypeToFileName = true,
string referenceImageExtension = null, string referenceImageExtension = null,

4
tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs

@ -62,7 +62,7 @@ public class TestEnvironmentTests
return; return;
} }
IImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName); ImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
Assert.IsType(expectedEncoderType, encoder); Assert.IsType(expectedEncoderType, encoder);
} }
@ -96,7 +96,7 @@ public class TestEnvironmentTests
return; return;
} }
IImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName); ImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
Assert.IsType(expectedEncoderType, encoder); Assert.IsType(expectedEncoderType, encoder);
} }

Loading…
Cancel
Save