Browse Source

Update tests and fix issues

pull/2180/head
James Jackson-South 4 years ago
parent
commit
1c2d1f42e2
  1. 4
      src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs
  2. 2
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  3. 2
      src/ImageSharp/Formats/ImageDecoder{T}.cs
  4. 2
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  5. 2
      src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs
  6. 45
      src/ImageSharp/Image.FromBytes.cs
  7. 3
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs
  8. 4
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs
  9. 7
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs
  10. 19
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs
  11. 3
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs
  12. 5
      tests/ImageSharp.Benchmarks/Codecs/Tga/DecodeTga.cs
  13. 4
      tests/ImageSharp.Benchmarks/Codecs/Webp/DecodeWebp.cs
  14. 164
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  15. 60
      tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
  16. 34
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
  17. 47
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  18. 61
      tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs
  19. 58
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
  20. 82
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  21. 6
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
  22. 9
      tests/ImageSharp.Tests/Formats/Jpg/SpectralToPixelConversionTests.cs
  23. 11
      tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs
  24. 10
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs
  25. 74
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  26. 102
      tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs
  27. 23
      tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs
  28. 2
      tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs
  29. 6
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  30. 22
      tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs
  31. 4
      tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs
  32. 107
      tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs
  33. 35
      tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs
  34. 91
      tests/ImageSharp.Tests/Image/ImageTests.Decode_Cancellation.cs
  35. 60
      tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs
  36. 81
      tests/ImageSharp.Tests/Image/ImageTests.Identify.cs
  37. 21
      tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs
  38. 65
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs
  39. 66
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs
  40. 88
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs
  41. 71
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs
  42. 61
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs
  43. 17
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs
  44. 75
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs
  45. 10
      tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
  46. 20
      tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs
  47. 30
      tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs
  48. 10
      tests/ImageSharp.Tests/Metadata/Profiles/XMP/XmpProfileTests.cs
  49. 17
      tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs
  50. 12
      tests/ImageSharp.Tests/ProfilingBenchmarks/LoadResizeSaveProfilingBenchmarks.cs
  51. 56
      tests/ImageSharp.Tests/TestFile.cs
  52. 36
      tests/ImageSharp.Tests/TestFormat.cs
  53. 77
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs
  54. 43
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
  55. 77
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
  56. 35
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
  57. 2
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
  58. 32
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  59. 31
      tests/ImageSharp.Tests/TestUtilities/Tests/MagickReferenceCodecTests.cs
  60. 58
      tests/ImageSharp.Tests/TestUtilities/Tests/SystemDrawingReferenceCodecTests.cs
  61. 79
      tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs

4
src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs

@ -12,9 +12,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public DecoderOptions GeneralOptions { get; set; } = new(); public DecoderOptions GeneralOptions { get; set; } = new();
/// <summary> /// <summary>
/// Gets the value indicating how to deal with skipped pixels, /// Gets or sets the value indicating how to deal with skipped pixels,
/// which can occur during decoding run length encoded bitmaps. /// which can occur during decoding run length encoded bitmaps.
/// </summary> /// </summary>
public RleSkippedPixelHandling RleSkippedPixelHandling { get; } public RleSkippedPixelHandling RleSkippedPixelHandling { get; set; }
} }
} }

2
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{ {
if (nextFlag == GifConstants.ImageLabel) if (nextFlag == GifConstants.ImageLabel)
{ {
if (previousFrame != null && frameCount++ > this.maxFrames) if (previousFrame != null && ++frameCount == this.maxFrames)
{ {
break; break;
} }

2
src/ImageSharp/Formats/ImageDecoder{T}.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats
/// </summary> /// </summary>
/// <typeparam name="T">The type of specialized decoder options.</typeparam> /// <typeparam name="T">The type of specialized decoder options.</typeparam>
public abstract class ImageDecoder<T> : IImageInfoDetector, IImageDecoder public abstract class ImageDecoder<T> : IImageInfoDetector, IImageDecoder
where T : ISpecializedDecoderOptions, new() where T : class, ISpecializedDecoderOptions, new()
{ {
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken)

2
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, cancellationToken); ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, cancellationToken);
frames.Add(frame); frames.Add(frame);
if (frameCount++ > this.maxFrames) if (++frameCount == this.maxFrames)
{ {
break; break;
} }

2
src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs

@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
break; break;
} }
if (stream.Position == stream.Length || frameCount++ > this.maxFrames) if (stream.Position == stream.Length || ++frameCount == this.maxFrames)
{ {
break; break;
} }

45
src/ImageSharp/Image.FromBytes.cs

@ -52,6 +52,51 @@ namespace SixLabors.ImageSharp
return default; return default;
} }
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="data">The byte span containing encoded image data to read the header from.</param>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(ReadOnlySpan<byte> data) => Identify(data, out IImageFormat _);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(ReadOnlySpan<byte> data, out IImageFormat format)
=> Identify(DecoderOptions.Default, data, out format);
/// <summary>
/// Reads the raw image information from the specified span of bytes without fully decoding it.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="data">The byte span containing encoded image data to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
public static unsafe IImageInfo Identify(DecoderOptions options, ReadOnlySpan<byte> data, out IImageFormat format)
{
fixed (byte* ptr = &data.GetPinnableReference())
{
using var stream = new UnmanagedMemoryStream(ptr, data.Length);
return Identify(options, stream, out format);
}
}
/// <summary> /// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span. /// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary> /// </summary>

3
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs

@ -3,6 +3,7 @@
using System.IO; using System.IO;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Tests; using SixLabors.ImageSharp.Tests;
@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
private void GenericBechmark() private void GenericBechmark()
{ {
this.preloadedImageStream.Position = 0; this.preloadedImageStream.Position = 0;
using Image img = this.decoder.Decode(Configuration.Default, this.preloadedImageStream, default); using Image img = this.decoder.Decode(DecoderOptions.Default, this.preloadedImageStream, default);
} }
[GlobalSetup(Target = nameof(JpegBaselineInterleaved444))] [GlobalSetup(Target = nameof(JpegBaselineInterleaved444))]

4
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs

@ -38,8 +38,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{ {
using var memoryStream = new MemoryStream(this.jpegBytes); using var memoryStream = new MemoryStream(this.jpegBytes);
using var bufferedStream = new BufferedReadStream(Configuration.Default, memoryStream); using var bufferedStream = new BufferedReadStream(Configuration.Default, memoryStream);
var options = new JpegDecoderOptions();
options.GeneralOptions.SkipMetadata = true;
using var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder { IgnoreMetadata = true }); using var decoder = new JpegDecoderCore(options);
var spectralConverter = new NoopSpectralConverter(); var spectralConverter = new NoopSpectralConverter();
decoder.ParseStream(bufferedStream, spectralConverter, cancellationToken: default); decoder.ParseStream(bufferedStream, spectralConverter, cancellationToken: default);
} }

7
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs

@ -3,7 +3,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests; using SixLabors.ImageSharp.Tests;
using SDImage = System.Drawing.Image; using SDImage = System.Drawing.Image;
@ -18,8 +17,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Config(typeof(Config.ShortMultiFramework))] [Config(typeof(Config.ShortMultiFramework))]
public class DecodeJpeg_Aggregate : MultiImageBenchmarkBase public class DecodeJpeg_Aggregate : MultiImageBenchmarkBase
{ {
protected override IEnumerable<string> InputImageSubfoldersOrFiles => protected override IEnumerable<string> InputImageSubfoldersOrFiles
new[] => new[]
{ {
TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome, TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome,
TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr, TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr,
@ -33,7 +32,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark] [Benchmark]
public void ImageSharp() public void ImageSharp()
=> this.ForEachStream(ms => Image.Load<Rgba32>(ms, new JpegDecoder())); => this.ForEachStream(ms => Image.Load<Rgba32>(ms));
[Benchmark(Baseline = true)] [Benchmark(Baseline = true)]
public void SystemDrawing() public void SystemDrawing()

19
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs

@ -3,8 +3,7 @@
using System.IO; using System.IO;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests; using SixLabors.ImageSharp.Tests;
using SDImage = System.Drawing.Image; using SDImage = System.Drawing.Image;
using SDSize = System.Drawing.Size; using SDSize = System.Drawing.Size;
@ -47,26 +46,18 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)] [Benchmark(Baseline = true)]
public SDSize SystemDrawing() public SDSize SystemDrawing()
{ {
using (var memoryStream = new MemoryStream(this.jpegBytes)) using var memoryStream = new MemoryStream(this.jpegBytes);
{ using var image = SDImage.FromStream(memoryStream);
using (var image = SDImage.FromStream(memoryStream))
{
return image.Size; return image.Size;
} }
}
}
[Benchmark] [Benchmark]
public Size ImageSharp() public Size ImageSharp()
{ {
using (var memoryStream = new MemoryStream(this.jpegBytes)) using var memoryStream = new MemoryStream(this.jpegBytes);
{ using var image = Image.Load(new DecoderOptions() { SkipMetadata = true }, memoryStream);
using (var image = Image.Load(memoryStream, new JpegDecoder { IgnoreMetadata = true }))
{
return new Size(image.Width, image.Height); return new Size(image.Width, image.Height);
} }
}
}
/* /*
| Method | TestImage | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | | Method | TestImage | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |

3
tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs

@ -3,6 +3,7 @@
using System.IO; using System.IO;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Tests; using SixLabors.ImageSharp.Tests;
@ -32,7 +33,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{ {
using var memoryStream = new MemoryStream(this.jpegBytes); using var memoryStream = new MemoryStream(this.jpegBytes);
var decoder = new JpegDecoder(); var decoder = new JpegDecoder();
return decoder.Identify(Configuration.Default, memoryStream, default); return decoder.Identify(DecoderOptions.Default, memoryStream, default);
} }
} }
} }

5
tests/ImageSharp.Benchmarks/Codecs/Tga/DecodeTga.cs

@ -7,7 +7,6 @@ using System.Threading;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using ImageMagick; using ImageMagick;
using Pfim; using Pfim;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests; using SixLabors.ImageSharp.Tests;
@ -18,7 +17,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{ {
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
private readonly PfimConfig pfimConfig = new PfimConfig(allocator: new PfimAllocator()); private readonly PfimConfig pfimConfig = new(allocator: new PfimAllocator());
private byte[] data; private byte[] data;
@ -40,7 +39,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Description = "ImageSharp Tga")] [Benchmark(Description = "ImageSharp Tga")]
public int TgaImageSharp() public int TgaImageSharp()
{ {
using var image = Image.Load<Bgr24>(this.data, new TgaDecoder()); using var image = Image.Load<Bgr24>(this.data);
return image.Width; return image.Width;
} }

4
tests/ImageSharp.Benchmarks/Codecs/Webp/DecodeWebp.cs

@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public int WebpLossy() public int WebpLossy()
{ {
using var memoryStream = new MemoryStream(this.webpLossyBytes); using var memoryStream = new MemoryStream(this.webpLossyBytes);
using var image = Image.Load<Rgba32>(this.configuration, memoryStream); using var image = Image.Load<Rgba32>(memoryStream);
return image.Height; return image.Height;
} }
@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public int WebpLossless() public int WebpLossless()
{ {
using var memoryStream = new MemoryStream(this.webpLosslessBytes); using var memoryStream = new MemoryStream(this.webpLosslessBytes);
using var image = Image.Load<Rgba32>(this.configuration, memoryStream); using var image = Image.Load<Rgba32>(memoryStream);
return image.Height; return image.Height;
} }

164
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -4,7 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using Microsoft.DotNet.RemoteExecutor; using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
@ -75,11 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
} }
string providerDump = BasicSerializer.Serialize(provider); string providerDump = BasicSerializer.Serialize(provider);
RemoteExecutor.Invoke( RemoteExecutor.Invoke(RunTest, providerDump, "Disco").Dispose();
RunTest,
providerDump,
"Disco")
.Dispose();
} }
[Theory] [Theory]
@ -98,12 +94,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBitfields<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBitfields<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit16Inverted, PixelTypes.Rgba32)] [WithFile(Bit16Inverted, PixelTypes.Rgba32)]
@ -111,12 +105,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_Inverted<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_Inverted<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit1, PixelTypes.Rgba32)] [WithFile(Bit1, PixelTypes.Rgba32)]
@ -124,72 +116,60 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_1Bit<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_1Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder()); image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(Bit4, PixelTypes.Rgba32)] [WithFile(Bit4, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_4Bit<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_4Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit8, PixelTypes.Rgba32)] [WithFile(Bit8, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_8Bit<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit16, PixelTypes.Rgba32)] [WithFile(Bit16, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_16Bit<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit32Rgb, PixelTypes.Rgba32)] [WithFile(Bit32Rgb, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_32Bit<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Rgba32v4, PixelTypes.Rgba32)] [WithFile(Rgba32v4, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_32BitV4Header_Fast<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_32BitV4Header_Fast<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(RLE4Cut, PixelTypes.Rgba32)] [WithFile(RLE4Cut, PixelTypes.Rgba32)]
@ -199,12 +179,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
RleSkippedPixelHandling skippedPixelHandling = TestEnvironment.IsWindows ? RleSkippedPixelHandling.Black : RleSkippedPixelHandling.FirstColorOfPalette; RleSkippedPixelHandling skippedPixelHandling = TestEnvironment.IsWindows ? RleSkippedPixelHandling.Black : RleSkippedPixelHandling.FirstColorOfPalette;
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = skippedPixelHandling })) BmpDecoderOptions options = new() { RleSkippedPixelHandling = skippedPixelHandling };
{
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(RLE4, PixelTypes.Rgba32)] [WithFile(RLE4, PixelTypes.Rgba32)]
@ -212,12 +192,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
RleSkippedPixelHandling skippedPixelHandling = TestEnvironment.IsWindows ? RleSkippedPixelHandling.Black : RleSkippedPixelHandling.FirstColorOfPalette; RleSkippedPixelHandling skippedPixelHandling = TestEnvironment.IsWindows ? RleSkippedPixelHandling.Black : RleSkippedPixelHandling.FirstColorOfPalette;
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = skippedPixelHandling })) BmpDecoderOptions options = new() { RleSkippedPixelHandling = skippedPixelHandling };
{
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(RLE8Cut, PixelTypes.Rgba32)] [WithFile(RLE8Cut, PixelTypes.Rgba32)]
@ -227,15 +207,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_SystemDrawingRefDecoder<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_SystemDrawingRefDecoder<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.Black })) BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black };
{ using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider); image.DebugSave(provider);
if (TestEnvironment.IsWindows) if (TestEnvironment.IsWindows)
{ {
image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder()); image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder());
} }
} }
}
[Theory] [Theory]
[WithFile(RLE8Cut, PixelTypes.Rgba32)] [WithFile(RLE8Cut, PixelTypes.Rgba32)]
@ -243,12 +222,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_MagickRefDecoder<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_MagickRefDecoder<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette })) BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette };
{ using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder()); image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(RLE8, PixelTypes.Rgba32, false)] [WithFile(RLE8, PixelTypes.Rgba32, false)]
@ -263,12 +241,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
provider.LimitAllocatorBufferCapacity().InBytesSqrt(400); provider.LimitAllocatorBufferCapacity().InBytesSqrt(400);
} }
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette })) BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette };
{ using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder()); image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(RLE24, PixelTypes.Rgba32, false)] [WithFile(RLE24, PixelTypes.Rgba32, false)]
@ -285,48 +262,42 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
provider.LimitAllocatorBufferCapacity().InBytesSqrt(400); provider.LimitAllocatorBufferCapacity().InBytesSqrt(400);
} }
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.Black })) BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black };
{ using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider); image.DebugSave(provider);
// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file. // TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider); // image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(RgbaAlphaBitfields, PixelTypes.Rgba32)] [WithFile(RgbaAlphaBitfields, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeAlphaBitfields<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeAlphaBitfields<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file. // TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider); // image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit32Rgba, PixelTypes.Rgba32)] [WithFile(Bit32Rgba, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeBitmap_WithAlphaChannel<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBitmap_WithAlphaChannel<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder()); image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(Rgba321010102, PixelTypes.Rgba32)] [WithFile(Rgba321010102, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeBitfields_WithUnusualBitmasks<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBitfields_WithUnusualBitmasks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
// Choosing large tolerance of 6.1 here, because for some reason with the MagickReferenceDecoder the alpha channel // Choosing large tolerance of 6.1 here, because for some reason with the MagickReferenceDecoder the alpha channel
@ -336,7 +307,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
// Exporting the image as PNG with GIMP yields to the same result as the ImageSharp implementation. // Exporting the image as PNG with GIMP yields to the same result as the ImageSharp implementation.
image.CompareToOriginal(provider, ImageComparer.TolerantPercentage(6.1f), new MagickReferenceDecoder()); image.CompareToOriginal(provider, ImageComparer.TolerantPercentage(6.1f), new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(WinBmpv2, PixelTypes.Rgba32)] [WithFile(WinBmpv2, PixelTypes.Rgba32)]
@ -344,38 +314,32 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBmpv2<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBmpv2<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
// Do not validate. Reference files will fail validation. // Do not validate. Reference files will fail validation.
image.CompareToOriginal(provider, new MagickReferenceDecoder(false)); image.CompareToOriginal(provider, new MagickReferenceDecoder(false));
} }
}
[Theory] [Theory]
[WithFile(WinBmpv3, PixelTypes.Rgba32)] [WithFile(WinBmpv3, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeBmpv3<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBmpv3<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(LessThanFullSizedPalette, PixelTypes.Rgba32)] [WithFile(LessThanFullSizedPalette, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeLessThanFullPalette<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeLessThanFullPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder()); image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(OversizedPalette, PixelTypes.Rgba32)] [WithFile(OversizedPalette, PixelTypes.Rgba32)]
@ -383,78 +347,66 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeOversizedPalette<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeOversizedPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
if (TestEnvironment.IsWindows) if (TestEnvironment.IsWindows)
{ {
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
} }
}
[Theory] [Theory]
[WithFile(InvalidPaletteSize, PixelTypes.Rgba32)] [WithFile(InvalidPaletteSize, PixelTypes.Rgba32)]
public void BmpDecoder_ThrowsInvalidImageContentException_OnInvalidPaletteSize<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_ThrowsInvalidImageContentException_OnInvalidPaletteSize<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => Assert.Throws<InvalidImageContentException>(() =>
Assert.Throws<InvalidImageContentException>(() =>
{ {
using (provider.GetImage(BmpDecoder)) using (provider.GetImage(BmpDecoder))
{ {
} }
}); });
}
[Theory] [Theory]
[WithFile(Rgb24jpeg, PixelTypes.Rgba32)] [WithFile(Rgb24jpeg, PixelTypes.Rgba32)]
[WithFile(Rgb24png, PixelTypes.Rgba32)] [WithFile(Rgb24png, PixelTypes.Rgba32)]
public void BmpDecoder_ThrowsNotSupportedException_OnUnsupportedBitmaps<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_ThrowsNotSupportedException_OnUnsupportedBitmaps<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => Assert.Throws<NotSupportedException>(() =>
Assert.Throws<NotSupportedException>(() =>
{ {
using (provider.GetImage(BmpDecoder)) using (provider.GetImage(BmpDecoder))
{ {
} }
}); });
}
[Theory] [Theory]
[WithFile(Rgb32h52AdobeV3, PixelTypes.Rgba32)] [WithFile(Rgb32h52AdobeV3, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeAdobeBmpv3<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeAdobeBmpv3<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder()); image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(Rgba32bf56AdobeV3, PixelTypes.Rgba32)] [WithFile(Rgba32bf56AdobeV3, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeAdobeBmpv3_WithAlpha<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeAdobeBmpv3_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder()); image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(WinBmpv4, PixelTypes.Rgba32)] [WithFile(WinBmpv4, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeBmpv4<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBmpv4<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(WinBmpv5, PixelTypes.Rgba32)] [WithFile(WinBmpv5, PixelTypes.Rgba32)]
@ -462,48 +414,40 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBmpv5<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecodeBmpv5<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Pal8Offset, PixelTypes.Rgba32)] [WithFile(Pal8Offset, PixelTypes.Rgba32)]
public void BmpDecoder_RespectsFileHeaderOffset<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_RespectsFileHeaderOffset<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(F, CommonNonDefaultPixelTypes)] [WithFile(F, CommonNonDefaultPixelTypes)]
public void BmpDecoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Bit8Palette4, PixelTypes.Rgba32)] [WithFile(Bit8Palette4, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode4BytePerEntryPalette<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode4BytePerEntryPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[InlineData(Bit32Rgb, 32)] [InlineData(Bit32Rgb, 32)]
@ -521,13 +465,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Identify_DetectsCorrectPixelType(string imagePath, int expectedPixelSize) public void Identify_DetectsCorrectPixelType(string imagePath, int expectedPixelSize)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
IImageInfo imageInfo = Image.Identify(stream); IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo); Assert.NotNull(imageInfo);
Assert.Equal(expectedPixelSize, imageInfo.PixelType?.BitsPerPixel); Assert.Equal(expectedPixelSize, imageInfo.PixelType?.BitsPerPixel);
} }
}
[Theory] [Theory]
[InlineData(Bit32Rgb, 127, 64)] [InlineData(Bit32Rgb, 127, 64)]
@ -541,54 +483,45 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Identify_DetectsCorrectWidthAndHeight(string imagePath, int expectedWidth, int expectedHeight) public void Identify_DetectsCorrectWidthAndHeight(string imagePath, int expectedWidth, int expectedHeight)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
IImageInfo imageInfo = Image.Identify(stream); IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo); Assert.NotNull(imageInfo);
Assert.Equal(expectedWidth, imageInfo.Width); Assert.Equal(expectedWidth, imageInfo.Width);
Assert.Equal(expectedHeight, imageInfo.Height); Assert.Equal(expectedHeight, imageInfo.Height);
} }
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new BmpDecoder(); var decoder = new BmpDecoder();
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, stream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
{
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
}
[Theory] [Theory]
[WithFile(Os2v2Short, PixelTypes.Rgba32)] [WithFile(Os2v2Short, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_Os2v2XShortHeader<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_Os2v2XShortHeader<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
// TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file. // TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file.
// image.CompareToOriginal(provider); // image.CompareToOriginal(provider);
} }
}
[Theory] [Theory]
[WithFile(Os2v2, PixelTypes.Rgba32)] [WithFile(Os2v2, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_Os2v2Header<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_Os2v2Header<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
// TODO: System.Drawing can not decode this image. MagickReferenceDecoder can decode it, // TODO: System.Drawing can not decode this image. MagickReferenceDecoder can decode it,
@ -596,7 +529,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
// The results are the same as the image sharp implementation. // The results are the same as the image sharp implementation.
// image.CompareToOriginal(provider, new MagickReferenceDecoder()); // image.CompareToOriginal(provider, new MagickReferenceDecoder());
} }
}
[Theory] [Theory]
[WithFile(Os2BitmapArray, PixelTypes.Rgba32)] [WithFile(Os2BitmapArray, PixelTypes.Rgba32)]
@ -611,13 +543,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_Os2BitmapArray<TPixel>(TestImageProvider<TPixel> provider) public void BmpDecoder_CanDecode_Os2BitmapArray<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(BmpDecoder)) using Image<TPixel> image = provider.GetImage(BmpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
// TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file. // TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file.
// image.CompareToOriginal(provider); // image.CompareToOriginal(provider);
} }
} }
}
} }

60
tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs

@ -53,23 +53,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
var options = new BmpEncoder(); var options = new BmpEncoder();
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image()) using Image<Rgba32> input = testFile.CreateRgba32Image();
{ using var memStream = new MemoryStream();
using (var memStream = new MemoryStream())
{
input.Save(memStream, options); input.Save(memStream, options);
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
ImageMetadata meta = output.Metadata; ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
}
}
[Theory] [Theory]
[MemberData(nameof(BmpBitsPerPixelFiles))] [MemberData(nameof(BmpBitsPerPixelFiles))]
@ -78,22 +72,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
var options = new BmpEncoder(); var options = new BmpEncoder();
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image()) using Image<Rgba32> input = testFile.CreateRgba32Image();
{ using var memStream = new MemoryStream();
using (var memStream = new MemoryStream())
{
input.Save(memStream, options); input.Save(memStream, options);
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
BmpMetadata meta = output.Metadata.GetBmpMetadata(); BmpMetadata meta = output.Metadata.GetBmpMetadata();
Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel); Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel);
} }
}
}
}
[Theory] [Theory]
[WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)] [WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)]
@ -237,20 +225,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
return; return;
} }
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
var encoder = new BmpEncoder var encoder = new BmpEncoder
{ {
BitsPerPixel = BmpBitsPerPixel.Pixel8, BitsPerPixel = BmpBitsPerPixel.Pixel8,
Quantizer = new WuQuantizer() Quantizer = new WuQuantizer()
}; };
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false);
// Use the default decoder to test our encoded image. This verifies the content. // Use the default decoder to test our encoded image. This verifies the content.
// We do not verify the reference image though as some are invalid. // We do not verify the reference image though as some are invalid.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder)) using FileStream stream = File.OpenRead(actualOutputFile);
{ using Image<TPixel> referenceImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
referenceImage.CompareToReferenceOutput( referenceImage.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.01f), ImageComparer.TolerantPercentage(0.01f),
provider, provider,
@ -258,8 +246,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
appendPixelTypeToFileName: false, appendPixelTypeToFileName: false,
decoder: new MagickReferenceDecoder(false)); decoder: new MagickReferenceDecoder(false));
} }
}
}
[Theory] [Theory]
[WithFile(Bit32Rgb, PixelTypes.Rgba32)] [WithFile(Bit32Rgb, PixelTypes.Rgba32)]
@ -271,8 +257,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
return; return;
} }
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
var encoder = new BmpEncoder var encoder = new BmpEncoder
{ {
BitsPerPixel = BmpBitsPerPixel.Pixel8, BitsPerPixel = BmpBitsPerPixel.Pixel8,
@ -283,8 +268,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
// Use the default decoder to test our encoded image. This verifies the content. // Use the default decoder to test our encoded image. This verifies the content.
// We do not verify the reference image though as some are invalid. // We do not verify the reference image though as some are invalid.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder)) using FileStream stream = File.OpenRead(actualOutputFile);
{ using Image<TPixel> referenceImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
referenceImage.CompareToReferenceOutput( referenceImage.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.01f), ImageComparer.TolerantPercentage(0.01f),
provider, provider,
@ -292,8 +277,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
appendPixelTypeToFileName: false, appendPixelTypeToFileName: false,
decoder: new MagickReferenceDecoder(false)); decoder: new MagickReferenceDecoder(false));
} }
}
}
[Theory] [Theory]
[WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]
@ -306,27 +289,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider) public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> input = provider.GetImage(new BmpDecoder())) using Image<TPixel> input = provider.GetImage(new BmpDecoder(), new());
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile; ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray(); byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
input.Save(memStream, new BmpEncoder()); input.Save(memStream, new BmpEncoder());
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile; ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray(); byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile); Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes); Assert.Equal(expectedProfileBytes, actualProfileBytes);
} }
}
}
}
[Theory] [Theory]
[WithFile(Car, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] [WithFile(Car, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]
@ -346,8 +323,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
ImageComparer customComparer = null) ImageComparer customComparer = null)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
// There is no alpha in bmp with less then 32 bits per pixels, so the reference image will be made opaque. // There is no alpha in bmp with less then 32 bits per pixels, so the reference image will be made opaque.
if (bitsPerPixel != BmpBitsPerPixel.Pixel32) if (bitsPerPixel != BmpBitsPerPixel.Pixel32)
{ {
@ -365,5 +342,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, customComparer); image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, customComparer);
} }
} }
}
} }

34
tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs

@ -45,13 +45,11 @@ namespace SixLabors.ImageSharp.Tests.Formats
public void ResolutionShouldChange<TPixel>(TestImageProvider<TPixel> provider) public void ResolutionShouldChange<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
image.Metadata.VerticalResolution = 150; image.Metadata.VerticalResolution = 150;
image.Metadata.HorizontalResolution = 150; image.Metadata.HorizontalResolution = 150;
image.DebugSave(provider); image.DebugSave(provider);
} }
}
[Fact] [Fact]
public void ImageCanEncodeToString() public void ImageCanEncodeToString()
@ -60,13 +58,11 @@ namespace SixLabors.ImageSharp.Tests.Formats
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
using (Image<Rgba32> image = file.CreateRgba32Image()) using Image<Rgba32> image = file.CreateRgba32Image();
{
string filename = Path.Combine(path, $"{file.FileNameWithoutExtension}.txt"); string filename = Path.Combine(path, $"{file.FileNameWithoutExtension}.txt");
File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance)); File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance));
} }
} }
}
[Fact] [Fact]
public void DecodeThenEncodeImageFromStreamShouldSucceed() public void DecodeThenEncodeImageFromStreamShouldSucceed()
@ -75,12 +71,10 @@ namespace SixLabors.ImageSharp.Tests.Formats
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
using (Image<Rgba32> image = file.CreateRgba32Image()) using Image<Rgba32> image = file.CreateRgba32Image();
{
image.Save(Path.Combine(path, file.FileName)); image.Save(Path.Combine(path, file.FileName));
} }
} }
}
public static readonly TheoryData<string> QuantizerNames = public static readonly TheoryData<string> QuantizerNames =
new() new()
@ -120,8 +114,7 @@ namespace SixLabors.ImageSharp.Tests.Formats
foreach (TestFile file in Files) foreach (TestFile file in Files)
{ {
using (Image<Rgba32> image = file.CreateRgba32Image()) using Image<Rgba32> image = file.CreateRgba32Image();
{
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.bmp"))) using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.bmp")))
{ {
image.SaveAsBmp(output); image.SaveAsBmp(output);
@ -158,7 +151,6 @@ namespace SixLabors.ImageSharp.Tests.Formats
} }
} }
} }
}
[Fact] [Fact]
public void ImageShouldPreservePixelByteOrderWhenSerialized() public void ImageShouldPreservePixelByteOrderWhenSerialized()
@ -176,12 +168,10 @@ namespace SixLabors.ImageSharp.Tests.Formats
serialized = memoryStream.ToArray(); serialized = memoryStream.ToArray();
} }
using (var image2 = Image.Load<Rgba32>(serialized)) using var image2 = Image.Load<Rgba32>(serialized);
{
image2.Save($"{path}{Path.DirectorySeparatorChar}{file.FileName}"); image2.Save($"{path}{Path.DirectorySeparatorChar}{file.FileName}");
} }
} }
}
[Theory] [Theory]
[InlineData(10, 10, "pbm")] [InlineData(10, 10, "pbm")]
@ -213,10 +203,8 @@ namespace SixLabors.ImageSharp.Tests.Formats
public void CanIdentifyImageLoadedFromBytes(int width, int height, string extension) public void CanIdentifyImageLoadedFromBytes(int width, int height, string extension)
{ {
using (var image = Image.LoadPixelData(new Rgba32[width * height], width, height)) using var image = Image.LoadPixelData<Rgba32>(new Rgba32[width * height], width, height);
{ using var memoryStream = new MemoryStream();
using (var memoryStream = new MemoryStream())
{
IImageFormat format = GetFormat(extension); IImageFormat format = GetFormat(extension);
image.Save(memoryStream, format); image.Save(memoryStream, format);
memoryStream.Position = 0; memoryStream.Position = 0;
@ -231,22 +219,18 @@ namespace SixLabors.ImageSharp.Tests.Formats
Assert.Equal(format, detectedFormat); Assert.Equal(format, detectedFormat);
} }
}
}
[Fact] [Fact]
public void IdentifyReturnsNullWithInvalidStream() public void IdentifyReturnsNullWithInvalidStream()
{ {
var invalid = new byte[10]; byte[] invalid = new byte[10];
using (var memoryStream = new MemoryStream(invalid)) using var memoryStream = new MemoryStream(invalid);
{
IImageInfo imageInfo = Image.Identify(memoryStream, out IImageFormat format); IImageInfo imageInfo = Image.Identify(memoryStream, out IImageFormat format);
Assert.Null(imageInfo); Assert.Null(imageInfo);
Assert.Null(format); Assert.Null(format);
} }
}
private static IImageFormat GetFormat(string format) private static IImageFormat GetFormat(string format)
=> Configuration.Default.ImageFormats => Configuration.Default.ImageFormats

47
tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

@ -4,7 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using Microsoft.DotNet.RemoteExecutor; using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
@ -35,12 +35,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
public void Decode_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider) public void Decode_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
image.DebugSaveMultiFrame(provider); image.DebugSaveMultiFrame(provider);
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact);
} }
}
[Fact] [Fact]
public unsafe void Decode_NonTerminatedFinalFrame() public unsafe void Decode_NonTerminatedFinalFrame()
@ -51,27 +49,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
fixed (byte* data = testFile.Bytes.AsSpan(0, length)) fixed (byte* data = testFile.Bytes.AsSpan(0, length))
{ {
using (var stream = new UnmanagedMemoryStream(data, length)) using var stream = new UnmanagedMemoryStream(data, length);
{ using Image<Rgba32> image = GifDecoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
using (Image<Rgba32> image = GifDecoder.Decode<Rgba32>(Configuration.Default, stream, default))
{
Assert.Equal((200, 200), (image.Width, image.Height)); Assert.Equal((200, 200), (image.Width, image.Height));
} }
} }
}
}
[Theory] [Theory]
[WithFile(TestImages.Gif.Trans, TestPixelTypes)] [WithFile(TestImages.Gif.Trans, TestPixelTypes)]
public void GifDecoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider) public void GifDecoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider); image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Gif.Cheers, PixelTypes.Rgba32, 93)] [WithFile(TestImages.Gif.Cheers, PixelTypes.Rgba32, 93)]
@ -80,35 +72,30 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
public void Decode_VerifyRootFrameAndFrameCount<TPixel>(TestImageProvider<TPixel> provider, int expectedFrameCount) public void Decode_VerifyRootFrameAndFrameCount<TPixel>(TestImageProvider<TPixel> provider, int expectedFrameCount)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
Assert.Equal(expectedFrameCount, image.Frames.Count); Assert.Equal(expectedFrameCount, image.Frames.Count);
image.DebugSave(provider); image.DebugSave(provider);
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider); image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)]
public void CanDecodeJustOneFrame<TPixel>(TestImageProvider<TPixel> provider) public void CanDecodeJustOneFrame<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new GifDecoder { DecodingMode = FrameDecodingMode.First })) DecoderOptions options = new() { MaxFrames = 1 };
{ using Image<TPixel> image = provider.GetImage(new GifDecoder(), options);
Assert.Equal(1, image.Frames.Count); Assert.Equal(1, image.Frames.Count);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)]
public void CanDecodeAllFrames<TPixel>(TestImageProvider<TPixel> provider) public void CanDecodeAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new GifDecoder { DecodingMode = FrameDecodingMode.All })) using Image<TPixel> image = provider.GetImage(new GifDecoder());
{
Assert.True(image.Frames.Count > 1); Assert.True(image.Frames.Count > 1);
} }
}
[Theory] [Theory]
[InlineData(TestImages.Gif.Cheers, 8)] [InlineData(TestImages.Gif.Cheers, 8)]
@ -118,11 +105,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
public void DetectPixelSize(string imagePath, int expectedPixelSize) public void DetectPixelSize(string imagePath, int expectedPixelSize)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel); Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Gif.ZeroSize, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.ZeroSize, PixelTypes.Rgba32)]
@ -146,12 +131,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
public void Decode_WithMaxDimensions_Works<TPixel>(TestImageProvider<TPixel> provider, int expectedWidth, int expectedHeight) public void Decode_WithMaxDimensions_Works<TPixel>(TestImageProvider<TPixel> provider, int expectedWidth, int expectedHeight)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(GifDecoder)) using Image<TPixel> image = provider.GetImage(GifDecoder);
{
Assert.Equal(expectedWidth, image.Width); Assert.Equal(expectedWidth, image.Width);
Assert.Equal(expectedHeight, image.Height); Assert.Equal(expectedHeight, image.Height);
} }
}
[Fact] [Fact]
public void CanDecodeIntermingledImages() public void CanDecodeIntermingledImages()
@ -190,13 +173,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
public void Issue405_BadApplicationExtensionBlockLength<TPixel>(TestImageProvider<TPixel> provider) public void Issue405_BadApplicationExtensionBlockLength<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider); image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
} }
}
// https://github.com/SixLabors/ImageSharp/issues/1668 // https://github.com/SixLabors/ImageSharp/issues/1668
[Theory] [Theory]
@ -204,13 +185,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
public void Issue1668_InvalidColorIndex<TPixel>(TestImageProvider<TPixel> provider) public void Issue1668_InvalidColorIndex<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider); image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)]

61
tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs

@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -58,52 +59,40 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
[Fact] [Fact]
public void Decode_IgnoreMetadataIsFalse_CommentsAreRead() public void Decode_IgnoreMetadataIsFalse_CommentsAreRead()
{ {
var options = new GifDecoder
{
IgnoreMetadata = false
};
var testFile = TestFile.Create(TestImages.Gif.Rings); var testFile = TestFile.Create(TestImages.Gif.Rings);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options)) using Image<Rgba32> image = testFile.CreateRgba32Image(new GifDecoder());
{
GifMetadata metadata = image.Metadata.GetGifMetadata(); GifMetadata metadata = image.Metadata.GetGifMetadata();
Assert.Equal(1, metadata.Comments.Count); Assert.Equal(1, metadata.Comments.Count);
Assert.Equal("ImageSharp", metadata.Comments[0]); Assert.Equal("ImageSharp", metadata.Comments[0]);
} }
}
[Fact] [Fact]
public void Decode_IgnoreMetadataIsTrue_CommentsAreIgnored() public void Decode_IgnoreMetadataIsTrue_CommentsAreIgnored()
{ {
var options = new GifDecoder DecoderOptions options = new()
{ {
IgnoreMetadata = true SkipMetadata = true
}; };
var testFile = TestFile.Create(TestImages.Gif.Rings); var testFile = TestFile.Create(TestImages.Gif.Rings);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options)) using Image<Rgba32> image = testFile.CreateRgba32Image(new GifDecoder(), options);
{
GifMetadata metadata = image.Metadata.GetGifMetadata(); GifMetadata metadata = image.Metadata.GetGifMetadata();
Assert.Equal(0, metadata.Comments.Count); Assert.Equal(0, metadata.Comments.Count);
} }
}
[Fact] [Fact]
public void Decode_CanDecodeLargeTextComment() public void Decode_CanDecodeLargeTextComment()
{ {
var options = new GifDecoder();
var testFile = TestFile.Create(TestImages.Gif.LargeComment); var testFile = TestFile.Create(TestImages.Gif.LargeComment);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options)) using Image<Rgba32> image = testFile.CreateRgba32Image(new GifDecoder());
{
GifMetadata metadata = image.Metadata.GetGifMetadata(); GifMetadata metadata = image.Metadata.GetGifMetadata();
Assert.Equal(2, metadata.Comments.Count); Assert.Equal(2, metadata.Comments.Count);
Assert.Equal(new string('c', 349), metadata.Comments[0]); Assert.Equal(new string('c', 349), metadata.Comments[0]);
Assert.Equal("ImageSharp", metadata.Comments[1]); Assert.Equal("ImageSharp", metadata.Comments[1]);
} }
}
[Fact] [Fact]
public void Encode_PreservesTextData() public void Encode_PreservesTextData()
@ -111,84 +100,68 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
var decoder = new GifDecoder(); var decoder = new GifDecoder();
var testFile = TestFile.Create(TestImages.Gif.LargeComment); var testFile = TestFile.Create(TestImages.Gif.LargeComment);
using (Image<Rgba32> input = testFile.CreateRgba32Image(decoder)) using Image<Rgba32> input = testFile.CreateRgba32Image(decoder);
using (var memoryStream = new MemoryStream()) using var memoryStream = new MemoryStream();
{
input.Save(memoryStream, new GifEncoder()); input.Save(memoryStream, new GifEncoder());
memoryStream.Position = 0; memoryStream.Position = 0;
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, memoryStream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, memoryStream, default);
{
GifMetadata metadata = image.Metadata.GetGifMetadata(); GifMetadata metadata = image.Metadata.GetGifMetadata();
Assert.Equal(2, metadata.Comments.Count); Assert.Equal(2, metadata.Comments.Count);
Assert.Equal(new string('c', 349), metadata.Comments[0]); Assert.Equal(new string('c', 349), metadata.Comments[0]);
Assert.Equal("ImageSharp", metadata.Comments[1]); Assert.Equal("ImageSharp", metadata.Comments[1]);
} }
}
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new GifDecoder(); var decoder = new GifDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default); IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new GifDecoder(); var decoder = new GifDecoder();
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, stream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
{
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
}
[Theory] [Theory]
[MemberData(nameof(RepeatFiles))] [MemberData(nameof(RepeatFiles))]
public void Identify_VerifyRepeatCount(string imagePath, uint repeatCount) public void Identify_VerifyRepeatCount(string imagePath, uint repeatCount)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new GifDecoder(); var decoder = new GifDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default); IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
GifMetadata meta = image.Metadata.GetGifMetadata(); GifMetadata meta = image.Metadata.GetGifMetadata();
Assert.Equal(repeatCount, meta.RepeatCount); Assert.Equal(repeatCount, meta.RepeatCount);
} }
}
[Theory] [Theory]
[MemberData(nameof(RepeatFiles))] [MemberData(nameof(RepeatFiles))]
public void Decode_VerifyRepeatCount(string imagePath, uint repeatCount) public void Decode_VerifyRepeatCount(string imagePath, uint repeatCount)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new GifDecoder(); var decoder = new GifDecoder();
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, stream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
{
GifMetadata meta = image.Metadata.GetGifMetadata(); GifMetadata meta = image.Metadata.GetGifMetadata();
Assert.Equal(repeatCount, meta.RepeatCount); Assert.Equal(repeatCount, meta.RepeatCount);
} }
} }
}
}
} }

58
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs

@ -80,63 +80,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new JpegDecoder(); var decoder = new JpegDecoder();
using (Image image = decoder.Decode(Configuration.Default, stream, default)) using Image image = decoder.Decode(DecoderOptions.Default, stream, default);
{
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new JpegDecoder(); var decoder = new JpegDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default); IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
[Theory] [Theory]
[MemberData(nameof(QualityFiles))] [MemberData(nameof(QualityFiles))]
public void Identify_VerifyQuality(string imagePath, int quality) public void Identify_VerifyQuality(string imagePath, int quality)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new JpegDecoder(); var decoder = new JpegDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default); IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata(); JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality); Assert.Equal(quality, meta.Quality);
} }
}
[Theory] [Theory]
[MemberData(nameof(QualityFiles))] [MemberData(nameof(QualityFiles))]
public void Decode_VerifyQuality(string imagePath, int quality) public void Decode_VerifyQuality(string imagePath, int quality)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{ using Image image = JpegDecoder.Decode(DecoderOptions.Default, stream, default);
using (Image image = JpegDecoder.Decode(Configuration.Default, stream, default))
{
JpegMetadata meta = image.Metadata.GetJpegMetadata(); JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality); Assert.Equal(quality, meta.Quality);
} }
}
}
[Theory] [Theory]
[InlineData(TestImages.Jpeg.Baseline.Floorplan, JpegColorType.Luminance)] [InlineData(TestImages.Jpeg.Baseline.Floorplan, JpegColorType.Luminance)]
@ -150,13 +138,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Identify_DetectsCorrectColorType(string imagePath, JpegColorType expectedColorType) public void Identify_DetectsCorrectColorType(string imagePath, JpegColorType expectedColorType)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{ IImageInfo image = JpegDecoder.Identify(DecoderOptions.Default, stream, default);
IImageInfo image = JpegDecoder.Identify(Configuration.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata(); JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType); Assert.Equal(expectedColorType, meta.ColorType);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Jpeg.Baseline.Floorplan, PixelTypes.Rgb24, JpegColorType.Luminance)] [WithFile(TestImages.Jpeg.Baseline.Floorplan, PixelTypes.Rgb24, JpegColorType.Luminance)]
@ -167,30 +153,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Decode_DetectsCorrectColorType<TPixel>(TestImageProvider<TPixel> provider, JpegColorType expectedColorType) public void Decode_DetectsCorrectColorType<TPixel>(TestImageProvider<TPixel> provider, JpegColorType expectedColorType)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(JpegDecoder)) using Image<TPixel> image = provider.GetImage(JpegDecoder);
{
JpegMetadata meta = image.Metadata.GetJpegMetadata(); JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType); Assert.Equal(expectedColorType, meta.ColorType);
} }
}
private static void TestImageInfo(string imagePath, IImageDecoder decoder, bool useIdentify, Action<IImageInfo> test) private static void TestImageInfo(string imagePath, IImageDecoder decoder, bool useIdentify, Action<IImageInfo> test)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
if (useIdentify) if (useIdentify)
{ {
IImageInfo imageInfo = ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream, default); IImageInfo imageInfo = ((IImageInfoDetector)decoder).Identify(DecoderOptions.Default, stream, default);
test(imageInfo); test(imageInfo);
} }
else else
{ {
using var img = decoder.Decode<Rgba32>(Configuration.Default, stream, default); using Image<Rgba32> img = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
test(img); test(img);
} }
} }
}
private static void TestMetadataImpl( private static void TestMetadataImpl(
bool useIdentify, bool useIdentify,
@ -248,13 +230,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(true)] [InlineData(true)]
public void IgnoreMetadata_ControlsWhetherMetadataIsParsed(bool ignoreMetadata) public void IgnoreMetadata_ControlsWhetherMetadataIsParsed(bool ignoreMetadata)
{ {
var decoder = new JpegDecoder { IgnoreMetadata = ignoreMetadata }; DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
// Snake.jpg has both Exif and ICC profiles defined: // Snake.jpg has both Exif and ICC profiles defined:
var testFile = TestFile.Create(TestImages.Jpeg.Baseline.Snake); var testFile = TestFile.Create(TestImages.Jpeg.Baseline.Snake);
using (Image<Rgba32> image = testFile.CreateRgba32Image(decoder)) using Image<Rgba32> image = testFile.CreateRgba32Image(JpegDecoder, options);
{
if (ignoreMetadata) if (ignoreMetadata)
{ {
Assert.Null(image.Metadata.ExifProfile); Assert.Null(image.Metadata.ExifProfile);
@ -266,7 +247,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.NotNull(image.Metadata.IccProfile); Assert.NotNull(image.Metadata.IccProfile);
} }
} }
}
[Theory] [Theory]
[InlineData(false)] [InlineData(false)]
@ -314,7 +294,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Exception ex = Record.Exception(() => Exception ex = Record.Exception(() =>
{ {
using Image<TPixel> image = provider.GetImage(JpegDecoder); using Image<TPixel> image = provider.GetImage(JpegDecoder);
var clone = image.Metadata.ExifProfile.DeepClone(); ExifProfile clone = image.Metadata.ExifProfile.DeepClone();
}); });
Assert.Null(ex); Assert.Null(ex);
} }
@ -357,12 +337,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void EncodedStringTags_Read() public void EncodedStringTags_Read()
{ {
using (var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora_EncodedStrings))) using var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora_EncodedStrings));
{
ExifProfile exif = image.Metadata.ExifProfile; ExifProfile exif = image.Metadata.ExifProfile;
VerifyEncodedStrings(exif); VerifyEncodedStrings(exif);
} }
}
private static void VerifyEncodedStrings(ExifProfile exif) private static void VerifyEncodedStrings(ExifProfile exif)
{ {

82
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -6,6 +6,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
@ -73,10 +74,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void ParseStream_BasicPropertiesAreCorrect() public void ParseStream_BasicPropertiesAreCorrect()
{ {
JpegDecoderOptions options = new();
byte[] bytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes; byte[] bytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes;
using var ms = new MemoryStream(bytes); using var ms = new MemoryStream(bytes);
using var bufferedStream = new BufferedReadStream(Configuration.Default, ms); using var bufferedStream = new BufferedReadStream(Configuration.Default, ms);
using var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); using var decoder = new JpegDecoderCore(options);
using Image<Rgba32> image = decoder.Decode<Rgba32>(bufferedStream, cancellationToken: default); using Image<Rgba32> image = decoder.Decode<Rgba32>(bufferedStream, cancellationToken: default);
// I don't know why these numbers are different. All I know is that the decoder works // I don't know why these numbers are different. All I know is that the decoder works
@ -148,17 +150,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small); string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var pausedStream = new PausedStream(file); using var pausedStream = new PausedStream(file);
pausedStream.OnWaiting(s => pausedStream.OnWaiting(_ =>
{ {
cts.Cancel(); cts.Cancel();
pausedStream.Release(); pausedStream.Release();
}); });
var config = Configuration.CreateDefaultInstance(); var configuration = Configuration.CreateDefaultInstance();
config.FileSystem = new SingleStreamFileSystem(pausedStream); configuration.FileSystem = new SingleStreamFileSystem(pausedStream);
DecoderOptions options = new()
{
Configuration = configuration
};
await Assert.ThrowsAsync<TaskCanceledException>(async () => await Assert.ThrowsAsync<TaskCanceledException>(async () =>
{ {
using Image image = await Image.LoadAsync(config, "someFakeFile", cts.Token); using Image image = await Image.LoadAsync(options, "someFakeFile", cts.Token);
}); });
} }
@ -169,28 +176,30 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small); string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var pausedStream = new PausedStream(file); using var pausedStream = new PausedStream(file);
pausedStream.OnWaiting(s => pausedStream.OnWaiting(_ =>
{ {
cts.Cancel(); cts.Cancel();
pausedStream.Release(); pausedStream.Release();
}); });
var config = Configuration.CreateDefaultInstance(); var configuration = Configuration.CreateDefaultInstance();
config.FileSystem = new SingleStreamFileSystem(pausedStream); configuration.FileSystem = new SingleStreamFileSystem(pausedStream);
DecoderOptions options = new()
{
Configuration = configuration
};
await Assert.ThrowsAsync<TaskCanceledException>(async () => await Image.IdentifyAsync(config, "someFakeFile", cts.Token)); await Assert.ThrowsAsync<TaskCanceledException>(async () => await Image.IdentifyAsync(options, "someFakeFile", cts.Token));
} }
[Theory] [Theory]
[WithFileCollection(nameof(UnsupportedTestJpegs), PixelTypes.Rgba32)] [WithFileCollection(nameof(UnsupportedTestJpegs), PixelTypes.Rgba32)]
public void ThrowsNotSupported_WithUnsupportedJpegs<TPixel>(TestImageProvider<TPixel> provider) public void ThrowsNotSupported_WithUnsupportedJpegs<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => Assert.Throws<NotSupportedException>(() =>
Assert.Throws<NotSupportedException>(() =>
{ {
using Image<TPixel> image = provider.GetImage(JpegDecoder); using Image<TPixel> image = provider.GetImage(JpegDecoder);
}); });
}
// https://github.com/SixLabors/ImageSharp/pull/1732 // https://github.com/SixLabors/ImageSharp/pull/1732
[Theory] [Theory]
@ -198,12 +207,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue1732_DecodesWithRgbColorSpace<TPixel>(TestImageProvider<TPixel> provider) public void Issue1732_DecodesWithRgbColorSpace<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(JpegDecoder)) using Image<TPixel> image = provider.GetImage(JpegDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
// https://github.com/SixLabors/ImageSharp/issues/2057 // https://github.com/SixLabors/ImageSharp/issues/2057
[Theory] [Theory]
@ -211,12 +218,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue2057_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider) public void Issue2057_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(JpegDecoder)) using Image<TPixel> image = provider.GetImage(JpegDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
// https://github.com/SixLabors/ImageSharp/issues/2133 // https://github.com/SixLabors/ImageSharp/issues/2133
[Theory] [Theory]
@ -224,12 +229,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue2133_DeduceColorSpace<TPixel>(TestImageProvider<TPixel> provider) public void Issue2133_DeduceColorSpace<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(JpegDecoder)) using Image<TPixel> image = provider.GetImage(JpegDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
}
// https://github.com/SixLabors/ImageSharp/issues/2133 // https://github.com/SixLabors/ImageSharp/issues/2133
[Theory] [Theory]
@ -237,44 +240,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue2136_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider) public void Issue2136_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(JpegDecoder)) using Image<TPixel> image = provider.GetImage(JpegDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider); image.CompareToOriginal(provider);
} }
} }
// DEBUG ONLY!
// The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm"
// into "\tests\Images\ActualOutput\JpegDecoderTests\"
// [Theory]
// [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32, "PdfJsOriginal_progress.png")]
public void ValidateProgressivePdfJsOutput<TPixel>(
TestImageProvider<TPixel> provider,
string pdfJsOriginalResultImage)
where TPixel : unmanaged, IPixel<TPixel>
{
// tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm
string pdfJsOriginalResultPath = Path.Combine(
provider.Utility.GetTestOutputDir(),
pdfJsOriginalResultImage);
byte[] sourceBytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes;
provider.Utility.TestName = nameof(DecodeProgressiveJpegOutputName);
var comparer = ImageComparer.Tolerant(0, 0);
using (Image<TPixel> expectedImage = provider.GetReferenceOutputImage<TPixel>(appendPixelTypeToFileName: false))
using (var pdfJsOriginalResult = Image.Load<Rgba32>(pdfJsOriginalResultPath))
using (var pdfJsPortResult = Image.Load<Rgba32>(sourceBytes, JpegDecoder))
{
ImageSimilarityReport originalReport = comparer.CompareImagesOrFrames(expectedImage, pdfJsOriginalResult);
ImageSimilarityReport portReport = comparer.CompareImagesOrFrames(expectedImage, pdfJsPortResult);
this.Output.WriteLine($"Difference for PDF.js ORIGINAL: {originalReport.DifferencePercentageString}");
this.Output.WriteLine($"Difference for PORT: {portReport.DifferencePercentageString}");
}
}
}
} }

6
tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

@ -49,8 +49,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
// Calculating data from ImageSharp // Calculating data from ImageSharp
byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes; byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes;
JpegDecoderOptions option = new();
using var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); using var decoder = new JpegDecoderCore(option);
using var ms = new MemoryStream(sourceBytes); using var ms = new MemoryStream(sourceBytes);
using var bufferedStream = new BufferedReadStream(Configuration.Default, ms); using var bufferedStream = new BufferedReadStream(Configuration.Default, ms);
@ -78,8 +79,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// Calculating data from ImageSharp // Calculating data from ImageSharp
byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes; byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes;
JpegDecoderOptions options = new();
using var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); using var decoder = new JpegDecoderCore(options);
using var ms = new MemoryStream(sourceBytes); using var ms = new MemoryStream(sourceBytes);
using var bufferedStream = new BufferedReadStream(Configuration.Default, ms); using var bufferedStream = new BufferedReadStream(Configuration.Default, ms);

9
tests/ImageSharp.Tests/Formats/Jpg/SpectralToPixelConversionTests.cs

@ -40,8 +40,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
using var bufferedStream = new BufferedReadStream(Configuration.Default, ms); using var bufferedStream = new BufferedReadStream(Configuration.Default, ms);
// Decoding // Decoding
JpegDecoderOptions options = new();
using var converter = new SpectralConverter<TPixel>(Configuration.Default); using var converter = new SpectralConverter<TPixel>(Configuration.Default);
using var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); using var decoder = new JpegDecoderCore(options);
var scanDecoder = new HuffmanScanDecoder(bufferedStream, converter, cancellationToken: default); var scanDecoder = new HuffmanScanDecoder(bufferedStream, converter, cancellationToken: default);
decoder.ParseStream(bufferedStream, converter, cancellationToken: default); decoder.ParseStream(bufferedStream, converter, cancellationToken: default);
@ -50,9 +51,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
provider.Utility.TestName = JpegDecoderTests.DecodeBaselineJpegOutputName; provider.Utility.TestName = JpegDecoderTests.DecodeBaselineJpegOutputName;
// Comparison // Comparison
using (var image = new Image<TPixel>(Configuration.Default, converter.GetPixelBuffer(CancellationToken.None), new ImageMetadata())) using var image = new Image<TPixel>(Configuration.Default, converter.GetPixelBuffer(CancellationToken.None), new ImageMetadata());
using (Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(appendPixelTypeToFileName: false)) using Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(appendPixelTypeToFileName: false);
{
ImageSimilarityReport report = ImageComparer.Exact.CompareImagesOrFrames(referenceImage, image); ImageSimilarityReport report = ImageComparer.Exact.CompareImagesOrFrames(referenceImage, image);
this.Output.WriteLine($"*** {provider.SourceFileOrDescription} ***"); this.Output.WriteLine($"*** {provider.SourceFileOrDescription} ***");
@ -62,5 +62,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.True(report.TotalNormalizedDifference.Value < 0.005f); Assert.True(report.TotalNormalizedDifference.Value < 0.005f);
} }
} }
}
} }

11
tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs

@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public static float[] Create8x8FloatData() public static float[] Create8x8FloatData()
{ {
var result = new float[64]; float[] result = new float[64];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public static int[] Create8x8IntData() public static int[] Create8x8IntData()
{ {
var result = new int[64]; int[] result = new int[64];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public static short[] Create8x8ShortData() public static short[] Create8x8ShortData()
{ {
var result = new short[64]; short[] result = new short[64];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
public static int[] Create8x8RandomIntData(int minValue, int maxValue, int seed = 42) public static int[] Create8x8RandomIntData(int minValue, int maxValue, int seed = 42)
{ {
var rnd = new Random(seed); var rnd = new Random(seed);
var result = new int[64]; int[] result = new int[64];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
@ -222,7 +222,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
using var ms = new MemoryStream(bytes); using var ms = new MemoryStream(bytes);
using var bufferedStream = new BufferedReadStream(Configuration.Default, ms); using var bufferedStream = new BufferedReadStream(Configuration.Default, ms);
var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); JpegDecoderOptions options = new();
var decoder = new JpegDecoderCore(options);
if (metaDataOnly) if (metaDataOnly)
{ {
decoder.Identify(bufferedStream, cancellationToken: default); decoder.Identify(bufferedStream, cancellationToken: default);

10
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs

@ -4,6 +4,7 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.IO; using System.IO;
using System.Text; using System.Text;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -75,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
var decoder = new PngDecoder(); var decoder = new PngDecoder();
ImageFormatException exception = ImageFormatException exception =
Assert.Throws<InvalidImageContentException>(() => decoder.Decode<Rgb24>(Configuration.Default, memStream, default)); Assert.Throws<InvalidImageContentException>(() => decoder.Decode<Rgb24>(DecoderOptions.Default, memStream, default));
Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message); Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message);
} }
@ -83,18 +84,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
private static string GetChunkTypeName(uint value) private static string GetChunkTypeName(uint value)
{ {
var data = new byte[4]; byte[] data = new byte[4];
BinaryPrimitives.WriteUInt32BigEndian(data, value); BinaryPrimitives.WriteUInt32BigEndian(data, value);
return Encoding.ASCII.GetString(data); return Encoding.ASCII.GetString(data);
} }
private static void WriteHeaderChunk(MemoryStream memStream) private static void WriteHeaderChunk(MemoryStream memStream) =>
{
// Writes a 1x1 32bit png header chunk containing a single black pixel. // Writes a 1x1 32bit png header chunk containing a single black pixel.
memStream.Write(Raw1X1PngIhdrAndpHYs, 0, Raw1X1PngIhdrAndpHYs.Length); memStream.Write(Raw1X1PngIhdrAndpHYs, 0, Raw1X1PngIhdrAndpHYs.Length);
}
private static void WriteChunk(MemoryStream memStream, string chunkName) private static void WriteChunk(MemoryStream memStream, string chunkName)
{ {

74
tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

@ -111,15 +111,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[WithTestPatternImages(nameof(PngColorTypes), 7, 5, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(PngColorTypes), 7, 5, PixelTypes.Rgba32)]
public void WorksWithDifferentSizes<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType) public void WorksWithDifferentSizes<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => TestPngEncoderCore(
TestPngEncoderCore(
provider, provider,
pngColorType, pngColorType,
PngFilterMethod.Adaptive, PngFilterMethod.Adaptive,
PngBitDepth.Bit8, PngBitDepth.Bit8,
PngInterlaceMode.None, PngInterlaceMode.None,
appendPngColorType: true); appendPngColorType: true);
}
[Theory] [Theory]
[WithTestPatternImages(nameof(PngColorTypes), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)] [WithTestPatternImages(nameof(PngColorTypes), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)]
@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
return; return;
} }
foreach (var filterMethod in PngFilterMethods) foreach (object[] filterMethod in PngFilterMethods)
{ {
foreach (PngInterlaceMode interlaceMode in InterlaceMode) foreach (PngInterlaceMode interlaceMode in InterlaceMode)
{ {
@ -235,7 +233,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void WorksWithAllBitDepthsAndExcludeAllFilter<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth) public void WorksWithAllBitDepthsAndExcludeAllFilter<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
foreach (var filterMethod in PngFilterMethods) foreach (object[] filterMethod in PngFilterMethods)
{ {
foreach (PngInterlaceMode interlaceMode in InterlaceMode) foreach (PngInterlaceMode interlaceMode in InterlaceMode)
{ {
@ -284,21 +282,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void InfersColorTypeAndBitDepth<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth) public void InfersColorTypeAndBitDepth<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Stream stream = new MemoryStream()) using Stream stream = new MemoryStream();
{
PngEncoder.Encode(provider.GetImage(), stream); PngEncoder.Encode(provider.GetImage(), stream);
stream.Seek(0, SeekOrigin.Begin); stream.Seek(0, SeekOrigin.Begin);
var decoder = new PngDecoder(); var decoder = new PngDecoder();
Image image = decoder.Decode(Configuration.Default, stream, default); Image image = decoder.Decode(DecoderOptions.Default, stream, default);
PngMetadata metadata = image.Metadata.GetPngMetadata(); PngMetadata metadata = image.Metadata.GetPngMetadata();
Assert.Equal(pngColorType, metadata.ColorType); Assert.Equal(pngColorType, metadata.ColorType);
Assert.Equal(pngBitDepth, metadata.BitDepth); Assert.Equal(pngBitDepth, metadata.BitDepth);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Png.Palette8Bpp, nameof(PaletteLargeOnly), PixelTypes.Rgba32)] [WithFile(TestImages.Png.Palette8Bpp, nameof(PaletteLargeOnly), PixelTypes.Rgba32)]
@ -329,9 +325,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void WritesFileMarker<TPixel>(TestImageProvider<TPixel> provider) public void WritesFileMarker<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
using (var ms = new MemoryStream()) using var ms = new MemoryStream();
{
image.Save(ms, PngEncoder); image.Save(ms, PngEncoder);
byte[] data = ms.ToArray().Take(8).ToArray(); byte[] data = ms.ToArray().Take(8).ToArray();
@ -349,52 +344,39 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Assert.Equal(expected, data); Assert.Equal(expected, data);
} }
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Encode_PreserveRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Encode_PreserveRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image()) using Image<Rgba32> input = testFile.CreateRgba32Image();
{ using var memStream = new MemoryStream();
using (var memStream = new MemoryStream())
{
input.Save(memStream, PngEncoder); input.Save(memStream, PngEncoder);
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
ImageMetadata meta = output.Metadata; ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
}
}
[Theory] [Theory]
[MemberData(nameof(PngBitDepthFiles))] [MemberData(nameof(PngBitDepthFiles))]
public void Encode_PreserveBits(string imagePath, PngBitDepth pngBitDepth) public void Encode_PreserveBits(string imagePath, PngBitDepth pngBitDepth)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image()) using Image<Rgba32> input = testFile.CreateRgba32Image();
{ using var memStream = new MemoryStream();
using (var memStream = new MemoryStream())
{
input.Save(memStream, PngEncoder); input.Save(memStream, PngEncoder);
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
PngMetadata meta = output.Metadata.GetPngMetadata(); PngMetadata meta = output.Metadata.GetPngMetadata();
Assert.Equal(pngBitDepth, meta.BitDepth); Assert.Equal(pngBitDepth, meta.BitDepth);
} }
}
}
}
[Theory] [Theory]
[InlineData(PngColorType.Palette)] [InlineData(PngColorType.Palette)]
@ -437,9 +419,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
memStream.Position = 0; memStream.Position = 0;
using var actual = Image.Load<Rgba32>(memStream); using var actual = Image.Load<Rgba32>(memStream);
Rgba32 expectedColor = Color.Blue; Rgba32 expectedColor = Color.Blue;
if (colorType == PngColorType.Grayscale || colorType == PngColorType.GrayscaleWithAlpha) if (colorType is PngColorType.Grayscale or PngColorType.GrayscaleWithAlpha)
{ {
var luminance = ColorNumerics.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B); byte luminance = ColorNumerics.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B);
expectedColor = new Rgba32(luminance, luminance, luminance); expectedColor = new Rgba32(luminance, luminance, luminance);
} }
@ -467,17 +449,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Encode_PreserveTrns(string imagePath, PngBitDepth pngBitDepth, PngColorType pngColorType) public void Encode_PreserveTrns(string imagePath, PngBitDepth pngBitDepth, PngColorType pngColorType)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image()) using Image<Rgba32> input = testFile.CreateRgba32Image();
{
PngMetadata inMeta = input.Metadata.GetPngMetadata(); PngMetadata inMeta = input.Metadata.GetPngMetadata();
Assert.True(inMeta.HasTransparency); Assert.True(inMeta.HasTransparency);
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
input.Save(memStream, PngEncoder); input.Save(memStream, PngEncoder);
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
PngMetadata outMeta = output.Metadata.GetPngMetadata(); PngMetadata outMeta = output.Metadata.GetPngMetadata();
Assert.True(outMeta.HasTransparency); Assert.True(outMeta.HasTransparency);
@ -511,9 +490,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
break; break;
} }
} }
}
}
}
[Theory] [Theory]
[WithTestPatternImages(587, 821, PixelTypes.Rgba32)] [WithTestPatternImages(587, 821, PixelTypes.Rgba32)]
@ -591,8 +567,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
PngChunkFilter optimizeMethod = PngChunkFilter.None) PngChunkFilter optimizeMethod = PngChunkFilter.None)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
var encoder = new PngEncoder var encoder = new PngEncoder
{ {
ColorType = pngColorType, ColorType = pngColorType,
@ -621,12 +596,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
// We compare using both our decoder and the reference decoder as pixel transformation // We compare using both our decoder and the reference decoder as pixel transformation
// occurs within the encoder itself leaving the input image unaffected. // occurs within the encoder itself leaving the input image unaffected.
// This means we are benefiting from testing our decoder also. // This means we are benefiting from testing our decoder also.
using (var imageSharpImage = Image.Load<TPixel>(actualOutputFile, new PngDecoder())) using FileStream fileStream = File.OpenRead(actualOutputFile);
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder)) using Image<TPixel> imageSharpImage = new PngDecoder().Decode<TPixel>(DecoderOptions.Default, fileStream, default);
{
fileStream.Position = 0;
using Image<TPixel> referenceImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, fileStream, default);
ImageComparer.Exact.VerifySimilarity(referenceImage, imageSharpImage); ImageComparer.Exact.VerifySimilarity(referenceImage, imageSharpImage);
} }
} }
}
}
} }

102
tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@ -56,12 +57,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decoder_CanReadTextData<TPixel>(TestImageProvider<TPixel> provider) public void Decoder_CanReadTextData<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new PngDecoder())) using Image<TPixel> image = provider.GetImage(new PngDecoder());
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta); VerifyTextDataIsPresent(meta);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)] [WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)]
@ -69,27 +68,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new PngDecoder(); var decoder = new PngDecoder();
using (Image<TPixel> input = provider.GetImage(decoder)) using Image<TPixel> input = provider.GetImage(decoder);
using (var memoryStream = new MemoryStream()) using var memoryStream = new MemoryStream();
{
input.Save(memoryStream, new PngEncoder()); input.Save(memoryStream, new PngEncoder());
memoryStream.Position = 0; memoryStream.Position = 0;
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, memoryStream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, memoryStream, default);
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta); VerifyTextDataIsPresent(meta);
} }
}
}
[Theory] [Theory]
[WithFile(TestImages.Png.InvalidTextData, PixelTypes.Rgba32)] [WithFile(TestImages.Png.InvalidTextData, PixelTypes.Rgba32)]
public void Decoder_IgnoresInvalidTextData<TPixel>(TestImageProvider<TPixel> provider) public void Decoder_IgnoresInvalidTextData<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new PngDecoder())) using Image<TPixel> image = provider.GetImage(new PngDecoder());
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.DoesNotContain(meta.TextData, m => m.Value is "leading space"); Assert.DoesNotContain(meta.TextData, m => m.Value is "leading space");
Assert.DoesNotContain(meta.TextData, m => m.Value is "trailing space"); Assert.DoesNotContain(meta.TextData, m => m.Value is "trailing space");
@ -98,7 +92,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Assert.DoesNotContain(meta.TextData, m => m.Value is "invalid characters"); Assert.DoesNotContain(meta.TextData, m => m.Value is "invalid characters");
Assert.DoesNotContain(meta.TextData, m => m.Value is "too large"); Assert.DoesNotContain(meta.TextData, m => m.Value is "too large");
} }
}
[Theory] [Theory]
[WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)] [WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)]
@ -106,9 +99,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new PngDecoder(); var decoder = new PngDecoder();
using (Image<TPixel> input = provider.GetImage(decoder)) using Image<TPixel> input = provider.GetImage(decoder);
using (var memoryStream = new MemoryStream()) using var memoryStream = new MemoryStream();
{
// This will be a zTXt chunk. // This will be a zTXt chunk.
var expectedText = new PngTextData("large-text", new string('c', 100), string.Empty, string.Empty); var expectedText = new PngTextData("large-text", new string('c', 100), string.Empty, string.Empty);
@ -123,61 +116,55 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
}); });
memoryStream.Position = 0; memoryStream.Position = 0;
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, memoryStream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, memoryStream, default);
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Contains(meta.TextData, m => m.Equals(expectedText)); Assert.Contains(meta.TextData, m => m.Equals(expectedText));
Assert.Contains(meta.TextData, m => m.Equals(expectedTextNoneLatin)); Assert.Contains(meta.TextData, m => m.Equals(expectedTextNoneLatin));
} }
}
}
[Theory] [Theory]
[WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)] [WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)]
public void Decode_ReadsExifData<TPixel>(TestImageProvider<TPixel> provider) public void Decode_ReadsExifData<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new PngDecoder DecoderOptions options = new()
{ {
IgnoreMetadata = false SkipMetadata = false
}; };
using (Image<TPixel> image = provider.GetImage(decoder)) using Image<TPixel> image = provider.GetImage(new PngDecoder(), options);
{
Assert.NotNull(image.Metadata.ExifProfile); Assert.NotNull(image.Metadata.ExifProfile);
ExifProfile exif = image.Metadata.ExifProfile; ExifProfile exif = image.Metadata.ExifProfile;
VerifyExifDataIsPresent(exif); VerifyExifDataIsPresent(exif);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)] [WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)]
public void Decode_IgnoresExifData_WhenIgnoreMetadataIsTrue<TPixel>(TestImageProvider<TPixel> provider) public void Decode_IgnoresExifData_WhenIgnoreMetadataIsTrue<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new PngDecoder DecoderOptions options = new()
{ {
IgnoreMetadata = true SkipMetadata = true
}; };
using (Image<TPixel> image = provider.GetImage(decoder)) PngDecoder decoder = new();
{
using Image<TPixel> image = provider.GetImage(decoder, options);
Assert.Null(image.Metadata.ExifProfile); Assert.Null(image.Metadata.ExifProfile);
} }
}
[Fact] [Fact]
public void Decode_IgnoreMetadataIsFalse_TextChunkIsRead() public void Decode_IgnoreMetadataIsFalse_TextChunkIsRead()
{ {
var options = new PngDecoder DecoderOptions options = new()
{ {
IgnoreMetadata = false SkipMetadata = false
}; };
var testFile = TestFile.Create(TestImages.Png.Blur); var testFile = TestFile.Create(TestImages.Png.Blur);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options)) using Image<Rgba32> image = testFile.CreateRgba32Image(new PngDecoder(), options);
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Equal(1, meta.TextData.Count); Assert.Equal(1, meta.TextData.Count);
@ -185,114 +172,95 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Assert.Equal("paint.net 4.0.6", meta.TextData[0].Value); Assert.Equal("paint.net 4.0.6", meta.TextData[0].Value);
Assert.Equal(0.4545d, meta.Gamma, precision: 4); Assert.Equal(0.4545d, meta.Gamma, precision: 4);
} }
}
[Fact] [Fact]
public void Decode_IgnoreMetadataIsTrue_TextChunksAreIgnored() public void Decode_IgnoreMetadataIsTrue_TextChunksAreIgnored()
{ {
var options = new PngDecoder DecoderOptions options = new()
{ {
IgnoreMetadata = true SkipMetadata = true
}; };
var testFile = TestFile.Create(TestImages.Png.PngWithMetadata); var testFile = TestFile.Create(TestImages.Png.PngWithMetadata);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options)) using Image<Rgba32> image = testFile.CreateRgba32Image(new PngDecoder(), options);
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Equal(0, meta.TextData.Count); Assert.Equal(0, meta.TextData.Count);
} }
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new PngDecoder(); var decoder = new PngDecoder();
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, stream, default)) using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
{
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
}
[Theory] [Theory]
[WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)] [WithFile(TestImages.Png.PngWithMetadata, PixelTypes.Rgba32)]
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider) public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> input = provider.GetImage(new PngDecoder())) using Image<TPixel> input = provider.GetImage(new PngDecoder());
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile; ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray(); byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
input.Save(memStream, new PngEncoder()); input.Save(memStream, new PngEncoder());
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile; ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray(); byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile); Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes); Assert.Equal(expectedProfileBytes, actualProfileBytes);
} }
}
}
}
[Theory] [Theory]
[MemberData(nameof(RatioFiles))] [MemberData(nameof(RatioFiles))]
public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
var decoder = new PngDecoder(); var decoder = new PngDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default); IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata; ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits); Assert.Equal(resolutionUnit, meta.ResolutionUnits);
} }
}
[Theory] [Theory]
[InlineData(TestImages.Png.PngWithMetadata)] [InlineData(TestImages.Png.PngWithMetadata)]
public void Identify_ReadsTextData(string imagePath) public void Identify_ReadsTextData(string imagePath)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
IImageInfo imageInfo = Image.Identify(stream); IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo); Assert.NotNull(imageInfo);
PngMetadata meta = imageInfo.Metadata.GetFormatMetadata(PngFormat.Instance); PngMetadata meta = imageInfo.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta); VerifyTextDataIsPresent(meta);
} }
}
[Theory] [Theory]
[InlineData(TestImages.Png.PngWithMetadata)] [InlineData(TestImages.Png.PngWithMetadata)]
public void Identify_ReadsExifData(string imagePath) public void Identify_ReadsExifData(string imagePath)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
IImageInfo imageInfo = Image.Identify(stream); IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo); Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.Metadata.ExifProfile); Assert.NotNull(imageInfo.Metadata.ExifProfile);
ExifProfile exif = imageInfo.Metadata.ExifProfile; ExifProfile exif = imageInfo.Metadata.ExifProfile;
VerifyExifDataIsPresent(exif); VerifyExifDataIsPresent(exif);
} }
}
private static void VerifyExifDataIsPresent(ExifProfile exif) private static void VerifyExifDataIsPresent(ExifProfile exif)
{ {
@ -323,8 +291,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Identify_ReadsLegacyExifData(string imagePath) public void Identify_ReadsLegacyExifData(string imagePath)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
IImageInfo imageInfo = Image.Identify(stream); IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo); Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.Metadata.ExifProfile); Assert.NotNull(imageInfo.Metadata.ExifProfile);
@ -346,5 +313,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Assert.Equal(42, (int)exif.GetValue(ExifTag.ImageNumber).Value); Assert.Equal(42, (int)exif.GetValue(ExifTag.ImageNumber).Value);
} }
} }
}
} }

23
tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs

@ -2,6 +2,7 @@
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
@ -19,20 +20,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// does saving a file then reopening mean both files are identical??? // does saving a file then reopening mean both files are identical???
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
using (var ms = new MemoryStream()) using var ms = new MemoryStream();
{
// image.Save(provider.Utility.GetTestOutputFileName("bmp")); // image.Save(provider.Utility.GetTestOutputFileName("bmp"));
image.Save(ms, new PngEncoder()); image.Save(ms, new PngEncoder());
ms.Position = 0; ms.Position = 0;
using (var img2 = Image.Load<Rgba32>(ms, new PngDecoder())) using Image<Rgba32> img2 = new PngDecoder().Decode<Rgba32>(DecoderOptions.Default, ms, default);
{
ImageComparer.Tolerant().VerifySimilarity(image, img2); ImageComparer.Tolerant().VerifySimilarity(image, img2);
// img2.Save(provider.Utility.GetTestOutputFileName("bmp", "_loaded"), new BmpEncoder()); // 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 /* JJS: Disabled for now as the decoder now correctly decodes the full pixel components if the
paletted image has alpha of 0 paletted image has alpha of 0
@ -104,20 +102,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// does saving a file then reopening mean both files are identical??? // does saving a file then reopening mean both files are identical???
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
using (var ms = new MemoryStream()) using var ms = new MemoryStream();
{
// image.Save(provider.Utility.GetTestOutputFileName("png")); // image.Save(provider.Utility.GetTestOutputFileName("png"));
image.Mutate(x => x.Resize(100, 100)); image.Mutate(x => x.Resize(100, 100));
// image.Save(provider.Utility.GetTestOutputFileName("png", "resize")); // image.Save(provider.Utility.GetTestOutputFileName("png", "resize"));
image.Save(ms, new PngEncoder()); image.Save(ms, new PngEncoder());
ms.Position = 0; ms.Position = 0;
using (var img2 = Image.Load<Rgba32>(ms, new PngDecoder())) using Image<Rgba32> img2 = new PngDecoder().Decode<Rgba32>(DecoderOptions.Default, ms, default);
{
ImageComparer.Tolerant().VerifySimilarity(image, img2); ImageComparer.Tolerant().VerifySimilarity(image, img2);
} }
} }
}
}
} }

2
tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
Assert.Throws<UnknownImageFormatException>(() => Assert.Throws<UnknownImageFormatException>(() =>
{ {
using (Image.Load(Configuration.Default, stream, out IImageFormat _)) using (Image.Load(DecoderOptions.Default, stream, out IImageFormat _))
{ {
} }
}); });

6
tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

@ -4,6 +4,7 @@
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
using System; using System;
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -635,11 +636,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void CanDecodeJustOneFrame<TPixel>(TestImageProvider<TPixel> provider) public void CanDecodeJustOneFrame<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new TiffDecoder() { DecodingMode = FrameDecodingMode.First })) DecoderOptions options = new() { MaxFrames = 1 };
{ using Image<TPixel> image = provider.GetImage(new TiffDecoder(), options);
Assert.Equal(1, image.Frames.Count); Assert.Equal(1, image.Frames.Count);
} }
}
[Theory] [Theory]
[WithFile(RgbJpegCompressed, PixelTypes.Rgba32)] [WithFile(RgbJpegCompressed, PixelTypes.Rgba32)]

22
tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
@ -50,8 +51,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void TiffFrameMetadata_CloneIsDeep<TPixel>(TestImageProvider<TPixel> provider) public void TiffFrameMetadata_CloneIsDeep<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(TiffDecoder)) using Image<TPixel> image = provider.GetImage(TiffDecoder);
{
TiffFrameMetadata meta = image.Frames.RootFrame.Metadata.GetTiffMetadata(); TiffFrameMetadata meta = image.Frames.RootFrame.Metadata.GetTiffMetadata();
var cloneSameAsSampleMetaData = (TiffFrameMetadata)meta.DeepClone(); var cloneSameAsSampleMetaData = (TiffFrameMetadata)meta.DeepClone();
VerifyExpectedTiffFrameMetaDataIsPresent(cloneSameAsSampleMetaData); VerifyExpectedTiffFrameMetaDataIsPresent(cloneSameAsSampleMetaData);
@ -68,7 +68,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.False(meta.PhotometricInterpretation == clone.PhotometricInterpretation); Assert.False(meta.PhotometricInterpretation == clone.PhotometricInterpretation);
Assert.False(meta.Predictor == clone.Predictor); Assert.False(meta.Predictor == clone.Predictor);
} }
}
private static void VerifyExpectedTiffFrameMetaDataIsPresent(TiffFrameMetadata frameMetaData) private static void VerifyExpectedTiffFrameMetaDataIsPresent(TiffFrameMetadata frameMetaData)
{ {
@ -119,10 +118,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void MetadataProfiles<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata) public void MetadataProfiles<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new TiffDecoder() { IgnoreMetadata = ignoreMetadata })) DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
{ using Image<TPixel> image = provider.GetImage(new TiffDecoder(), options);
TiffMetadata meta = image.Metadata.GetTiffMetadata(); TiffMetadata meta = image.Metadata.GetTiffMetadata();
ImageFrameMetadata rootFrameMetaData = image.Frames.RootFrame.Metadata; ImageFrameMetadata rootFrameMetaData = image.Frames.RootFrame.Metadata;
Assert.NotNull(meta); Assert.NotNull(meta);
if (ignoreMetadata) if (ignoreMetadata)
{ {
@ -137,7 +137,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(26, rootFrameMetaData.ExifProfile.Values.Count); Assert.Equal(26, rootFrameMetaData.ExifProfile.Values.Count);
} }
} }
}
[Theory] [Theory]
[WithFile(InvalidIptcData, PixelTypes.Rgba32)] [WithFile(InvalidIptcData, PixelTypes.Rgba32)]
@ -158,8 +157,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void BaselineTags<TPixel>(TestImageProvider<TPixel> provider) public void BaselineTags<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(TiffDecoder)) using Image<TPixel> image = provider.GetImage(TiffDecoder);
{
ImageFrame<TPixel> rootFrame = image.Frames.RootFrame; ImageFrame<TPixel> rootFrame = image.Frames.RootFrame;
Assert.Equal(32, rootFrame.Width); Assert.Equal(32, rootFrame.Width);
Assert.Equal(32, rootFrame.Height); Assert.Equal(32, rootFrame.Height);
@ -215,15 +213,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.NotNull(tiffMetaData); Assert.NotNull(tiffMetaData);
Assert.Equal(ByteOrder.LittleEndian, tiffMetaData.ByteOrder); Assert.Equal(ByteOrder.LittleEndian, tiffMetaData.ByteOrder);
} }
}
[Theory] [Theory]
[WithFile(MultiframeDeflateWithPreview, PixelTypes.Rgba32)] [WithFile(MultiframeDeflateWithPreview, PixelTypes.Rgba32)]
public void SubfileType<TPixel>(TestImageProvider<TPixel> provider) public void SubfileType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(TiffDecoder)) using Image<TPixel> image = provider.GetImage(TiffDecoder);
{
TiffMetadata meta = image.Metadata.GetTiffMetadata(); TiffMetadata meta = image.Metadata.GetTiffMetadata();
Assert.NotNull(meta); Assert.NotNull(meta);
@ -239,7 +235,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(255, image.Frames[1].Width); Assert.Equal(255, image.Frames[1].Width);
Assert.Equal(255, image.Frames[1].Height); Assert.Equal(255, image.Frames[1].Height);
} }
}
[Theory] [Theory]
[WithFile(SampleMetadata, PixelTypes.Rgba32)] [WithFile(SampleMetadata, PixelTypes.Rgba32)]
@ -247,7 +242,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// Load Tiff image // Load Tiff image
using Image<TPixel> image = provider.GetImage(new TiffDecoder() { IgnoreMetadata = false }); DecoderOptions options = new() { SkipMetadata = false };
using Image<TPixel> image = provider.GetImage(new TiffDecoder(), options);
ImageMetadata inputMetaData = image.Metadata; ImageMetadata inputMetaData = image.Metadata;
ImageFrame<TPixel> rootFrameInput = image.Frames.RootFrame; ImageFrame<TPixel> rootFrameInput = image.Frames.RootFrame;

4
tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs

@ -3,7 +3,6 @@
using System; using System;
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Webp.Lossless; using SixLabors.ImageSharp.Formats.Webp.Lossless;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
@ -104,7 +103,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(expectedData, transformData); Assert.Equal(expectedData, transformData);
} }
// Test image: Input\Png\Bike.png
private static void RunColorSpaceTransformTestWithBikeImage() private static void RunColorSpaceTransformTestWithBikeImage()
{ {
// arrange // arrange
@ -119,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
// Convert image pixels to bgra array. // Convert image pixels to bgra array.
byte[] imgBytes = File.ReadAllBytes(TestImageFullPath(TestImages.Webp.Lossy.BikeSmall)); byte[] imgBytes = File.ReadAllBytes(TestImageFullPath(TestImages.Webp.Lossy.BikeSmall));
using var image = Image.Load<Rgba32>(imgBytes, new WebpDecoder()); using var image = Image.Load<Rgba32>(imgBytes);
uint[] bgra = ToBgra(image); uint[] bgra = ToBgra(image);
int colorTransformBits = 4; int colorTransformBits = 4;

107
tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs

@ -2,8 +2,8 @@
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
@ -44,15 +44,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
int expectedBitsPerPixel) int expectedBitsPerPixel)
{ {
var testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using var stream = new MemoryStream(testFile.Bytes, false);
{
IImageInfo imageInfo = Image.Identify(stream); IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo); Assert.NotNull(imageInfo);
Assert.Equal(expectedWidth, imageInfo.Width); Assert.Equal(expectedWidth, imageInfo.Width);
Assert.Equal(expectedHeight, imageInfo.Height); Assert.Equal(expectedHeight, imageInfo.Height);
Assert.Equal(expectedBitsPerPixel, imageInfo.PixelType.BitsPerPixel); Assert.Equal(expectedBitsPerPixel, imageInfo.PixelType.BitsPerPixel);
} }
}
[Theory] [Theory]
[WithFile(Lossy.BikeWithExif, PixelTypes.Rgba32)] [WithFile(Lossy.BikeWithExif, PixelTypes.Rgba32)]
@ -67,12 +65,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithoutFilter<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithoutFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.SimpleFilter01, PixelTypes.Rgba32)] [WithFile(Lossy.SimpleFilter01, PixelTypes.Rgba32)]
@ -83,12 +79,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithSimpleFilter<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithSimpleFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.IccpComplexFilter, PixelTypes.Rgba32)] [WithFile(Lossy.IccpComplexFilter, PixelTypes.Rgba32)]
@ -106,12 +100,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithComplexFilter<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithComplexFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.Small01, PixelTypes.Rgba32)] [WithFile(Lossy.Small01, PixelTypes.Rgba32)]
@ -121,12 +113,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_VerySmall<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_VerySmall<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.SegmentationNoFilter04, PixelTypes.Rgba32)] [WithFile(Lossy.SegmentationNoFilter04, PixelTypes.Rgba32)]
@ -140,12 +130,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithPartitions<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithPartitions<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.Partitions01, PixelTypes.Rgba32)] [WithFile(Lossy.Partitions01, PixelTypes.Rgba32)]
@ -154,12 +142,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithSegmentation<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithSegmentation<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.Sharpness01, PixelTypes.Rgba32)] [WithFile(Lossy.Sharpness01, PixelTypes.Rgba32)]
@ -171,12 +157,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithSharpnessLevel<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithSharpnessLevel<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossy.AlphaNoCompression, PixelTypes.Rgba32)] [WithFile(Lossy.AlphaNoCompression, PixelTypes.Rgba32)]
@ -196,24 +180,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithAlpha<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossy_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.Alpha, PixelTypes.Rgba32)] [WithFile(Lossless.Alpha, PixelTypes.Rgba32)]
public void WebpDecoder_CanDecode_Lossless_WithAlpha<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.NoTransform1, PixelTypes.Rgba32)] [WithFile(Lossless.NoTransform1, PixelTypes.Rgba32)]
@ -221,12 +201,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithoutTransforms<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithoutTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.GreenTransform1, PixelTypes.Rgba32)] [WithFile(Lossless.GreenTransform1, PixelTypes.Rgba32)]
@ -240,12 +218,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
TestImageProvider<TPixel> provider) TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.ColorIndexTransform1, PixelTypes.Rgba32)] [WithFile(Lossless.ColorIndexTransform1, PixelTypes.Rgba32)]
@ -256,12 +232,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithColorIndexTransform<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithColorIndexTransform<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.PredictorTransform1, PixelTypes.Rgba32)] [WithFile(Lossless.PredictorTransform1, PixelTypes.Rgba32)]
@ -269,12 +243,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithPredictorTransform<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithPredictorTransform<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.CrossColorTransform1, PixelTypes.Rgba32)] [WithFile(Lossless.CrossColorTransform1, PixelTypes.Rgba32)]
@ -282,12 +254,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithCrossColorTransform<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithCrossColorTransform<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.TwoTransforms1, PixelTypes.Rgba32)] [WithFile(Lossless.TwoTransforms1, PixelTypes.Rgba32)]
@ -306,12 +276,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithTwoTransforms<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithTwoTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.ThreeTransforms1, PixelTypes.Rgba32)] [WithFile(Lossless.ThreeTransforms1, PixelTypes.Rgba32)]
@ -325,20 +293,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithThreeTransforms<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithThreeTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.Animated, PixelTypes.Rgba32)] [WithFile(Lossless.Animated, PixelTypes.Rgba32)]
public void Decode_AnimatedLossless_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider) public void Decode_AnimatedLossless_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata(); WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata();
WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata(); WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata();
@ -349,15 +314,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(150U, frameMetaData.FrameDuration); Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count); Assert.Equal(12, image.Frames.Count);
} }
}
[Theory] [Theory]
[WithFile(Lossy.Animated, PixelTypes.Rgba32)] [WithFile(Lossy.Animated, PixelTypes.Rgba32)]
public void Decode_AnimatedLossy_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider) public void Decode_AnimatedLossy_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata(); WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata();
WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata(); WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata();
@ -368,18 +331,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(150U, frameMetaData.FrameDuration); Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count); Assert.Equal(12, image.Frames.Count);
} }
}
[Theory] [Theory]
[WithFile(Lossless.Animated, PixelTypes.Rgba32)] [WithFile(Lossless.Animated, PixelTypes.Rgba32)]
public void Decode_AnimatedLossless_WithFrameDecodingModeFirst_OnlyDecodesOneFrame<TPixel>(TestImageProvider<TPixel> provider) public void Decode_AnimatedLossless_WithFrameDecodingModeFirst_OnlyDecodesOneFrame<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new WebpDecoder() { DecodingMode = FrameDecodingMode.First })) DecoderOptions options = new() { MaxFrames = 1 };
{ using Image<TPixel> image = provider.GetImage(new WebpDecoder(), options);
Assert.Equal(1, image.Frames.Count); Assert.Equal(1, image.Frames.Count);
} }
}
[Theory] [Theory]
[WithFile(Lossless.LossLessCorruptImage1, PixelTypes.Rgba32)] [WithFile(Lossless.LossLessCorruptImage1, PixelTypes.Rgba32)]
@ -389,11 +350,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// Just make sure no exception is thrown. The reference decoder fails to load the image. // Just make sure no exception is thrown. The reference decoder fails to load the image.
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
} }
}
// https://github.com/SixLabors/ImageSharp/issues/1594 // https://github.com/SixLabors/ImageSharp/issues/1594
[Theory] [Theory]
@ -401,12 +360,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Issue1594<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Issue1594<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(WebpDecoder)) using Image<TPixel> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Theory] [Theory]
[WithFile(Lossless.LossLessCorruptImage3, PixelTypes.Rgba32)] [WithFile(Lossless.LossLessCorruptImage3, PixelTypes.Rgba32)]
@ -424,42 +381,34 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
private static void RunDecodeLossyWithHorizontalFilter() private static void RunDecodeLossyWithHorizontalFilter()
{ {
var provider = TestImageProvider<Rgba32>.File(TestImageLossyHorizontalFilterPath); var provider = TestImageProvider<Rgba32>.File(TestImageLossyHorizontalFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder)) using Image<Rgba32> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
private static void RunDecodeLossyWithVerticalFilter() private static void RunDecodeLossyWithVerticalFilter()
{ {
var provider = TestImageProvider<Rgba32>.File(TestImageLossyVerticalFilterPath); var provider = TestImageProvider<Rgba32>.File(TestImageLossyVerticalFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder)) using Image<Rgba32> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
private static void RunDecodeLossyWithSimpleFilterTest() private static void RunDecodeLossyWithSimpleFilterTest()
{ {
var provider = TestImageProvider<Rgba32>.File(TestImageLossySimpleFilterPath); var provider = TestImageProvider<Rgba32>.File(TestImageLossySimpleFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder)) using Image<Rgba32> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
private static void RunDecodeLossyWithComplexFilterTest() private static void RunDecodeLossyWithComplexFilterTest()
{ {
var provider = TestImageProvider<Rgba32>.File(TestImageLossyComplexFilterPath); var provider = TestImageProvider<Rgba32>.File(TestImageLossyComplexFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder)) using Image<Rgba32> image = provider.GetImage(WebpDecoder);
{
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder); image.CompareToOriginal(provider, ReferenceDecoder);
} }
}
[Fact] [Fact]
public void DecodeLossyWithHorizontalFilter_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunDecodeLossyWithHorizontalFilter, HwIntrinsics.DisableHWIntrinsic); public void DecodeLossyWithHorizontalFilter_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunDecodeLossyWithHorizontalFilter, HwIntrinsics.DisableHWIntrinsic);

35
tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs

@ -4,6 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
[Trait("Format", "Webp")] [Trait("Format", "Webp")]
public class WebpMetaDataTests public class WebpMetaDataTests
{ {
private static WebpDecoder WebpDecoder => new() { IgnoreMetadata = false }; private static WebpDecoder WebpDecoder => new();
[Theory] [Theory]
[WithFile(TestImages.Webp.Lossy.BikeWithExif, PixelTypes.Rgba32, false)] [WithFile(TestImages.Webp.Lossy.BikeWithExif, PixelTypes.Rgba32, false)]
@ -23,9 +24,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void IgnoreMetadata_ControlsWhetherExifIsParsed_WithLossyImage<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata) public void IgnoreMetadata_ControlsWhetherExifIsParsed_WithLossyImage<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata }; DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(WebpDecoder, options);
using Image<TPixel> image = provider.GetImage(decoder);
if (ignoreMetadata) if (ignoreMetadata)
{ {
Assert.Null(image.Metadata.ExifProfile); Assert.Null(image.Metadata.ExifProfile);
@ -45,9 +45,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void IgnoreMetadata_ControlsWhetherExifIsParsed_WithLosslessImage<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata) public void IgnoreMetadata_ControlsWhetherExifIsParsed_WithLosslessImage<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata }; DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(WebpDecoder, options);
using Image<TPixel> image = provider.GetImage(decoder);
if (ignoreMetadata) if (ignoreMetadata)
{ {
Assert.Null(image.Metadata.ExifProfile); Assert.Null(image.Metadata.ExifProfile);
@ -71,9 +70,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void IgnoreMetadata_ControlsWhetherIccpIsParsed<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata) public void IgnoreMetadata_ControlsWhetherIccpIsParsed<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata }; DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(WebpDecoder, options);
using Image<TPixel> image = provider.GetImage(decoder);
if (ignoreMetadata) if (ignoreMetadata)
{ {
Assert.Null(image.Metadata.IccProfile); Assert.Null(image.Metadata.IccProfile);
@ -91,9 +89,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public async Task IgnoreMetadata_ControlsWhetherXmpIsParsed<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata) public async Task IgnoreMetadata_ControlsWhetherXmpIsParsed<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata }; DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = await provider.GetImageAsync(WebpDecoder, options);
using Image<TPixel> image = await provider.GetImageAsync(decoder);
if (ignoreMetadata) if (ignoreMetadata)
{ {
Assert.Null(image.Metadata.XmpProfile); Assert.Null(image.Metadata.XmpProfile);
@ -178,30 +175,24 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider, WebpFileFormatType fileFormat) public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider, WebpFileFormatType fileFormat)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> input = provider.GetImage(new WebpDecoder())) using Image<TPixel> input = provider.GetImage(WebpDecoder);
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile; ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray(); byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
input.Save(memStream, new WebpEncoder() input.Save(memStream, new WebpEncoder()
{ {
FileFormat = fileFormat FileFormat = fileFormat
}); });
memStream.Position = 0; memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream)) using var output = Image.Load<Rgba32>(memStream);
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile; ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray(); byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile); Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes); Assert.Equal(expectedProfileBytes, actualProfileBytes);
} }
}
}
}
[Theory] [Theory]
[WithFile(TestImages.Webp.Lossy.WithExifNotEnoughData, PixelTypes.Rgba32)] [WithFile(TestImages.Webp.Lossy.WithExifNotEnoughData, PixelTypes.Rgba32)]

91
tests/ImageSharp.Tests/Image/ImageTests.Decode_Cancellation.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Xunit; using Xunit;
@ -15,101 +15,138 @@ namespace SixLabors.ImageSharp.Tests
public class Decode_Cancellation : ImageLoadTestBase public class Decode_Cancellation : ImageLoadTestBase
{ {
private bool isTestStreamSeekable; private bool isTestStreamSeekable;
private readonly SemaphoreSlim notifyWaitPositionReachedSemaphore = new SemaphoreSlim(0); private readonly SemaphoreSlim notifyWaitPositionReachedSemaphore = new(0);
private readonly SemaphoreSlim continueSemaphore = new SemaphoreSlim(0); private readonly SemaphoreSlim continueSemaphore = new(0);
private readonly CancellationTokenSource cts = new CancellationTokenSource(); private readonly CancellationTokenSource cts = new();
public Decode_Cancellation() public Decode_Cancellation() => this.TopLevelConfiguration.StreamProcessingBufferSize = 128;
{
this.TopLevelConfiguration.StreamProcessingBufferSize = 128;
}
[Theory] [Theory]
[InlineData(false)] [InlineData(false)]
[InlineData(true)] [InlineData(true)]
public async Task LoadAsync_Specific_Stream(bool isInputStreamSeekable) public Task LoadAsync_Specific_Stream(bool isInputStreamSeekable)
{ {
this.isTestStreamSeekable = isInputStreamSeekable; this.isTestStreamSeekable = isInputStreamSeekable;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync<Rgb24>(this.TopLevelConfiguration, this.DataStream, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync<Rgb24>(options, this.DataStream, this.cts.Token));
} }
[Theory] [Theory]
[InlineData(false)] [InlineData(false)]
[InlineData(true)] [InlineData(true)]
public async Task LoadAsync_Agnostic_Stream(bool isInputStreamSeekable) public Task LoadAsync_Agnostic_Stream(bool isInputStreamSeekable)
{ {
this.isTestStreamSeekable = isInputStreamSeekable; this.isTestStreamSeekable = isInputStreamSeekable;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync(this.TopLevelConfiguration, this.DataStream, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync(options, this.DataStream, this.cts.Token));
} }
[Fact] [Fact]
public async Task LoadAsync_Agnostic_Path() public Task LoadAsync_Agnostic_Path()
{ {
this.isTestStreamSeekable = true; this.isTestStreamSeekable = true;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync(this.TopLevelConfiguration, this.MockFilePath, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync(options, this.MockFilePath, this.cts.Token));
} }
[Fact] [Fact]
public async Task LoadAsync_Specific_Path() public Task LoadAsync_Specific_Path()
{ {
this.isTestStreamSeekable = true; this.isTestStreamSeekable = true;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync<Rgb24>(this.TopLevelConfiguration, this.MockFilePath, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.LoadAsync<Rgb24>(options, this.MockFilePath, this.cts.Token));
} }
[Theory] [Theory]
[InlineData(false)] [InlineData(false)]
[InlineData(true)] [InlineData(true)]
public async Task IdentifyAsync_Stream(bool isInputStreamSeekable) public Task IdentifyAsync_Stream(bool isInputStreamSeekable)
{ {
this.isTestStreamSeekable = isInputStreamSeekable; this.isTestStreamSeekable = isInputStreamSeekable;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyAsync(this.TopLevelConfiguration, this.DataStream, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyAsync(options, this.DataStream, this.cts.Token));
} }
[Fact] [Fact]
public async Task IdentifyAsync_CustomConfiguration_Path() public Task IdentifyAsync_CustomConfiguration_Path()
{ {
this.isTestStreamSeekable = true; this.isTestStreamSeekable = true;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyAsync(this.TopLevelConfiguration, this.MockFilePath, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyAsync(options, this.MockFilePath, this.cts.Token));
} }
[Theory] [Theory]
[InlineData(false)] [InlineData(false)]
[InlineData(true)] [InlineData(true)]
public async Task IdentifyWithFormatAsync_CustomConfiguration_Stream(bool isInputStreamSeekable) public Task IdentifyWithFormatAsync_CustomConfiguration_Stream(bool isInputStreamSeekable)
{ {
this.isTestStreamSeekable = isInputStreamSeekable; this.isTestStreamSeekable = isInputStreamSeekable;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyWithFormatAsync(this.TopLevelConfiguration, this.DataStream, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyWithFormatAsync(options, this.DataStream, this.cts.Token));
} }
[Fact] [Fact]
public async Task IdentifyWithFormatAsync_CustomConfiguration_Path() public Task IdentifyWithFormatAsync_CustomConfiguration_Path()
{ {
this.isTestStreamSeekable = true; this.isTestStreamSeekable = true;
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyWithFormatAsync(this.TopLevelConfiguration, this.MockFilePath, this.cts.Token)); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
return Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyWithFormatAsync(options, this.MockFilePath, this.cts.Token));
} }
[Fact] [Fact]
public async Task IdentifyWithFormatAsync_DefaultConfiguration_Stream() public Task IdentifyWithFormatAsync_DefaultConfiguration_Stream()
{ {
_ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning); _ = Task.Factory.StartNew(this.DoCancel, TaskCreationOptions.LongRunning);
await Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyWithFormatAsync(this.DataStream, this.cts.Token)); return Assert.ThrowsAsync<TaskCanceledException>(() => Image.IdentifyWithFormatAsync(this.DataStream, this.cts.Token));
} }
private async Task DoCancel() private async Task DoCancel()

60
tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs

@ -29,26 +29,23 @@ namespace SixLabors.ImageSharp.Tests
private static readonly IImageFormat ExpectedGlobalFormat = private static readonly IImageFormat ExpectedGlobalFormat =
Configuration.Default.ImageFormatsManager.FindFormatByFileExtension("bmp"); Configuration.Default.ImageFormatsManager.FindFormatByFileExtension("bmp");
[Theory] [Fact]
[InlineData(false)] public void FromBytes_GlobalConfiguration()
[InlineData(true)]
public void FromBytes_GlobalConfiguration(bool useSpan)
{ {
IImageFormat type = useSpan IImageFormat type = Image.DetectFormat(this.ActualImageSpan);
? Image.DetectFormat(this.ActualImageSpan)
: Image.DetectFormat(this.ActualImageBytes);
Assert.Equal(ExpectedGlobalFormat, type); Assert.Equal(ExpectedGlobalFormat, type);
} }
[Theory] [Fact]
[InlineData(false)] public void FromBytes_CustomConfiguration()
[InlineData(true)]
public void FromBytes_CustomConfiguration(bool useSpan)
{ {
IImageFormat type = useSpan DecoderOptions options = new()
? Image.DetectFormat(this.LocalConfiguration, this.ByteArray.AsSpan()) {
: Image.DetectFormat(this.LocalConfiguration, this.ByteArray); Configuration = this.LocalConfiguration
};
IImageFormat type = Image.DetectFormat(options, this.ByteArray);
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
} }
@ -63,7 +60,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromFileSystemPath_CustomConfiguration() public void FromFileSystemPath_CustomConfiguration()
{ {
IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.MockFilePath); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageFormat type = Image.DetectFormat(options, this.MockFilePath);
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
} }
@ -80,14 +82,24 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromStream_CustomConfiguration() public void FromStream_CustomConfiguration()
{ {
IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.DataStream); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageFormat type = Image.DetectFormat(options, this.DataStream);
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
} }
[Fact] [Fact]
public void WhenNoMatchingFormatFound_ReturnsNull() public void WhenNoMatchingFormatFound_ReturnsNull()
{ {
IImageFormat type = Image.DetectFormat(new Configuration(), this.DataStream); DecoderOptions options = new()
{
Configuration = new()
};
IImageFormat type = Image.DetectFormat(options, this.DataStream);
Assert.Null(type); Assert.Null(type);
} }
@ -104,14 +116,24 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task FromStreamAsync_CustomConfiguration() public async Task FromStreamAsync_CustomConfiguration()
{ {
IImageFormat type = await Image.DetectFormatAsync(this.LocalConfiguration, new AsyncStreamWrapper(this.DataStream, () => false)); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageFormat type = await Image.DetectFormatAsync(options, new AsyncStreamWrapper(this.DataStream, () => false));
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
} }
[Fact] [Fact]
public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull() public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull()
{ {
IImageFormat type = await Image.DetectFormatAsync(new Configuration(), new AsyncStreamWrapper(this.DataStream, () => false)); DecoderOptions options = new()
{
Configuration = new()
};
IImageFormat type = await Image.DetectFormatAsync(options, new AsyncStreamWrapper(this.DataStream, () => false));
Assert.Null(type); Assert.Null(type);
} }
} }

81
tests/ImageSharp.Tests/Image/ImageTests.Identify.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests
{ {
private static readonly string ActualImagePath = TestFile.GetInputFileFullPath(TestImages.Bmp.F); private static readonly string ActualImagePath = TestFile.GetInputFileFullPath(TestImages.Bmp.F);
private static readonly Size ExpectedImageSize = new Size(108, 202); private static readonly Size ExpectedImageSize = new(108, 202);
private static byte[] ActualImageBytes => TestFile.Create(TestImages.Bmp.F).Bytes; private static byte[] ActualImageBytes => TestFile.Create(TestImages.Bmp.F).Bytes;
@ -43,7 +43,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromBytes_CustomConfiguration() public void FromBytes_CustomConfiguration()
{ {
IImageInfo info = Image.Identify(this.LocalConfiguration, this.ByteArray, out IImageFormat type); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageInfo info = Image.Identify(options, this.ByteArray, out IImageFormat type);
Assert.Equal(this.LocalImageInfo, info); Assert.Equal(this.LocalImageInfo, info);
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
@ -61,7 +66,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromFileSystemPath_CustomConfiguration() public void FromFileSystemPath_CustomConfiguration()
{ {
IImageInfo info = Image.Identify(this.LocalConfiguration, this.MockFilePath, out IImageFormat type); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageInfo info = Image.Identify(options, this.MockFilePath, out IImageFormat type);
Assert.Equal(this.LocalImageInfo, info); Assert.Equal(this.LocalImageInfo, info);
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
@ -70,25 +80,21 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromStream_GlobalConfiguration() public void FromStream_GlobalConfiguration()
{ {
using (var stream = new MemoryStream(ActualImageBytes)) using var stream = new MemoryStream(ActualImageBytes);
{
IImageInfo info = Image.Identify(stream, out IImageFormat type); IImageInfo info = Image.Identify(stream, out IImageFormat type);
Assert.NotNull(info); Assert.NotNull(info);
Assert.Equal(ExpectedGlobalFormat, type); Assert.Equal(ExpectedGlobalFormat, type);
} }
}
[Fact] [Fact]
public void FromStream_GlobalConfiguration_NoFormat() public void FromStream_GlobalConfiguration_NoFormat()
{ {
using (var stream = new MemoryStream(ActualImageBytes)) using var stream = new MemoryStream(ActualImageBytes);
{
IImageInfo info = Image.Identify(stream); IImageInfo info = Image.Identify(stream);
Assert.NotNull(info); Assert.NotNull(info);
} }
}
[Fact] [Fact]
public void FromNonSeekableStream_GlobalConfiguration() public void FromNonSeekableStream_GlobalConfiguration()
@ -116,7 +122,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromStream_CustomConfiguration() public void FromStream_CustomConfiguration()
{ {
IImageInfo info = Image.Identify(this.LocalConfiguration, this.DataStream, out IImageFormat type); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageInfo info = Image.Identify(options, this.DataStream, out IImageFormat type);
Assert.Equal(this.LocalImageInfo, info); Assert.Equal(this.LocalImageInfo, info);
Assert.Equal(this.LocalImageFormat, type); Assert.Equal(this.LocalImageFormat, type);
@ -125,7 +136,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void FromStream_CustomConfiguration_NoFormat() public void FromStream_CustomConfiguration_NoFormat()
{ {
IImageInfo info = Image.Identify(this.LocalConfiguration, this.DataStream); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageInfo info = Image.Identify(options, this.DataStream);
Assert.Equal(this.LocalImageInfo, info); Assert.Equal(this.LocalImageInfo, info);
} }
@ -133,7 +149,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void WhenNoMatchingFormatFound_ReturnsNull() public void WhenNoMatchingFormatFound_ReturnsNull()
{ {
IImageInfo info = Image.Identify(new Configuration(), this.DataStream, out IImageFormat type); DecoderOptions options = new()
{
Configuration = new()
};
IImageInfo info = Image.Identify(options, this.DataStream, out IImageFormat type);
Assert.Null(info); Assert.Null(info);
Assert.Null(type); Assert.Null(type);
@ -168,27 +189,23 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task FromStreamAsync_GlobalConfiguration_NoFormat() public async Task FromStreamAsync_GlobalConfiguration_NoFormat()
{ {
using (var stream = new MemoryStream(ActualImageBytes)) using var stream = new MemoryStream(ActualImageBytes);
{
var asyncStream = new AsyncStreamWrapper(stream, () => false); var asyncStream = new AsyncStreamWrapper(stream, () => false);
IImageInfo info = await Image.IdentifyAsync(asyncStream); IImageInfo info = await Image.IdentifyAsync(asyncStream);
Assert.NotNull(info); Assert.NotNull(info);
} }
}
[Fact] [Fact]
public async Task FromStreamAsync_GlobalConfiguration() public async Task FromStreamAsync_GlobalConfiguration()
{ {
using (var stream = new MemoryStream(ActualImageBytes)) using var stream = new MemoryStream(ActualImageBytes);
{
var asyncStream = new AsyncStreamWrapper(stream, () => false); var asyncStream = new AsyncStreamWrapper(stream, () => false);
(IImageInfo ImageInfo, IImageFormat Format) res = await Image.IdentifyWithFormatAsync(asyncStream); (IImageInfo ImageInfo, IImageFormat Format) res = await Image.IdentifyWithFormatAsync(asyncStream);
Assert.Equal(ExpectedImageSize, res.ImageInfo.Size()); Assert.Equal(ExpectedImageSize, res.ImageInfo.Size());
Assert.Equal(ExpectedGlobalFormat, res.Format); Assert.Equal(ExpectedGlobalFormat, res.Format);
} }
}
[Fact] [Fact]
public async Task FromNonSeekableStreamAsync_GlobalConfiguration_NoFormat() public async Task FromNonSeekableStreamAsync_GlobalConfiguration_NoFormat()
@ -244,14 +261,24 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task FromPathAsync_CustomConfiguration() public async Task FromPathAsync_CustomConfiguration()
{ {
IImageInfo info = await Image.IdentifyAsync(this.LocalConfiguration, this.MockFilePath); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageInfo info = await Image.IdentifyAsync(options, this.MockFilePath);
Assert.Equal(this.LocalImageInfo, info); Assert.Equal(this.LocalImageInfo, info);
} }
[Fact] [Fact]
public async Task IdentifyWithFormatAsync_FromPath_CustomConfiguration() public async Task IdentifyWithFormatAsync_FromPath_CustomConfiguration()
{ {
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(this.LocalConfiguration, this.MockFilePath); DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(options, this.MockFilePath);
Assert.NotNull(info.ImageInfo); Assert.NotNull(info.ImageInfo);
Assert.Equal(this.LocalImageFormat, info.Format); Assert.Equal(this.LocalImageFormat, info.Format);
} }
@ -276,8 +303,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task FromStreamAsync_CustomConfiguration() public async Task FromStreamAsync_CustomConfiguration()
{ {
DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false); var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false);
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(this.LocalConfiguration, asyncStream); (IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(options, asyncStream);
Assert.Equal(this.LocalImageInfo, info.ImageInfo); Assert.Equal(this.LocalImageInfo, info.ImageInfo);
Assert.Equal(this.LocalImageFormat, info.Format); Assert.Equal(this.LocalImageFormat, info.Format);
@ -286,8 +318,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull() public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull()
{ {
DecoderOptions options = new()
{
Configuration = new()
};
var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false); var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false);
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(new Configuration(), asyncStream); (IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(options, asyncStream);
Assert.Null(info.ImageInfo); Assert.Null(info.ImageInfo);
} }

21
tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs

@ -63,28 +63,27 @@ namespace SixLabors.ImageSharp.Tests
this.localImageFormatMock = new Mock<IImageFormat>(); this.localImageFormatMock = new Mock<IImageFormat>();
var detector = new Mock<IImageInfoDetector>(); var detector = new Mock<IImageInfoDetector>();
detector.Setup(x => x.Identify(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>())).Returns(this.localImageInfoMock.Object); detector.Setup(x => x.Identify(It.IsAny<DecoderOptions>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.Returns(this.localImageInfoMock.Object);
this.localDecoder = detector.As<IImageDecoder>(); this.localDecoder = detector.As<IImageDecoder>();
this.localDecoder.Setup(x => x.Decode<Rgba32>(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>())) this.localDecoder
.Callback<Configuration, Stream, CancellationToken>((c, s, ct) => .Setup(x => x.Decode<Rgba32>(It.IsAny<DecoderOptions>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
{ .Callback<DecoderOptions, Stream, CancellationToken>((c, s, ct) =>
using (var ms = new MemoryStream())
{ {
using var ms = new MemoryStream();
s.CopyTo(ms); s.CopyTo(ms);
this.DecodedData = ms.ToArray(); this.DecodedData = ms.ToArray();
}
}) })
.Returns(this.localStreamReturnImageRgba32); .Returns(this.localStreamReturnImageRgba32);
this.localDecoder.Setup(x => x.Decode(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>())) this.localDecoder
.Callback<Configuration, Stream, CancellationToken>((c, s, ct) => .Setup(x => x.Decode(It.IsAny<DecoderOptions>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
{ .Callback<DecoderOptions, Stream, CancellationToken>((c, s, ct) =>
using (var ms = new MemoryStream())
{ {
using var ms = new MemoryStream();
s.CopyTo(ms); s.CopyTo(ms);
this.DecodedData = ms.ToArray(); this.DecodedData = ms.ToArray();
}
}) })
.Returns(this.localStreamReturnImageAgnostic); .Returns(this.localStreamReturnImageAgnostic);

65
tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs

@ -16,7 +16,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Path_Specific() public void Configuration_Path_Specific()
{ {
var img = Image.Load<Rgb24>(this.TopLevelConfiguration, this.MockFilePath); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgb24>(options, this.MockFilePath);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img); Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
@ -27,7 +32,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Path_Agnostic() public void Configuration_Path_Agnostic()
{ {
var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.MockFilePath);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img); Assert.Equal(this.TestFormat.SampleAgnostic(), img);
@ -36,27 +46,14 @@ namespace SixLabors.ImageSharp.Tests
} }
[Fact] [Fact]
public void Configuration_Path_Decoder_Specific() public void Configuration_Path_OutFormat_Specific()
{ {
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); DecoderOptions options = new()
Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(this.TopLevelConfiguration, this.DataStream, default));
}
[Fact]
public void Configuration_Path_Decoder_Agnostic()
{ {
var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); Configuration = this.TopLevelConfiguration
};
Assert.NotNull(img); var img = Image.Load<Rgba32>(options, this.MockFilePath, out IImageFormat format);
this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, this.DataStream, default));
}
[Fact]
public void Configuration_Path_OutFormat_Specific()
{
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, this.MockFilePath, out IImageFormat format);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat, format); Assert.Equal(this.TestFormat, format);
@ -67,7 +64,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Path_OutFormat_Agnostic() public void Configuration_Path_OutFormat_Agnostic()
{ {
var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, out IImageFormat format); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.MockFilePath, out IImageFormat format);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat, format); Assert.Equal(this.TestFormat, format);
@ -77,23 +79,28 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void WhenFileNotFound_Throws() public void WhenFileNotFound_Throws()
{ => Assert.Throws<System.IO.FileNotFoundException>(
Assert.Throws<System.IO.FileNotFoundException>(
() => () =>
{ {
Image.Load<Rgba32>(this.TopLevelConfiguration, Guid.NewGuid().ToString()); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
Image.Load<Rgba32>(options, Guid.NewGuid().ToString());
}); });
}
[Fact] [Fact]
public void WhenPathIsNull_Throws() public void WhenPathIsNull_Throws()
{ => Assert.Throws<ArgumentNullException>(
Assert.Throws<ArgumentNullException>(
() => () =>
{ {
Image.Load<Rgba32>(this.TopLevelConfiguration, (string)null); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
Image.Load<Rgba32>(options, (string)null);
}); });
} }
} }
}
} }

66
tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs

@ -2,6 +2,7 @@
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System; using System;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Formats.Bmp;
@ -17,10 +18,7 @@ namespace SixLabors.ImageSharp.Tests
{ {
private string Path { get; } = TestFile.GetInputFileFullPath(TestImages.Bmp.Bit8); private string Path { get; } = TestFile.GetInputFileFullPath(TestImages.Bmp.Bit8);
private static void VerifyDecodedImage(Image img) private static void VerifyDecodedImage(Image img) => Assert.Equal(new Size(127, 64), img.Size());
{
Assert.Equal(new Size(127, 64), img.Size());
}
[Fact] [Fact]
public void Path_Specific() public void Path_Specific()
@ -39,49 +37,21 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task Path_Agnostic_Async() public async Task Path_Agnostic_Async()
{ {
using var img = await Image.LoadAsync(this.Path); using Image img = await Image.LoadAsync(this.Path);
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
[Fact] [Fact]
public async Task Path_Specific_Async() public async Task Path_Specific_Async()
{ {
using var img = await Image.LoadAsync<Rgb24>(this.Path); using Image<Rgb24> img = await Image.LoadAsync<Rgb24>(this.Path);
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
[Fact] [Fact]
public async Task Path_Agnostic_Configuration_Async() public async Task Path_Agnostic_Configuration_Async()
{ {
using var img = await Image.LoadAsync(this.Path); using Image img = await Image.LoadAsync(this.Path);
VerifyDecodedImage(img);
}
[Fact]
public void Path_Decoder_Specific()
{
using var img = Image.Load<Rgba32>(this.Path, new BmpDecoder());
VerifyDecodedImage(img);
}
[Fact]
public void Path_Decoder_Agnostic()
{
using var img = Image.Load(this.Path, new BmpDecoder());
VerifyDecodedImage(img);
}
[Fact]
public async Task Path_Decoder_Agnostic_Async()
{
using var img = await Image.LoadAsync(this.Path, new BmpDecoder());
VerifyDecodedImage(img);
}
[Fact]
public async Task Path_Decoder_Specific_Async()
{
using var img = await Image.LoadAsync<Rgb24>(this.Path, new BmpDecoder());
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
@ -103,37 +73,19 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void WhenFileNotFound_Throws() public void WhenFileNotFound_Throws()
{ => Assert.Throws<FileNotFoundException>(() => Image.Load<Rgba32>(Guid.NewGuid().ToString()));
Assert.Throws<System.IO.FileNotFoundException>(
() =>
{
Image.Load<Rgba32>(Guid.NewGuid().ToString());
});
}
[Fact] [Fact]
public void WhenPathIsNull_Throws() public void WhenPathIsNull_Throws()
{ => Assert.Throws<ArgumentNullException>(() => Image.Load<Rgba32>((string)null));
Assert.Throws<ArgumentNullException>(
() =>
{
Image.Load<Rgba32>((string)null);
});
}
[Fact] [Fact]
public Task Async_WhenFileNotFound_Throws() public Task Async_WhenFileNotFound_Throws()
{ => Assert.ThrowsAsync<FileNotFoundException>(() => Image.LoadAsync<Rgba32>(Guid.NewGuid().ToString()));
return Assert.ThrowsAsync<System.IO.FileNotFoundException>(
() => Image.LoadAsync<Rgba32>(Guid.NewGuid().ToString()));
}
[Fact] [Fact]
public Task Async_WhenPathIsNull_Throws() public Task Async_WhenPathIsNull_Throws()
{ => Assert.ThrowsAsync<ArgumentNullException>(() => Image.LoadAsync<Rgba32>((string)null));
return Assert.ThrowsAsync<ArgumentNullException>(
() => Image.LoadAsync<Rgba32>((string)null));
}
} }
} }
} }

88
tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs

@ -15,14 +15,15 @@ namespace SixLabors.ImageSharp.Tests
{ {
private ReadOnlySpan<byte> ByteSpan => this.ByteArray.AsSpan(); private ReadOnlySpan<byte> ByteSpan => this.ByteArray.AsSpan();
[Theory] [Fact]
[InlineData(false)] public void Configuration_Bytes_Specific()
[InlineData(true)]
public void Configuration_Bytes_Specific(bool useSpan)
{ {
var img = useSpan DecoderOptions options = new()
? Image.Load<Rgb24>(this.TopLevelConfiguration, this.ByteSpan) {
: Image.Load<Rgb24>(this.TopLevelConfiguration, this.ByteArray); Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgb24>(options, this.ByteSpan);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img); Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
@ -30,14 +31,15 @@ namespace SixLabors.ImageSharp.Tests
this.TestFormat.VerifySpecificDecodeCall<Rgb24>(this.Marker, this.TopLevelConfiguration); this.TestFormat.VerifySpecificDecodeCall<Rgb24>(this.Marker, this.TopLevelConfiguration);
} }
[Theory] [Fact]
[InlineData(false)] public void Configuration_Bytes_Agnostic()
[InlineData(true)]
public void Configuration_Bytes_Agnostic(bool useSpan)
{ {
var img = useSpan DecoderOptions options = new()
? Image.Load(this.TopLevelConfiguration, this.ByteSpan) {
: Image.Load(this.TopLevelConfiguration, this.ByteArray); Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.ByteSpan);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img); Assert.Equal(this.TestFormat.SampleAgnostic(), img);
@ -45,45 +47,15 @@ namespace SixLabors.ImageSharp.Tests
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
} }
[Theory] [Fact]
[InlineData(false)] public void Configuration_Bytes_OutFormat_Specific()
[InlineData(true)]
public void Configuration_Bytes_Decoder_Specific(bool useSpan)
{ {
var localFormat = new TestFormat(); DecoderOptions options = new()
var img = useSpan ?
Image.Load<Rgba32>(this.TopLevelConfiguration, this.ByteSpan, localFormat.Decoder) :
Image.Load<Rgba32>(this.TopLevelConfiguration, this.ByteArray, localFormat.Decoder);
Assert.NotNull(img);
localFormat.VerifySpecificDecodeCall<Rgba32>(this.Marker, this.TopLevelConfiguration);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Configuration_Bytes_Decoder_Agnostic(bool useSpan)
{ {
var localFormat = new TestFormat(); Configuration = this.TopLevelConfiguration
};
var img = useSpan ?
Image.Load(this.TopLevelConfiguration, this.ByteSpan, localFormat.Decoder) :
Image.Load(this.TopLevelConfiguration, this.ByteArray, localFormat.Decoder);
Assert.NotNull(img);
localFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}
[Theory] var img = Image.Load<Bgr24>(options, this.ByteSpan, out IImageFormat format);
[InlineData(false)]
[InlineData(true)]
public void Configuration_Bytes_OutFormat_Specific(bool useSpan)
{
IImageFormat format;
var img = useSpan ?
Image.Load<Bgr24>(this.TopLevelConfiguration, this.ByteSpan, out format) :
Image.Load<Bgr24>(this.TopLevelConfiguration, this.ByteArray, out format);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat, format); Assert.Equal(this.TestFormat, format);
@ -91,15 +63,15 @@ namespace SixLabors.ImageSharp.Tests
this.TestFormat.VerifySpecificDecodeCall<Bgr24>(this.Marker, this.TopLevelConfiguration); this.TestFormat.VerifySpecificDecodeCall<Bgr24>(this.Marker, this.TopLevelConfiguration);
} }
[Theory] [Fact]
[InlineData(false)] public void Configuration_Bytes_OutFormat_Agnostic()
[InlineData(true)]
public void Configuration_Bytes_OutFormat_Agnostic(bool useSpan)
{ {
IImageFormat format; DecoderOptions options = new()
var img = useSpan ? {
Image.Load(this.TopLevelConfiguration, this.ByteSpan, out format) : Configuration = this.TopLevelConfiguration
Image.Load(this.TopLevelConfiguration, this.ByteArray, out format); };
var img = Image.Load(options, this.ByteSpan, out IImageFormat format);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat, format); Assert.Equal(this.TestFormat, format);

71
tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs

@ -16,82 +16,39 @@ namespace SixLabors.ImageSharp.Tests
{ {
private static byte[] ByteArray { get; } = TestFile.Create(TestImages.Bmp.Bit8).Bytes; private static byte[] ByteArray { get; } = TestFile.Create(TestImages.Bmp.Bit8).Bytes;
private static Span<byte> ByteSpan => new Span<byte>(ByteArray); private static Span<byte> ByteSpan => new(ByteArray);
private static void VerifyDecodedImage(Image img) private static void VerifyDecodedImage(Image img) => Assert.Equal(new Size(127, 64), img.Size());
{
Assert.Equal(new Size(127, 64), img.Size());
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Bytes_Specific(bool useSpan)
{
using (var img = useSpan ? Image.Load<Rgba32>(ByteSpan) : Image.Load<Rgba32>(ByteArray))
{
VerifyDecodedImage(img);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Bytes_Agnostic(bool useSpan)
{
using (var img = useSpan ? Image.Load(ByteSpan) : Image.Load(ByteArray))
{
VerifyDecodedImage(img);
}
}
[Theory] [Fact]
[InlineData(false)] public void Bytes_Specific()
[InlineData(true)]
public void Bytes_Decoder_Specific(bool useSpan)
{
using (var img = useSpan ? Image.Load<Rgba32>(ByteSpan, new BmpDecoder()) : Image.Load<Rgba32>(ByteArray, new BmpDecoder()))
{ {
using var img = Image.Load<Rgba32>(ByteSpan);
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
}
[Theory] [Fact]
[InlineData(false)] public void Bytes_Agnostic()
[InlineData(true)]
public void Bytes_Decoder_Agnostic(bool useSpan)
{
using (var img = useSpan ? Image.Load(ByteSpan, new BmpDecoder()) : Image.Load(ByteArray, new BmpDecoder()))
{ {
using var img = Image.Load(ByteSpan);
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
}
[Theory] [Fact]
[InlineData(false)] public void Bytes_OutFormat_Specific()
[InlineData(true)]
public void Bytes_OutFormat_Specific(bool useSpan)
{
IImageFormat format;
using (var img = useSpan ? Image.Load<Rgba32>(ByteSpan, out format) : Image.Load<Rgba32>(ByteArray, out format))
{ {
using var img = Image.Load<Rgba32>(ByteSpan, out IImageFormat format);
VerifyDecodedImage(img); VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format); Assert.IsType<BmpFormat>(format);
} }
}
[Theory] [Fact]
[InlineData(false)] public void Bytes_OutFormat_Agnostic()
[InlineData(true)]
public void Bytes_OutFormat_Agnostic(bool useSpan)
{
IImageFormat format;
using (var img = useSpan ? Image.Load(ByteSpan, out format) : Image.Load(ByteArray, out format))
{ {
using var img = Image.Load(ByteSpan, out IImageFormat format);
VerifyDecodedImage(img); VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format); Assert.IsType<BmpFormat>(format);
} }
} }
} }
}
} }

61
tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -17,7 +16,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Stream_Specific() public void Configuration_Stream_Specific()
{ {
var img = Image.Load<Rgb24>(this.TopLevelConfiguration, this.DataStream); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgb24>(options, this.DataStream);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img); Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
@ -28,7 +32,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Stream_Agnostic() public void Configuration_Stream_Agnostic()
{ {
var img = Image.Load(this.TopLevelConfiguration, this.DataStream); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.DataStream);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img); Assert.Equal(this.TestFormat.SampleAgnostic(), img);
@ -39,8 +48,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void NonSeekableStream() public void NonSeekableStream()
{ {
DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var stream = new NonSeekableStream(this.DataStream); var stream = new NonSeekableStream(this.DataStream);
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, stream); var img = Image.Load<Rgba32>(options, stream);
Assert.NotNull(img); Assert.NotNull(img);
@ -50,8 +64,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public async Task NonSeekableStreamAsync() public async Task NonSeekableStreamAsync()
{ {
DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var stream = new NonSeekableStream(this.DataStream); var stream = new NonSeekableStream(this.DataStream);
Image<Rgba32> img = await Image.LoadAsync<Rgba32>(this.TopLevelConfiguration, stream); Image<Rgba32> img = await Image.LoadAsync<Rgba32>(options, stream);
Assert.NotNull(img); Assert.NotNull(img);
@ -59,29 +78,14 @@ namespace SixLabors.ImageSharp.Tests
} }
[Fact] [Fact]
public void Configuration_Stream_Decoder_Specific() public void Configuration_Stream_OutFormat_Specific()
{ {
var stream = new MemoryStream(); DecoderOptions options = new()
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, stream, this.localDecoder.Object);
Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(this.TopLevelConfiguration, stream, default));
}
[Fact]
public void Configuration_Stream_Decoder_Agnostic()
{ {
var stream = new MemoryStream(); Configuration = this.TopLevelConfiguration
var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object); };
Assert.NotNull(img); var img = Image.Load<Rgba32>(options, this.DataStream, out IImageFormat format);
this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, stream, default));
}
[Fact]
public void Configuration_Stream_OutFormat_Specific()
{
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, this.DataStream, out IImageFormat format);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat, format); Assert.Equal(this.TestFormat, format);
@ -92,7 +96,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Stream_OutFormat_Agnostic() public void Configuration_Stream_OutFormat_Agnostic()
{ {
var img = Image.Load(this.TopLevelConfiguration, this.DataStream, out IImageFormat format); DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.DataStream, out IImageFormat format);
Assert.NotNull(img); Assert.NotNull(img);
Assert.Equal(this.TestFormat, format); Assert.Equal(this.TestFormat, format);

17
tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs

@ -20,30 +20,23 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Image_Load_Throws_UnknownImageFormatException() public void Image_Load_Throws_UnknownImageFormatException()
=> Assert.Throws<UnknownImageFormatException>(() =>
{ {
Assert.Throws<UnknownImageFormatException>(() => using (Image.Load(DecoderOptions.Default, this.Stream, out IImageFormat format))
{
using (Image.Load(Configuration.Default, this.Stream, out IImageFormat format))
{ {
} }
}); });
}
[Fact] [Fact]
public void Image_Load_T_Throws_UnknownImageFormatException() public void Image_Load_T_Throws_UnknownImageFormatException()
=> Assert.Throws<UnknownImageFormatException>(() =>
{ {
Assert.Throws<UnknownImageFormatException>(() => using (Image.Load<Rgba32>(DecoderOptions.Default, this.Stream, out IImageFormat format))
{
using (Image.Load<Rgba32>(Configuration.Default, this.Stream, out IImageFormat format))
{ {
} }
}); });
}
public void Dispose() public void Dispose() => this.Stream?.Dispose();
{
this.Stream?.Dispose();
}
} }
} }
} }

75
tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs

@ -31,71 +31,43 @@ namespace SixLabors.ImageSharp.Tests
} }
private static void VerifyDecodedImage(Image img) private static void VerifyDecodedImage(Image img)
{ => Assert.Equal(new Size(127, 64), img.Size());
Assert.Equal(new Size(127, 64), img.Size());
}
[Fact] [Fact]
public void Stream_Specific() public void Stream_Specific()
{ {
using (var img = Image.Load<Rgba32>(this.Stream)) using var img = Image.Load<Rgba32>(this.Stream);
{
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
}
[Fact] [Fact]
public void Stream_Agnostic() public void Stream_Agnostic()
{ {
using (var img = Image.Load(this.Stream)) using var img = Image.Load(this.Stream);
{
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
}
[Fact] [Fact]
public void Stream_OutFormat_Specific() public void Stream_OutFormat_Specific()
{ {
using (var img = Image.Load<Rgba32>(this.Stream, out IImageFormat format)) using var img = Image.Load<Rgba32>(this.Stream, out IImageFormat format);
{
VerifyDecodedImage(img); VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format); Assert.IsType<BmpFormat>(format);
} }
}
[Fact]
public void Stream_Decoder_Specific()
{
using (var img = Image.Load<Rgba32>(this.Stream, new BmpDecoder()))
{
VerifyDecodedImage(img);
}
}
[Fact]
public void Stream_Decoder_Agnostic()
{
using (var img = Image.Load(this.Stream, new BmpDecoder()))
{
VerifyDecodedImage(img);
}
}
[Fact] [Fact]
public void Stream_OutFormat_Agnostic() public void Stream_OutFormat_Agnostic()
{ {
using (var img = Image.Load(this.Stream, out IImageFormat format)) using var img = Image.Load(this.Stream, out IImageFormat format);
{
VerifyDecodedImage(img); VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format); Assert.IsType<BmpFormat>(format);
} }
}
[Fact] [Fact]
public async Task Async_Stream_OutFormat_Agnostic() public async Task Async_Stream_OutFormat_Agnostic()
{ {
this.AllowSynchronousIO = false; this.AllowSynchronousIO = false;
var formattedImage = await Image.LoadWithFormatAsync(this.Stream); (Image Image, IImageFormat Format) formattedImage = await Image.LoadWithFormatAsync(this.Stream);
using (formattedImage.Image) using (formattedImage.Image)
{ {
VerifyDecodedImage(formattedImage.Image); VerifyDecodedImage(formattedImage.Image);
@ -107,27 +79,23 @@ namespace SixLabors.ImageSharp.Tests
public async Task Async_Stream_Specific() public async Task Async_Stream_Specific()
{ {
this.AllowSynchronousIO = false; this.AllowSynchronousIO = false;
using (var img = await Image.LoadAsync<Rgba32>(this.Stream)) using Image<Rgba32> img = await Image.LoadAsync<Rgba32>(this.Stream);
{
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
}
[Fact] [Fact]
public async Task Async_Stream_Agnostic() public async Task Async_Stream_Agnostic()
{ {
this.AllowSynchronousIO = false; this.AllowSynchronousIO = false;
using (var img = await Image.LoadAsync(this.Stream)) using Image img = await Image.LoadAsync(this.Stream);
{
VerifyDecodedImage(img); VerifyDecodedImage(img);
} }
}
[Fact] [Fact]
public async Task Async_Stream_OutFormat_Specific() public async Task Async_Stream_OutFormat_Specific()
{ {
this.AllowSynchronousIO = false; this.AllowSynchronousIO = false;
var formattedImage = await Image.LoadWithFormatAsync<Rgba32>(this.Stream); (Image<Rgba32> Image, IImageFormat Format) formattedImage = await Image.LoadWithFormatAsync<Rgba32>(this.Stream);
using (formattedImage.Image) using (formattedImage.Image)
{ {
VerifyDecodedImage(formattedImage.Image); VerifyDecodedImage(formattedImage.Image);
@ -135,30 +103,7 @@ namespace SixLabors.ImageSharp.Tests
} }
} }
[Fact] public void Dispose() => this.BaseStream?.Dispose();
public async Task Async_Stream_Decoder_Specific()
{
this.AllowSynchronousIO = false;
using (var img = await Image.LoadAsync<Rgba32>(this.Stream, new BmpDecoder()))
{
VerifyDecodedImage(img);
}
}
[Fact]
public async Task Async_Stream_Decoder_Agnostic()
{
this.AllowSynchronousIO = false;
using (var img = await Image.LoadAsync(this.Stream, new BmpDecoder()))
{
VerifyDecodedImage(img);
}
}
public void Dispose()
{
this.BaseStream?.Dispose();
}
} }
} }
} }

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

@ -6,7 +6,6 @@ using System.IO;
using Microsoft.DotNet.RemoteExecutor; using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using Xunit; using Xunit;
@ -62,13 +61,18 @@ namespace SixLabors.ImageSharp.Tests
IImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder( IImageEncoder 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().ToString()}.{formatInner}"); string path = Path.Combine(dir, $"{Guid.NewGuid()}.{formatInner}");
using (Image<Rgba32> temp = new(2048, 2048)) using (Image<Rgba32> temp = new(2048, 2048))
{ {
temp.Save(path, encoder); temp.Save(path, encoder);
} }
using var image = Image.Load<Rgba32>(configuration, path); DecoderOptions options = new()
{
Configuration = configuration
};
using var image = Image.Load<Rgba32>(options, path);
File.Delete(path); File.Delete(path);
Assert.Equal(1, image.GetPixelMemoryGroup().Count); Assert.Equal(1, image.GetPixelMemoryGroup().Count);
} }

20
tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs

@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
WebpLossy WebpLossy
} }
private static readonly Dictionary<ExifTag, object> TestProfileValues = new Dictionary<ExifTag, object> private static readonly Dictionary<ExifTag, object> TestProfileValues = new()
{ {
{ ExifTag.Software, "Software" }, { ExifTag.Software, "Software" },
{ ExifTag.Copyright, "Copyright" }, { ExifTag.Copyright, "Copyright" },
@ -125,8 +125,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
[InlineData(TestImageWriteFormat.WebpLossy)] [InlineData(TestImageWriteFormat.WebpLossy)]
public void WriteFraction(TestImageWriteFormat imageFormat) public void WriteFraction(TestImageWriteFormat imageFormat)
{ {
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
double exposureTime = 1.0 / 1600; double exposureTime = 1.0 / 1600;
ExifProfile profile = GetExifProfile(); ExifProfile profile = GetExifProfile();
@ -161,7 +160,6 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
image.Dispose(); image.Dispose();
} }
}
[Theory] [Theory]
[InlineData(TestImageWriteFormat.Jpeg)] [InlineData(TestImageWriteFormat.Jpeg)]
@ -553,38 +551,32 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
private static Image<Rgba32> WriteAndReadJpeg(Image<Rgba32> image) private static Image<Rgba32> WriteAndReadJpeg(Image<Rgba32> image)
{ {
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
image.SaveAsJpeg(memStream); image.SaveAsJpeg(memStream);
image.Dispose(); image.Dispose();
memStream.Position = 0; memStream.Position = 0;
return Image.Load<Rgba32>(memStream); return Image.Load<Rgba32>(memStream);
} }
}
private static Image<Rgba32> WriteAndReadPng(Image<Rgba32> image) private static Image<Rgba32> WriteAndReadPng(Image<Rgba32> image)
{ {
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
image.SaveAsPng(memStream); image.SaveAsPng(memStream);
image.Dispose(); image.Dispose();
memStream.Position = 0; memStream.Position = 0;
return Image.Load<Rgba32>(memStream); return Image.Load<Rgba32>(memStream);
} }
}
private static Image<Rgba32> WriteAndReadWebp(Image<Rgba32> image, WebpFileFormatType fileFormat) private static Image<Rgba32> WriteAndReadWebp(Image<Rgba32> image, WebpFileFormatType fileFormat)
{ {
using (var memStream = new MemoryStream()) using var memStream = new MemoryStream();
{
image.SaveAsWebp(memStream, new WebpEncoder() { FileFormat = fileFormat }); image.SaveAsWebp(memStream, new WebpEncoder() { FileFormat = fileFormat });
image.Dispose(); image.Dispose();
memStream.Position = 0; memStream.Position = 0;
return Image.Load<Rgba32>(memStream, new WebpDecoder()); return Image.Load<Rgba32>(memStream);
}
} }
private static void TestProfile(ExifProfile profile) private static void TestProfile(ExifProfile profile)

30
tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs

@ -15,9 +15,9 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
public class IptcProfileTests public class IptcProfileTests
{ {
private static JpegDecoder JpegDecoder => new JpegDecoder() { IgnoreMetadata = false }; private static JpegDecoder JpegDecoder => new();
private static TiffDecoder TiffDecoder => new TiffDecoder() { IgnoreMetadata = false }; private static TiffDecoder TiffDecoder => new();
public static IEnumerable<object[]> AllIptcTags() public static IEnumerable<object[]> AllIptcTags()
{ {
@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
// arrange // arrange
var profile = new IptcProfile(); var profile = new IptcProfile();
var value = new string('s', tag.MaxLength() + 1); string value = new('s', tag.MaxLength() + 1);
int expectedLength = tag.MaxLength(); int expectedLength = tag.MaxLength();
// act // act
@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
// arrange // arrange
var profile = new IptcProfile(); var profile = new IptcProfile();
var value = new string('s', tag.MaxLength() + 1); string value = new('s', tag.MaxLength() + 1);
int expectedLength = value.Length; int expectedLength = value.Length;
// act // act
@ -164,8 +164,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
// arrange // arrange
var profile = new IptcProfile(); var profile = new IptcProfile();
var expectedCaptionWriter = "unittest"; const string expectedCaptionWriter = "unittest";
var expectedCaption = "test"; const string expectedCaption = "test";
profile.SetValue(IptcTag.CaptionWriter, expectedCaptionWriter); profile.SetValue(IptcTag.CaptionWriter, expectedCaptionWriter);
profile.SetValue(IptcTag.Caption, expectedCaption); profile.SetValue(IptcTag.Caption, expectedCaption);
@ -185,8 +185,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
// arrange // arrange
var profile = new IptcProfile(); var profile = new IptcProfile();
var captionWriter = "unittest"; const string captionWriter = "unittest";
var caption = "test"; const string caption = "test";
profile.SetValue(IptcTag.CaptionWriter, captionWriter); profile.SetValue(IptcTag.CaptionWriter, captionWriter);
profile.SetValue(IptcTag.Caption, caption); profile.SetValue(IptcTag.Caption, caption);
@ -222,8 +222,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
// arrange // arrange
var image = new Image<Rgba32>(1, 1); var image = new Image<Rgba32>(1, 1);
image.Metadata.IptcProfile = new IptcProfile(); image.Metadata.IptcProfile = new IptcProfile();
var expectedCaptionWriter = "unittest"; const string expectedCaptionWriter = "unittest";
var expectedCaption = "test"; const string expectedCaption = "test";
image.Metadata.IptcProfile.SetValue(IptcTag.CaptionWriter, expectedCaptionWriter); image.Metadata.IptcProfile.SetValue(IptcTag.CaptionWriter, expectedCaptionWriter);
image.Metadata.IptcProfile.SetValue(IptcTag.Caption, expectedCaption); image.Metadata.IptcProfile.SetValue(IptcTag.Caption, expectedCaption);
@ -257,8 +257,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
// arrange // arrange
var profile = new IptcProfile(); var profile = new IptcProfile();
var expectedValue1 = "test"; const string expectedValue1 = "test";
var expectedValue2 = "another one"; const string expectedValue2 = "another one";
profile.SetValue(tag, expectedValue1, false); profile.SetValue(tag, expectedValue1, false);
// act // act
@ -309,7 +309,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{ {
// arrange // arrange
var profile = new IptcProfile(); var profile = new IptcProfile();
var expectedValue = "another one"; const string expectedValue = "another one";
profile.SetValue(tag, "test", false); profile.SetValue(tag, "test", false);
// act // act
@ -330,7 +330,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
profile.SetValue(IptcTag.Byline, "test2"); profile.SetValue(IptcTag.Byline, "test2");
// act // act
var result = profile.RemoveValue(IptcTag.Byline); bool result = profile.RemoveValue(IptcTag.Byline);
// assert // assert
Assert.True(result, "removed result should be true"); Assert.True(result, "removed result should be true");
@ -346,7 +346,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
profile.SetValue(IptcTag.Byline, "test2"); profile.SetValue(IptcTag.Byline, "test2");
// act // act
var result = profile.RemoveValue(IptcTag.Byline, "test2"); bool result = profile.RemoveValue(IptcTag.Byline, "test2");
// assert // assert
Assert.True(result, "removed result should be true"); Assert.True(result, "removed result should be true");

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

@ -20,15 +20,15 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Xmp
{ {
public class XmpProfileTests public class XmpProfileTests
{ {
private static GifDecoder GifDecoder => new() { IgnoreMetadata = false }; private static GifDecoder GifDecoder => new();
private static JpegDecoder JpegDecoder => new() { IgnoreMetadata = false }; private static JpegDecoder JpegDecoder => new();
private static PngDecoder PngDecoder => new() { IgnoreMetadata = false }; private static PngDecoder PngDecoder => new();
private static TiffDecoder TiffDecoder => new() { IgnoreMetadata = false }; private static TiffDecoder TiffDecoder => new();
private static WebpDecoder WebpDecoder => new() { IgnoreMetadata = false }; private static WebpDecoder WebpDecoder => new();
[Theory] [Theory]
[WithFile(TestImages.Gif.Receipt, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Receipt, PixelTypes.Rgba32)]

17
tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
{ {
} }
public static readonly TheoryData<string, int> DecodeJpegData = new TheoryData<string, int> public static readonly TheoryData<string, int> DecodeJpegData = new()
{ {
{ TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome, 20 }, { TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome, 20 },
{ TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr, 20 }, { TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr, 20 },
@ -38,16 +38,17 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
[MemberData(nameof(DecodeJpegData))] [MemberData(nameof(DecodeJpegData))]
public void DecodeJpeg(string fileName, int executionCount) public void DecodeJpeg(string fileName, int executionCount)
{ {
var decoder = new JpegDecoder() DecoderOptions options = new()
{ {
IgnoreMetadata = true SkipMetadata = true
}; };
this.DecodeJpegBenchmarkImpl(fileName, decoder, executionCount);
this.DecodeJpegBenchmarkImpl(fileName, options, executionCount);
} }
private void DecodeJpegBenchmarkImpl(string fileName, IImageDecoder decoder, int executionCount) private void DecodeJpegBenchmarkImpl(string fileName, DecoderOptions options, int executionCount)
{ {
// do not run this on CI even by accident // Do not run this on CI even by accident
if (TestEnvironment.RunsOnCI) if (TestEnvironment.RunsOnCI)
{ {
return; return;
@ -65,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
executionCount, executionCount,
() => () =>
{ {
var img = Image.Load<Rgba32>(bytes, decoder); var img = Image.Load<Rgba32>(options, bytes);
img.Dispose(); img.Dispose();
}, },
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line #pragma warning disable SA1515 // Single-line comment should be preceded by blank line
@ -124,7 +125,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
}, },
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line #pragma warning disable SA1515 // Single-line comment should be preceded by blank line
// ReSharper disable once ExplicitCallerInfoArgument // ReSharper disable once ExplicitCallerInfoArgument
$@"Encode {testFiles.Length} images"); $"Encode {testFiles.Length} images");
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line #pragma warning restore SA1515 // Single-line comment should be preceded by blank line
} }

12
tests/ImageSharp.Tests/ProfilingBenchmarks/LoadResizeSaveProfilingBenchmarks.cs

@ -2,6 +2,7 @@
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using Xunit; using Xunit;
@ -23,15 +24,19 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
var configuration = Configuration.CreateDefaultInstance(); var configuration = Configuration.CreateDefaultInstance();
configuration.MaxDegreeOfParallelism = 1; configuration.MaxDegreeOfParallelism = 1;
DecoderOptions options = new()
{
Configuration = configuration
};
byte[] imageBytes = TestFile.Create(imagePath).Bytes; byte[] imageBytes = TestFile.Create(imagePath).Bytes;
using (var ms = new MemoryStream()) using var ms = new MemoryStream();
{
this.Measure( this.Measure(
30, 30,
() => () =>
{ {
using (var image = Image.Load(configuration, imageBytes)) using (var image = Image.Load(options, imageBytes))
{ {
image.Mutate(x => x.Resize(image.Size() / 4)); image.Mutate(x => x.Resize(image.Size() / 4));
image.SaveAsJpeg(ms); image.SaveAsJpeg(ms);
@ -41,5 +46,4 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
}); });
} }
} }
}
} }

56
tests/ImageSharp.Tests/TestFile.cs

@ -13,18 +13,18 @@ namespace SixLabors.ImageSharp.Tests
/// <summary> /// <summary>
/// A test image file. /// A test image file.
/// </summary> /// </summary>
public class TestFile public sealed class TestFile
{ {
/// <summary> /// <summary>
/// The test file cache. /// The test file cache.
/// </summary> /// </summary>
private static readonly ConcurrentDictionary<string, TestFile> Cache = new ConcurrentDictionary<string, TestFile>(); private static readonly ConcurrentDictionary<string, TestFile> Cache = new();
/// <summary> /// <summary>
/// The "Formats" directory, as lazy value /// The "Formats" directory, as lazy value
/// </summary> /// </summary>
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
private static readonly Lazy<string> InputImagesDirectoryValue = new Lazy<string>(() => TestEnvironment.InputImagesDirectoryFullPath); private static readonly Lazy<string> InputImagesDirectoryValue = new(() => TestEnvironment.InputImagesDirectoryFullPath);
/// <summary> /// <summary>
/// The image (lazy initialized value) /// The image (lazy initialized value)
@ -40,15 +40,12 @@ namespace SixLabors.ImageSharp.Tests
/// Initializes a new instance of the <see cref="TestFile"/> class. /// Initializes a new instance of the <see cref="TestFile"/> class.
/// </summary> /// </summary>
/// <param name="file">The file.</param> /// <param name="file">The file.</param>
private TestFile(string file) private TestFile(string file) => this.FullPath = file;
{
this.FullPath = file;
}
/// <summary> /// <summary>
/// Gets the image bytes. /// Gets the image bytes.
/// </summary> /// </summary>
public byte[] Bytes => this.bytes ?? (this.bytes = File.ReadAllBytes(this.FullPath)); public byte[] Bytes => this.bytes ??= File.ReadAllBytes(this.FullPath);
/// <summary> /// <summary>
/// Gets the full path to file. /// Gets the full path to file.
@ -68,7 +65,7 @@ namespace SixLabors.ImageSharp.Tests
/// <summary> /// <summary>
/// Gets the image with lazy initialization. /// Gets the image with lazy initialization.
/// </summary> /// </summary>
private Image<Rgba32> Image => this.image ?? (this.image = ImageSharp.Image.Load<Rgba32>(this.Bytes)); private Image<Rgba32> Image => this.image ??= ImageSharp.Image.Load<Rgba32>(this.Bytes);
/// <summary> /// <summary>
/// Gets the input image directory. /// Gets the input image directory.
@ -85,9 +82,7 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="string"/>. /// The <see cref="string"/>.
/// </returns> /// </returns>
public static string GetInputFileFullPath(string file) public static string GetInputFileFullPath(string file)
{ => Path.Combine(InputImagesDirectory, file).Replace('\\', Path.DirectorySeparatorChar);
return Path.Combine(InputImagesDirectory, file).Replace('\\', Path.DirectorySeparatorChar);
}
/// <summary> /// <summary>
/// Creates a new test file or returns one from the cache. /// Creates a new test file or returns one from the cache.
@ -97,9 +92,7 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="TestFile"/>. /// The <see cref="TestFile"/>.
/// </returns> /// </returns>
public static TestFile Create(string file) public static TestFile Create(string file)
{ => Cache.GetOrAdd(file, (string fileName) => new TestFile(GetInputFileFullPath(fileName)));
return Cache.GetOrAdd(file, (string fileName) => new TestFile(GetInputFileFullPath(file)));
}
/// <summary> /// <summary>
/// Gets the file name. /// Gets the file name.
@ -109,9 +102,7 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="string"/>. /// The <see cref="string"/>.
/// </returns> /// </returns>
public string GetFileName(object value) public string GetFileName(object value)
{ => $"{this.FileNameWithoutExtension}-{value}{Path.GetExtension(this.FullPath)}";
return $"{this.FileNameWithoutExtension}-{value}{Path.GetExtension(this.FullPath)}";
}
/// <summary> /// <summary>
/// Gets the file name without extension. /// Gets the file name without extension.
@ -121,30 +112,37 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="string"/>. /// The <see cref="string"/>.
/// </returns> /// </returns>
public string GetFileNameWithoutExtension(object value) public string GetFileNameWithoutExtension(object value)
{ => this.FileNameWithoutExtension + "-" + value;
return this.FileNameWithoutExtension + "-" + value;
}
/// <summary> /// <summary>
/// Creates a new image. /// Creates a new <see cref="Rgba32"/> image.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The <see cref="ImageSharp.Image"/>. /// The <see cref="Image{Rgba32}"/>.
/// </returns> /// </returns>
public Image<Rgba32> CreateRgba32Image() public Image<Rgba32> CreateRgba32Image()
{ => this.Image.Clone();
return this.Image.Clone();
}
/// <summary> /// <summary>
/// Creates a new image. /// Creates a new <see cref="Rgba32"/> image.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The <see cref="ImageSharp.Image"/>. /// The <see cref="Image{Rgba32}"/>.
/// </returns> /// </returns>
public Image<Rgba32> CreateRgba32Image(IImageDecoder decoder) public Image<Rgba32> CreateRgba32Image(IImageDecoder decoder)
=> this.CreateRgba32Image(decoder, new());
/// <summary>
/// Creates a new <see cref="Rgba32"/> image.
/// </summary>
/// <returns>
/// The <see cref="Image{Rgba32}"/>.
/// </returns>
public Image<Rgba32> CreateRgba32Image(IImageDecoder decoder, DecoderOptions options)
{ {
return ImageSharp.Image.Load<Rgba32>(this.Image.GetConfiguration(), this.Bytes, decoder); options.Configuration = this.Image.GetConfiguration();
using MemoryStream stream = new(this.Bytes);
return decoder.Decode<Rgba32>(options, stream, default);
} }
} }
} }

36
tests/ImageSharp.Tests/TestFormat.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests
/// </summary> /// </summary>
public class TestFormat : IConfigurationModule, IImageFormat public class TestFormat : IConfigurationModule, IImageFormat
{ {
private readonly Dictionary<Type, object> sampleImages = new Dictionary<Type, object>(); private readonly Dictionary<Type, object> sampleImages = new();
// We should not change Configuration.Default in individual tests! // We should not change Configuration.Default in individual tests!
// Create new configuration instances with new Configuration(TestFormat.GlobalTestFormat) instead! // Create new configuration instances with new Configuration(TestFormat.GlobalTestFormat) instead!
@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests
public Stream CreateAsyncSemaphoreStream(SemaphoreSlim notifyWaitPositionReachedSemaphore, SemaphoreSlim continueSemaphore, bool seeakable, int size = 1024, int waitAfterPosition = 512) public Stream CreateAsyncSemaphoreStream(SemaphoreSlim notifyWaitPositionReachedSemaphore, SemaphoreSlim continueSemaphore, bool seeakable, int size = 1024, int waitAfterPosition = 512)
{ {
var buffer = new byte[size]; byte[] buffer = new byte[size];
this.header.CopyTo(buffer, 0); this.header.CopyTo(buffer, 0);
var semaphoreStream = new SemaphoreReadMemoryStream(buffer, waitAfterPosition, notifyWaitPositionReachedSemaphore, continueSemaphore); var semaphoreStream = new SemaphoreReadMemoryStream(buffer, waitAfterPosition, notifyWaitPositionReachedSemaphore, continueSemaphore);
return seeakable ? semaphoreStream : new AsyncStreamWrapper(semaphoreStream, () => false); return seeakable ? semaphoreStream : new AsyncStreamWrapper(semaphoreStream, () => false);
@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests
{ {
DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config, typeof(TPixel))).ToArray(); DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config, typeof(TPixel))).ToArray();
Assert.True(discovered.Any(), "No calls to decode on this format with the provided options happened"); Assert.True(discovered.Length > 0, "No calls to decode on this format with the provided options happened");
foreach (DecodeOperation d in discovered) foreach (DecodeOperation d in discovered)
{ {
@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests
{ {
DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config, typeof(TestPixelForAgnosticDecode))).ToArray(); DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config, typeof(TestPixelForAgnosticDecode))).ToArray();
Assert.True(discovered.Any(), "No calls to decode on this format with the provided options happened"); Assert.True(discovered.Length > 0, "No calls to decode on this format with the provided options happened");
foreach (DecodeOperation d in discovered) foreach (DecodeOperation d in discovered)
{ {
@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.Tests
public TestHeader(TestFormat testFormat) => this.testFormat = testFormat; public TestHeader(TestFormat testFormat) => this.testFormat = testFormat;
} }
public class TestDecoder : IImageDecoder, IImageInfoDetector public class TestDecoder : ImageDecoder<TestDecoderOptions>
{ {
private readonly TestFormat testFormat; private readonly TestFormat testFormat;
@ -206,20 +206,21 @@ namespace SixLabors.ImageSharp.Tests
public int HeaderSize => this.testFormat.HeaderSize; public int HeaderSize => this.testFormat.HeaderSize;
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public bool IsSupportedFileFormat(Span<byte> header) => this.testFormat.IsSupportedFileFormat(header);
where TPixel : unmanaged, IPixel<TPixel>
=> this.DecodeImpl<TPixel>(configuration, stream);
private Image<TPixel> DecodeImpl<TPixel>(Configuration config, Stream stream) public override IImageInfo IdentifySpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> => this.DecodeSpecialized<TestPixelForAgnosticDecode>(options, stream, cancellationToken);
public override Image<TPixel> DecodeSpecialized<TPixel>(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{ {
Configuration configuration = options.GeneralOptions.Configuration;
var ms = new MemoryStream(); var ms = new MemoryStream();
stream.CopyTo(ms, config.StreamProcessingBufferSize); stream.CopyTo(ms, configuration.StreamProcessingBufferSize);
byte[] marker = ms.ToArray().Skip(this.testFormat.header.Length).ToArray(); byte[] marker = ms.ToArray().Skip(this.testFormat.header.Length).ToArray();
this.testFormat.DecodeCalls.Add(new DecodeOperation this.testFormat.DecodeCalls.Add(new DecodeOperation
{ {
Marker = marker, Marker = marker,
Config = config, Config = configuration,
PixelType = typeof(TPixel) PixelType = typeof(TPixel)
}); });
@ -227,12 +228,13 @@ namespace SixLabors.ImageSharp.Tests
return this.testFormat.Sample<TPixel>(); return this.testFormat.Sample<TPixel>();
} }
public bool IsSupportedFileFormat(Span<byte> header) => this.testFormat.IsSupportedFileFormat(header); public override Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<TestPixelForAgnosticDecode>(options, stream, cancellationToken);
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<TestPixelForAgnosticDecode>(configuration, stream, cancellationToken); }
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) => public class TestDecoderOptions : ISpecializedDecoderOptions
this.DecodeImpl<Rgba32>(configuration, stream); {
public DecoderOptions GeneralOptions { get; set; } = new();
} }
public class TestEncoder : IImageEncoder public class TestEncoder : IImageEncoder

77
tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs

@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Diagnostics;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -90,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests
return false; return false;
} }
if (!object.Equals(kv.Value, otherVal)) if (!Equals(kv.Value, otherVal))
{ {
return false; return false;
} }
@ -126,7 +125,7 @@ namespace SixLabors.ImageSharp.Tests
public static bool operator !=(Key left, Key right) => !Equals(left, right); public static bool operator !=(Key left, Key right) => !Equals(left, right);
} }
private static readonly ConcurrentDictionary<Key, Image<TPixel>> Cache = new ConcurrentDictionary<Key, Image<TPixel>>(); private static readonly ConcurrentDictionary<Key, Image<TPixel>> Cache = new();
// Needed for deserialization! // Needed for deserialization!
// ReSharper disable once UnusedMember.Local // ReSharper disable once UnusedMember.Local
@ -149,35 +148,78 @@ namespace SixLabors.ImageSharp.Tests
return this.GetImage(decoder); return this.GetImage(decoder);
} }
public override Image<TPixel> GetImage(IImageDecoder decoder) public override Image<TPixel> GetImage(IImageDecoder decoder, DecoderOptions options)
{ {
Guard.NotNull(decoder, nameof(decoder)); Guard.NotNull(decoder, nameof(decoder));
Guard.NotNull(options, nameof(options));
// Do not cache with 64 bits or if image has been created with non-default MemoryAllocator // Do not cache with 64 bits or if image has been created with non-default MemoryAllocator
if (!TestEnvironment.Is64BitProcess || this.Configuration.MemoryAllocator != MemoryAllocator.Default) if (!TestEnvironment.Is64BitProcess || this.Configuration.MemoryAllocator != MemoryAllocator.Default)
{ {
return this.LoadImage(decoder); return this.DecodeImage(decoder, options);
} }
// do not cache so we can track allocation correctly when validating memory // do not cache so we can track allocation correctly when validating memory
if (MemoryAllocatorValidator.MonitoringAllocations) if (MemoryAllocatorValidator.MonitoringAllocations)
{ {
return this.LoadImage(decoder); return this.DecodeImage(decoder, options);
} }
var key = new Key(this.PixelType, this.FilePath, decoder); var key = new Key(this.PixelType, this.FilePath, decoder);
Image<TPixel> cachedImage = Cache.GetOrAdd(key, _ => this.LoadImage(decoder)); Image<TPixel> cachedImage = Cache.GetOrAdd(key, _ => this.DecodeImage(decoder, options));
return cachedImage.Clone(this.Configuration); return cachedImage.Clone(this.Configuration);
} }
public override Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder) public override Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder, DecoderOptions options)
{ {
Guard.NotNull(decoder, nameof(decoder)); Guard.NotNull(decoder, nameof(decoder));
Guard.NotNull(options, nameof(options));
options.Configuration = this.Configuration;
// Used in small subset of decoder tests, no caching. // Used in small subset of decoder tests, no caching.
// TODO: Check Path here. Why combined?
string path = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.FilePath); string path = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.FilePath);
return Image.LoadAsync<TPixel>(this.Configuration, path, decoder); using Stream stream = System.IO.File.OpenRead(path);
return Task.FromResult(decoder.Decode<TPixel>(options, stream, default));
}
public override Image<TPixel> GetImage<T>(ImageDecoder<T> decoder, T options)
{
Guard.NotNull(decoder, nameof(decoder));
Guard.NotNull(options, nameof(options));
// Do not cache with 64 bits or if image has been created with non-default MemoryAllocator
if (!TestEnvironment.Is64BitProcess || this.Configuration.MemoryAllocator != MemoryAllocator.Default)
{
return this.DecodeImage(decoder, options);
}
// do not cache so we can track allocation correctly when validating memory
if (MemoryAllocatorValidator.MonitoringAllocations)
{
return this.DecodeImage(decoder, options);
}
var key = new Key(this.PixelType, this.FilePath, decoder);
Image<TPixel> cachedImage = Cache.GetOrAdd(key, _ => this.DecodeImage(decoder, options));
return cachedImage.Clone(this.Configuration);
}
public override Task<Image<TPixel>> GetImageAsync<T>(ImageDecoder<T> decoder, T options)
{
Guard.NotNull(decoder, nameof(decoder));
Guard.NotNull(options, nameof(options));
options.GeneralOptions.Configuration = this.Configuration;
// Used in small subset of decoder tests, no caching.
// 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<TPixel>(options, stream, default));
} }
public override void Deserialize(IXunitSerializationInfo info) public override void Deserialize(IXunitSerializationInfo info)
@ -193,10 +235,23 @@ namespace SixLabors.ImageSharp.Tests
info.AddValue("path", this.FilePath); info.AddValue("path", this.FilePath);
} }
private Image<TPixel> LoadImage(IImageDecoder decoder) private Image<TPixel> DecodeImage(IImageDecoder decoder, DecoderOptions options)
{
options.Configuration = this.Configuration;
var testFile = TestFile.Create(this.FilePath);
using Stream stream = new MemoryStream(testFile.Bytes);
return decoder.Decode<TPixel>(options, stream, default);
}
private Image<TPixel> DecodeImage<T>(ImageDecoder<T> decoder, T options)
where T : class, ISpecializedDecoderOptions, new()
{ {
options.GeneralOptions.Configuration = this.Configuration;
var testFile = TestFile.Create(this.FilePath); var testFile = TestFile.Create(this.FilePath);
return Image.Load<TPixel>(this.Configuration, testFile.Bytes, decoder); using Stream stream = new MemoryStream(testFile.Bytes);
return decoder.DecodeSpecialized<TPixel>(options, stream, default);
} }
} }

43
tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs

@ -63,9 +63,7 @@ namespace SixLabors.ImageSharp.Tests
string filePath, string filePath,
MethodInfo testMethod = null, MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined) PixelTypes pixelTypeOverride = PixelTypes.Undefined)
{ => new FileProvider(filePath).Init(testMethod, pixelTypeOverride);
return new FileProvider(filePath).Init(testMethod, pixelTypeOverride);
}
public static TestImageProvider<TPixel> Lambda( public static TestImageProvider<TPixel> Lambda(
string declaringTypeName, string declaringTypeName,
@ -83,9 +81,7 @@ namespace SixLabors.ImageSharp.Tests
byte a = 255, byte a = 255,
MethodInfo testMethod = null, MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined) PixelTypes pixelTypeOverride = PixelTypes.Undefined)
{ => new SolidProvider(width, height, r, g, b, a).Init(testMethod, pixelTypeOverride);
return new SolidProvider(width, height, r, g, b, a).Init(testMethod, pixelTypeOverride);
}
/// <summary> /// <summary>
/// Returns an <see cref="Image{TPixel}"/> instance to the test case with the necessary traits. /// Returns an <see cref="Image{TPixel}"/> instance to the test case with the necessary traits.
@ -93,15 +89,25 @@ namespace SixLabors.ImageSharp.Tests
/// <returns>A test image.</returns> /// <returns>A test image.</returns>
public abstract Image<TPixel> GetImage(); public abstract Image<TPixel> GetImage();
public virtual Image<TPixel> GetImage(IImageDecoder decoder) public Image<TPixel> GetImage(IImageDecoder decoder)
{ => this.GetImage(decoder, new());
throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!");
}
public virtual Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder) public Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder)
{ => this.GetImageAsync(decoder, new());
throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!");
} public virtual Image<TPixel> GetImage(IImageDecoder decoder, DecoderOptions options)
=> throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!");
public virtual Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder, DecoderOptions options)
=> throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!");
public virtual Image<TPixel> GetImage<T>(ImageDecoder<T> decoder, T options)
where T : class, ISpecializedDecoderOptions, new()
=> throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!");
public virtual Task<Image<TPixel>> GetImageAsync<T>(ImageDecoder<T> decoder, T options)
where T : class, ISpecializedDecoderOptions, new()
=> throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!");
/// <summary> /// <summary>
/// Returns an <see cref="Image{TPixel}"/> instance to the test case with the necessary traits. /// Returns an <see cref="Image{TPixel}"/> instance to the test case with the necessary traits.
@ -163,14 +169,13 @@ namespace SixLabors.ImageSharp.Tests
protected TestImageProvider<TPixel> Init(MethodInfo testMethod, PixelTypes pixelTypeOverride) protected TestImageProvider<TPixel> Init(MethodInfo testMethod, PixelTypes pixelTypeOverride)
{ {
string subfolder = testMethod?.DeclaringType.GetAttribute<GroupOutputAttribute>()?.Subfolder string subfolder =
?? string.Empty; testMethod?.DeclaringType.GetAttribute<GroupOutputAttribute>()?.Subfolder ?? string.Empty;
return this.Init(testMethod?.DeclaringType.Name, testMethod?.Name, subfolder, pixelTypeOverride); return this.Init(testMethod?.DeclaringType.Name, testMethod?.Name, subfolder, pixelTypeOverride);
} }
public override string ToString() public override string ToString()
{ => $"{this.SourceFileOrDescription}[{this.PixelType}]";
return $"{this.SourceFileOrDescription}[{this.PixelType}]";
}
} }
} }

77
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs

@ -15,7 +15,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{ {
public class MagickReferenceDecoder : IImageDecoder public class MagickReferenceDecoder : ImageDecoder<MagickReferenceDecoderOptions>
{ {
private readonly bool validate; private readonly bool validate;
@ -28,39 +28,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder(); public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder();
private static void FromRgba32Bytes<TPixel>(Configuration configuration, Span<byte> rgbaBytes, IMemoryGroup<TPixel> destinationGroup) public override Image<TPixel> DecodeSpecialized<TPixel>(MagickReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{
Span<Rgba32> sourcePixels = MemoryMarshal.Cast<byte, Rgba32>(rgbaBytes);
foreach (Memory<TPixel> m in destinationGroup)
{
Span<TPixel> destBuffer = m.Span;
PixelOperations<TPixel>.Instance.FromRgba32(
configuration,
sourcePixels.Slice(0, destBuffer.Length),
destBuffer);
sourcePixels = sourcePixels.Slice(destBuffer.Length);
}
}
private static void FromRgba64Bytes<TPixel>(Configuration configuration, Span<byte> rgbaBytes, IMemoryGroup<TPixel> destinationGroup)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{
foreach (Memory<TPixel> m in destinationGroup)
{
Span<TPixel> destBuffer = m.Span;
PixelOperations<TPixel>.Instance.FromRgba64Bytes(
configuration,
rgbaBytes,
destBuffer,
destBuffer.Length);
rgbaBytes = rgbaBytes.Slice(destBuffer.Length * 8);
}
}
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{ {
Configuration configuration = options.GeneralOptions.Configuration;
var bmpReadDefines = new BmpReadDefines var bmpReadDefines = new BmpReadDefines
{ {
IgnoreFileSize = !this.validate IgnoreFileSize = !this.validate
@ -100,6 +70,45 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
return new Image<TPixel>(configuration, new ImageMetadata(), framesList); return new Image<TPixel>(configuration, new ImageMetadata(), framesList);
} }
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken); public override Image DecodeSpecialized(MagickReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
public override IImageInfo IdentifySpecialized(MagickReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
private static void FromRgba32Bytes<TPixel>(Configuration configuration, Span<byte> rgbaBytes, IMemoryGroup<TPixel> destinationGroup)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{
Span<Rgba32> sourcePixels = MemoryMarshal.Cast<byte, Rgba32>(rgbaBytes);
foreach (Memory<TPixel> m in destinationGroup)
{
Span<TPixel> destBuffer = m.Span;
PixelOperations<TPixel>.Instance.FromRgba32(
configuration,
sourcePixels.Slice(0, destBuffer.Length),
destBuffer);
sourcePixels = sourcePixels.Slice(destBuffer.Length);
}
}
private static void FromRgba64Bytes<TPixel>(Configuration configuration, Span<byte> rgbaBytes, IMemoryGroup<TPixel> destinationGroup)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{
foreach (Memory<TPixel> m in destinationGroup)
{
Span<TPixel> destBuffer = m.Span;
PixelOperations<TPixel>.Instance.FromRgba64Bytes(
configuration,
rgbaBytes,
destBuffer,
destBuffer.Length);
rgbaBytes = rgbaBytes.Slice(destBuffer.Length * 8);
}
}
}
public class MagickReferenceDecoderOptions : ISpecializedDecoderOptions
{
public DecoderOptions GeneralOptions { get; set; } = new();
} }
} }

35
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs

@ -6,28 +6,34 @@ using System.Threading;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SDBitmap = System.Drawing.Bitmap;
using SDImage = System.Drawing.Image;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{ {
public class SystemDrawingReferenceDecoder : IImageDecoder, IImageInfoDetector public class SystemDrawingReferenceDecoder : ImageDecoder<SystemDrawingReferenceDecoderOptions>
{ {
public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder(); public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder();
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public override IImageInfo IdentifySpecialized(SystemDrawingReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{ {
using (var sourceBitmap = new System.Drawing.Bitmap(stream)) 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<TPixel> DecodeSpecialized<TPixel>(SystemDrawingReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{ {
using var sourceBitmap = new SDBitmap(stream);
if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb)
{ {
return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sourceBitmap); return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sourceBitmap);
} }
using (var convertedBitmap = new System.Drawing.Bitmap( using var convertedBitmap = new SDBitmap(
sourceBitmap.Width, sourceBitmap.Width,
sourceBitmap.Height, sourceBitmap.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb)) System.Drawing.Imaging.PixelFormat.Format32bppArgb);
{
using (var g = System.Drawing.Graphics.FromImage(convertedBitmap)) using (var g = System.Drawing.Graphics.FromImage(convertedBitmap))
{ {
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
@ -40,18 +46,13 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(convertedBitmap); return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(convertedBitmap);
} }
}
}
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) public override Image DecodeSpecialized(SystemDrawingReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{ => this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{
var pixelType = new PixelTypeInfo(System.Drawing.Image.GetPixelFormatSize(sourceBitmap.PixelFormat));
return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata());
}
} }
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken); public class SystemDrawingReferenceDecoderOptions : ISpecializedDecoderOptions
{
public DecoderOptions GeneralOptions { get; set; } = new();
} }
} }

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

@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests
{ {
public static partial class TestEnvironment public static partial class TestEnvironment
{ {
private static readonly Lazy<Configuration> ConfigurationLazy = new Lazy<Configuration>(CreateDefaultConfiguration); private static readonly Lazy<Configuration> ConfigurationLazy = new(CreateDefaultConfiguration);
internal static Configuration Configuration => ConfigurationLazy.Value; internal static Configuration Configuration => ConfigurationLazy.Value;

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

@ -327,7 +327,8 @@ namespace SixLabors.ImageSharp.Tests
decoder ??= TestEnvironment.GetReferenceDecoder(referenceOutputFile); decoder ??= TestEnvironment.GetReferenceDecoder(referenceOutputFile);
return Image.Load<TPixel>(referenceOutputFile, decoder); using FileStream stream = File.OpenRead(referenceOutputFile);
return decoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
} }
public static Image<TPixel> GetReferenceOutputImageMultiFrame<TPixel>( public static Image<TPixel> GetReferenceOutputImageMultiFrame<TPixel>(
@ -355,7 +356,8 @@ namespace SixLabors.ImageSharp.Tests
throw new Exception("Reference output file missing: " + path); throw new Exception("Reference output file missing: " + path);
} }
var tempImage = Image.Load<TPixel>(path, decoder); using FileStream stream = File.OpenRead(path);
Image<TPixel> tempImage = decoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
temporaryFrameImages.Add(tempImage); temporaryFrameImages.Add(tempImage);
} }
@ -383,14 +385,12 @@ namespace SixLabors.ImageSharp.Tests
bool appendPixelTypeToFileName = true) bool appendPixelTypeToFileName = true)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>( using Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(
testOutputDetails, testOutputDetails,
extension, extension,
appendPixelTypeToFileName)) appendPixelTypeToFileName);
{
return comparer.CompareImages(referenceImage, image); return comparer.CompareImages(referenceImage, image);
} }
}
public static Image<TPixel> ComparePixelBufferTo<TPixel>( public static Image<TPixel> ComparePixelBufferTo<TPixel>(
this Image<TPixel> image, this Image<TPixel> image,
@ -534,9 +534,10 @@ namespace SixLabors.ImageSharp.Tests
var testFile = TestFile.Create(path); var testFile = TestFile.Create(path);
referenceDecoder = referenceDecoder ?? TestEnvironment.GetReferenceDecoder(path); referenceDecoder ??= TestEnvironment.GetReferenceDecoder(path);
using (var original = Image.Load<TPixel>(testFile.Bytes, referenceDecoder)) using var stream = new MemoryStream(testFile.Bytes);
using (Image<TPixel> original = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default))
{ {
comparer.VerifySimilarity(original, image); comparer.VerifySimilarity(original, image);
} }
@ -559,9 +560,10 @@ namespace SixLabors.ImageSharp.Tests
var testFile = TestFile.Create(path); var testFile = TestFile.Create(path);
referenceDecoder = referenceDecoder ?? TestEnvironment.GetReferenceDecoder(path); referenceDecoder ??= TestEnvironment.GetReferenceDecoder(path);
using (var original = Image.Load<TPixel>(testFile.Bytes, referenceDecoder)) using var stream = new MemoryStream(testFile.Bytes);
using (Image<TPixel> original = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default))
{ {
comparer.VerifySimilarity(original, image); comparer.VerifySimilarity(original, image);
} }
@ -584,8 +586,7 @@ namespace SixLabors.ImageSharp.Tests
bool appendSourceFileOrDescription = true) bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
operation(image); operation(image);
image.DebugSave( image.DebugSave(
@ -601,7 +602,6 @@ namespace SixLabors.ImageSharp.Tests
appendPixelTypeToFileName: appendPixelTypeToFileName, appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription); appendSourceFileOrDescription: appendSourceFileOrDescription);
} }
}
/// <summary> /// <summary>
/// Utility method for doing the following in one step: /// Utility method for doing the following in one step:
@ -682,12 +682,12 @@ namespace SixLabors.ImageSharp.Tests
referenceDecoder ??= TestEnvironment.GetReferenceDecoder(actualOutputFile); referenceDecoder ??= TestEnvironment.GetReferenceDecoder(actualOutputFile);
using (var encodedImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder)) using FileStream stream = File.OpenRead(actualOutputFile);
{ using Image<TPixel> encodedImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
ImageComparer comparer = customComparer ?? ImageComparer.Exact; ImageComparer comparer = customComparer ?? ImageComparer.Exact;
comparer.VerifySimilarity(encodedImage, image); comparer.VerifySimilarity(encodedImage, image);
} }
}
internal static AllocatorBufferCapacityConfigurator LimitAllocatorBufferCapacity<TPixel>( internal static AllocatorBufferCapacityConfigurator LimitAllocatorBufferCapacity<TPixel>(
this TestImageProvider<TPixel> provider) this TestImageProvider<TPixel> provider)

31
tests/ImageSharp.Tests/TestUtilities/Tests/MagickReferenceCodecTests.cs

@ -1,17 +1,17 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit; using Xunit;
using Xunit.Abstractions;
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
{ {
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit.Abstractions;
public class MagickReferenceCodecTests public class MagickReferenceCodecTests
{ {
public MagickReferenceCodecTests(ITestOutputHelper output) => this.Output = output; public MagickReferenceCodecTests(ITestOutputHelper output) => this.Output = output;
@ -39,9 +39,12 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
ImageComparer comparer = ImageComparer.Exact; ImageComparer comparer = ImageComparer.Exact;
using (var mImage = Image.Load<TPixel>(path, magickDecoder)) using FileStream mStream = File.OpenRead(path);
using (var sdImage = Image.Load<TPixel>(path, sdDecoder)) using FileStream sdStream = File.OpenRead(path);
{
using Image<TPixel> mImage = magickDecoder.Decode<TPixel>(DecoderOptions.Default, mStream, default);
using Image<TPixel> sdImage = sdDecoder.Decode<TPixel>(DecoderOptions.Default, sdStream, default);
ImageSimilarityReport<TPixel, TPixel> report = comparer.CompareImagesOrFrames(mImage, sdImage); ImageSimilarityReport<TPixel, TPixel> report = comparer.CompareImagesOrFrames(mImage, sdImage);
mImage.DebugSave(dummyProvider); mImage.DebugSave(dummyProvider);
@ -51,7 +54,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
Assert.True(report.IsEmpty); Assert.True(report.IsEmpty);
} }
} }
}
[Theory] [Theory]
[WithBlankImages(1, 1, PixelTypesToTest64, TestImages.Png.Rgba64Bpp)] [WithBlankImages(1, 1, PixelTypesToTest64, TestImages.Png.Rgba64Bpp)]
@ -69,10 +71,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
// 1020 == 4 * 255 (Equivalent to manhattan distance of 1+1+1+1=4 in Rgba32 space) // 1020 == 4 * 255 (Equivalent to manhattan distance of 1+1+1+1=4 in Rgba32 space)
var comparer = ImageComparer.TolerantPercentage(1, 1020); var comparer = ImageComparer.TolerantPercentage(1, 1020);
using FileStream mStream = File.OpenRead(path);
using (var mImage = Image.Load<TPixel>(path, magickDecoder)) using FileStream sdStream = File.OpenRead(path);
using (var sdImage = Image.Load<TPixel>(path, sdDecoder)) using Image<TPixel> mImage = magickDecoder.Decode<TPixel>(DecoderOptions.Default, mStream, default);
{ using Image<TPixel> sdImage = sdDecoder.Decode<TPixel>(DecoderOptions.Default, sdStream, default);
ImageSimilarityReport<TPixel, TPixel> report = comparer.CompareImagesOrFrames(mImage, sdImage); ImageSimilarityReport<TPixel, TPixel> report = comparer.CompareImagesOrFrames(mImage, sdImage);
mImage.DebugSave(dummyProvider); mImage.DebugSave(dummyProvider);
@ -83,5 +85,4 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
} }
} }
} }
}
} }

58
tests/ImageSharp.Tests/TestUtilities/Tests/SystemDrawingReferenceCodecTests.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
@ -16,25 +18,18 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
{ {
private ITestOutputHelper Output { get; } private ITestOutputHelper Output { get; }
public SystemDrawingReferenceCodecTests(ITestOutputHelper output) public SystemDrawingReferenceCodecTests(ITestOutputHelper output) => this.Output = output;
{
this.Output = output;
}
[Theory] [Theory]
[WithTestPatternImages(20, 20, PixelTypes.Rgba32 | PixelTypes.Bgra32)] [WithTestPatternImages(20, 20, PixelTypes.Rgba32 | PixelTypes.Bgra32)]
public void To32bppArgbSystemDrawingBitmap<TPixel>(TestImageProvider<TPixel> provider) public void To32bppArgbSystemDrawingBitmap<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{ using System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image);
using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image))
{
string fileName = provider.Utility.GetTestOutputFileName("png"); string fileName = provider.Utility.GetTestOutputFileName("png");
sdBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png); sdBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
} }
}
}
[Theory] [Theory]
[WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)] [WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)]
@ -43,20 +38,15 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
{ {
string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash); string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash);
using (var sdBitmap = new System.Drawing.Bitmap(path)) using var sdBitmap = new System.Drawing.Bitmap(path);
{ using Image<TPixel> image = SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sdBitmap);
using (Image<TPixel> image = SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sdBitmap))
{
image.DebugSave(dummyProvider); image.DebugSave(dummyProvider);
} }
}
}
private static string SavePng<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType) private static string SavePng<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> sourceImage = provider.GetImage()) using Image<TPixel> sourceImage = provider.GetImage();
{
if (pngColorType != PngColorType.RgbWithAlpha) if (pngColorType != PngColorType.RgbWithAlpha)
{ {
sourceImage.Mutate(c => c.MakeOpaque()); sourceImage.Mutate(c => c.MakeOpaque());
@ -65,7 +55,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
var encoder = new PngEncoder { ColorType = pngColorType }; var encoder = new PngEncoder { ColorType = pngColorType };
return provider.Utility.SaveTestOutputFile(sourceImage, "png", encoder); return provider.Utility.SaveTestOutputFile(sourceImage, "png", encoder);
} }
}
[Theory] [Theory]
[WithTestPatternImages(100, 100, PixelTypes.Rgba32)] [WithTestPatternImages(100, 100, PixelTypes.Rgba32)]
@ -79,16 +68,12 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
string path = SavePng(provider, PngColorType.RgbWithAlpha); string path = SavePng(provider, PngColorType.RgbWithAlpha);
using (var sdBitmap = new System.Drawing.Bitmap(path)) using var sdBitmap = new System.Drawing.Bitmap(path);
{ using Image<TPixel> original = provider.GetImage();
using (Image<TPixel> original = provider.GetImage()) using Image<TPixel> resaved = SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sdBitmap);
using (Image<TPixel> resaved = SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sdBitmap))
{
ImageComparer comparer = ImageComparer.Exact; ImageComparer comparer = ImageComparer.Exact;
comparer.VerifySimilarity(original, resaved); comparer.VerifySimilarity(original, resaved);
} }
}
}
[Theory] [Theory]
[WithTestPatternImages(100, 100, PixelTypes.Rgb24)] [WithTestPatternImages(100, 100, PixelTypes.Rgb24)]
@ -97,18 +82,12 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
{ {
string path = SavePng(provider, PngColorType.Rgb); string path = SavePng(provider, PngColorType.Rgb);
using (Image<TPixel> original = provider.GetImage()) using Image<TPixel> original = provider.GetImage();
{ using var sdBitmap = new System.Drawing.Bitmap(path);
using (var sdBitmap = new System.Drawing.Bitmap(path)) using Image<TPixel> resaved = SystemDrawingBridge.From24bppRgbSystemDrawingBitmap<TPixel>(sdBitmap);
{
using (Image<TPixel> resaved = SystemDrawingBridge.From24bppRgbSystemDrawingBitmap<TPixel>(sdBitmap))
{
ImageComparer comparer = ImageComparer.Exact; ImageComparer comparer = ImageComparer.Exact;
comparer.VerifySimilarity(original, resaved); comparer.VerifySimilarity(original, resaved);
} }
}
}
}
[Theory] [Theory]
[WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)] [WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)]
@ -116,21 +95,18 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash); string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash);
using (var image = Image.Load<TPixel>(path, SystemDrawingReferenceDecoder.Instance)) using FileStream stream = File.OpenRead(path);
{ using Image<TPixel> image = SystemDrawingReferenceDecoder.Instance.Decode<TPixel>(DecoderOptions.Default, stream, default);
image.DebugSave(dummyProvider); image.DebugSave(dummyProvider);
} }
}
[Theory] [Theory]
[WithTestPatternImages(20, 20, PixelTypes.Rgba32 | PixelTypes.Argb32)] [WithTestPatternImages(20, 20, PixelTypes.Rgba32 | PixelTypes.Argb32)]
public void SaveWithReferenceEncoder<TPixel>(TestImageProvider<TPixel> provider) public void SaveWithReferenceEncoder<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
provider.Utility.SaveTestOutputFile(image, "png", SystemDrawingReferenceEncoder.Png); provider.Utility.SaveTestOutputFile(image, "png", SystemDrawingReferenceEncoder.Png);
} }
} }
}
} }

79
tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs

@ -18,13 +18,13 @@ namespace SixLabors.ImageSharp.Tests
{ {
public class TestImageProviderTests public class TestImageProviderTests
{ {
public static readonly TheoryData<object> BasicData = new TheoryData<object> public static readonly TheoryData<object> BasicData = new()
{ {
TestImageProvider<Rgba32>.Blank(10, 20), TestImageProvider<Rgba32>.Blank(10, 20),
TestImageProvider<HalfVector4>.Blank(10, 20), TestImageProvider<HalfVector4>.Blank(10, 20),
}; };
public static readonly TheoryData<object> FileData = new TheoryData<object> public static readonly TheoryData<object> FileData = new()
{ {
TestImageProvider<Rgba32>.File(TestImages.Bmp.Car), TestImageProvider<Rgba32>.File(TestImages.Bmp.Car),
TestImageProvider<HalfVector4>.File(TestImages.Bmp.F) TestImageProvider<HalfVector4>.File(TestImages.Bmp.F)
@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests
/// <returns>A test image.</returns> /// <returns>A test image.</returns>
public static Image<TPixel> CreateTestImage<TPixel>() public static Image<TPixel> CreateTestImage<TPixel>()
where TPixel : unmanaged, IPixel<TPixel> => where TPixel : unmanaged, IPixel<TPixel> =>
new Image<TPixel>(3, 3); new(3, 3);
[Theory] [Theory]
[MemberData(nameof(BasicData))] [MemberData(nameof(BasicData))]
@ -179,8 +179,7 @@ namespace SixLabors.ImageSharp.Tests
public void SaveTestOutputFileMultiFrame<TPixel>(TestImageProvider<TPixel> provider) public void SaveTestOutputFileMultiFrame<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
string[] files = provider.Utility.SaveTestOutputFileMultiFrame(image); string[] files = provider.Utility.SaveTestOutputFileMultiFrame(image);
Assert.True(files.Length > 2); Assert.True(files.Length > 2);
@ -190,7 +189,6 @@ namespace SixLabors.ImageSharp.Tests
Assert.True(File.Exists(path)); Assert.True(File.Exists(path));
} }
} }
}
[Theory] [Theory]
[WithBasicTestPatternImages(50, 100, PixelTypes.Rgba32)] [WithBasicTestPatternImages(50, 100, PixelTypes.Rgba32)]
@ -199,11 +197,9 @@ namespace SixLabors.ImageSharp.Tests
public void Use_WithBasicTestPatternImages<TPixel>(TestImageProvider<TPixel> provider) public void Use_WithBasicTestPatternImages<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> img = provider.GetImage()) using Image<TPixel> img = provider.GetImage();
{
img.DebugSave(provider); img.DebugSave(provider);
} }
}
[Theory] [Theory]
[WithBlankImages(42, 666, PixelTypes.All, "hello")] [WithBlankImages(42, 666, PixelTypes.All, "hello")]
@ -238,8 +234,7 @@ namespace SixLabors.ImageSharp.Tests
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Assert.NotNull(provider.Utility.SourceFileOrDescription); Assert.NotNull(provider.Utility.SourceFileOrDescription);
using (Image<TPixel> img = provider.GetImage()) using Image<TPixel> img = provider.GetImage();
{
Assert.True(img.Width * img.Height > 0); Assert.True(img.Width * img.Height > 0);
Assert.Equal(123, yo); Assert.Equal(123, yo);
@ -247,15 +242,12 @@ namespace SixLabors.ImageSharp.Tests
string fn = provider.Utility.GetTestOutputFileName("jpg"); string fn = provider.Utility.GetTestOutputFileName("jpg");
this.Output.WriteLine(fn); this.Output.WriteLine(fn);
} }
}
[Theory] [Theory]
[WithFile(TestImages.Jpeg.Baseline.Testorig420, PixelTypes.Rgba32)] [WithFile(TestImages.Jpeg.Baseline.Testorig420, PixelTypes.Rgba32)]
public void Use_WithFileAttribute_CustomConfig<TPixel>(TestImageProvider<TPixel> provider) public void Use_WithFileAttribute_CustomConfig<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => EnsureCustomConfigurationIsApplied(provider);
EnsureCustomConfigurationIsApplied(provider);
}
[Theory] [Theory]
[WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.Argb32)] [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.Argb32)]
@ -263,11 +255,9 @@ namespace SixLabors.ImageSharp.Tests
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Assert.NotNull(provider.Utility.SourceFileOrDescription); Assert.NotNull(provider.Utility.SourceFileOrDescription);
using (Image<TPixel> image = provider.GetImage()) using Image<TPixel> image = provider.GetImage();
{
provider.Utility.SaveTestOutputFile(image, "png"); provider.Utility.SaveTestOutputFile(image, "png");
} }
}
[Theory] [Theory]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All)] [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All)]
@ -312,19 +302,15 @@ namespace SixLabors.ImageSharp.Tests
public void Use_WithTestPatternImages<TPixel>(TestImageProvider<TPixel> provider) public void Use_WithTestPatternImages<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (Image<TPixel> img = provider.GetImage()) using Image<TPixel> img = provider.GetImage();
{
img.DebugSave(provider); img.DebugSave(provider);
} }
}
[Theory] [Theory]
[WithTestPatternImages(20, 20, PixelTypes.Rgba32)] [WithTestPatternImages(20, 20, PixelTypes.Rgba32)]
public void Use_WithTestPatternImages_CustomConfiguration<TPixel>(TestImageProvider<TPixel> provider) public void Use_WithTestPatternImages_CustomConfiguration<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => EnsureCustomConfigurationIsApplied(provider);
EnsureCustomConfigurationIsApplied(provider);
}
private static void EnsureCustomConfigurationIsApplied<TPixel>(TestImageProvider<TPixel> provider) private static void EnsureCustomConfigurationIsApplied<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
@ -334,22 +320,19 @@ namespace SixLabors.ImageSharp.Tests
var customConfiguration = Configuration.CreateDefaultInstance(); var customConfiguration = Configuration.CreateDefaultInstance();
provider.Configuration = customConfiguration; provider.Configuration = customConfiguration;
using (Image<TPixel> image2 = provider.GetImage()) using Image<TPixel> image2 = provider.GetImage();
using (Image<TPixel> image3 = provider.GetImage()) using Image<TPixel> image3 = provider.GetImage();
{
Assert.Same(customConfiguration, image2.GetConfiguration()); Assert.Same(customConfiguration, image2.GetConfiguration());
Assert.Same(customConfiguration, image3.GetConfiguration()); Assert.Same(customConfiguration, image3.GetConfiguration());
} }
} }
}
private class TestDecoder : IImageDecoder private class TestDecoder : ImageDecoder<TestDecoderOptions>
{ {
// Couldn't make xUnit happy without this hackery: // Couldn't make xUnit happy without this hackery:
private static readonly ConcurrentDictionary<string, int> InvocationCounts = private static readonly ConcurrentDictionary<string, int> InvocationCounts = new();
new ConcurrentDictionary<string, int>();
private static readonly object Monitor = new object(); private static readonly object Monitor = new();
private string callerName; private string callerName;
@ -361,13 +344,18 @@ namespace SixLabors.ImageSharp.Tests
} }
} }
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public override IImageInfo IdentifySpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> => this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
public override Image<TPixel> DecodeSpecialized<TPixel>(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{ {
InvocationCounts[this.callerName]++; InvocationCounts[this.callerName]++;
return new Image<TPixel>(42, 42); return new Image<TPixel>(42, 42);
} }
public override Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName]; internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName];
internal void InitCaller(string name) internal void InitCaller(string name)
@ -375,16 +363,13 @@ namespace SixLabors.ImageSharp.Tests
this.callerName = name; this.callerName = name;
InvocationCounts[name] = 0; InvocationCounts[name] = 0;
} }
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
} }
private class TestDecoderWithParameters : IImageDecoder private class TestDecoderWithParameters : ImageDecoder<TestDecoderOptions>
{ {
private static readonly ConcurrentDictionary<string, int> InvocationCounts = private static readonly ConcurrentDictionary<string, int> InvocationCounts = new();
new ConcurrentDictionary<string, int>();
private static readonly object Monitor = new object(); private static readonly object Monitor = new();
private string callerName; private string callerName;
@ -400,13 +385,18 @@ namespace SixLabors.ImageSharp.Tests
} }
} }
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public override IImageInfo IdentifySpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> => this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
public override Image<TPixel> DecodeSpecialized<TPixel>(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{ {
InvocationCounts[this.callerName]++; InvocationCounts[this.callerName]++;
return new Image<TPixel>(42, 42); return new Image<TPixel>(42, 42);
} }
public override Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName]; internal static int GetInvocationCount(string callerName) => InvocationCounts[callerName];
internal void InitCaller(string name) internal void InitCaller(string name)
@ -414,8 +404,11 @@ namespace SixLabors.ImageSharp.Tests
this.callerName = name; this.callerName = name;
InvocationCounts[name] = 0; InvocationCounts[name] = 0;
} }
}
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken); private class TestDecoderOptions : ISpecializedDecoderOptions
{
public DecoderOptions GeneralOptions { get; set; } = new();
} }
} }
} }

Loading…
Cancel
Save