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. 21
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs
  10. 23
      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. 344
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  15. 194
      tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
  16. 136
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
  17. 81
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  18. 125
      tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs
  19. 128
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
  20. 98
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  21. 6
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
  22. 31
      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. 226
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  26. 282
      tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs
  27. 45
      tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs
  28. 2
      tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs
  29. 8
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  30. 202
      tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs
  31. 4
      tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs
  32. 241
      tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs
  33. 61
      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. 105
      tests/ImageSharp.Tests/Image/ImageTests.Identify.cs
  37. 29
      tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs
  38. 67
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs
  39. 66
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs
  40. 90
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs
  41. 83
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs
  42. 63
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs
  43. 17
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs
  44. 91
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs
  45. 10
      tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
  46. 84
      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. 19
      tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs
  50. 32
      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. 53
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
  55. 77
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
  56. 67
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
  57. 2
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
  58. 66
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  59. 51
      tests/ImageSharp.Tests/TestUtilities/Tests/MagickReferenceCodecTests.cs
  60. 86
      tests/ImageSharp.Tests/TestUtilities/Tests/SystemDrawingReferenceCodecTests.cs
  61. 109
      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();
/// <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.
/// </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 (previousFrame != null && frameCount++ > this.maxFrames)
if (previousFrame != null && ++frameCount == this.maxFrames)
{
break;
}

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

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats
/// </summary>
/// <typeparam name="T">The type of specialized decoder options.</typeparam>
public abstract class ImageDecoder<T> : IImageInfoDetector, IImageDecoder
where T : ISpecializedDecoderOptions, new()
where T : class, ISpecializedDecoderOptions, new()
{
/// <inheritdoc/>
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);
frames.Add(frame);
if (frameCount++ > this.maxFrames)
if (++frameCount == this.maxFrames)
{
break;
}

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

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

45
src/ImageSharp/Image.FromBytes.cs

@ -52,6 +52,51 @@ namespace SixLabors.ImageSharp
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>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>

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

@ -3,6 +3,7 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Tests;
@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
private void GenericBechmark()
{
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))]

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 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();
decoder.ParseStream(bufferedStream, spectralConverter, cancellationToken: default);
}

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

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

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

@ -3,8 +3,7 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Tests;
using SDImage = System.Drawing.Image;
using SDSize = System.Drawing.Size;
@ -47,25 +46,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public SDSize SystemDrawing()
{
using (var memoryStream = new MemoryStream(this.jpegBytes))
{
using (var image = SDImage.FromStream(memoryStream))
{
return image.Size;
}
}
using var memoryStream = new MemoryStream(this.jpegBytes);
using var image = SDImage.FromStream(memoryStream);
return image.Size;
}
[Benchmark]
public Size ImageSharp()
{
using (var memoryStream = new MemoryStream(this.jpegBytes))
{
using (var image = Image.Load(memoryStream, new JpegDecoder { IgnoreMetadata = true }))
{
return new Size(image.Width, image.Height);
}
}
using var memoryStream = new MemoryStream(this.jpegBytes);
using var image = Image.Load(new DecoderOptions() { SkipMetadata = true }, memoryStream);
return new Size(image.Width, image.Height);
}
/*

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

@ -3,6 +3,7 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Tests;
@ -32,7 +33,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
using var memoryStream = new MemoryStream(this.jpegBytes);
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 ImageMagick;
using Pfim;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
@ -18,7 +17,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
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;
@ -40,7 +39,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Description = "ImageSharp Tga")]
public int TgaImageSharp()
{
using var image = Image.Load<Bgr24>(this.data, new TgaDecoder());
using var image = Image.Load<Bgr24>(this.data);
return image.Width;
}

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

@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public int WebpLossy()
{
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;
}
@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public int WebpLossless()
{
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;
}

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

@ -4,7 +4,7 @@
using System;
using System.IO;
using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
@ -75,11 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
}
string providerDump = BasicSerializer.Serialize(provider);
RemoteExecutor.Invoke(
RunTest,
providerDump,
"Disco")
.Dispose();
RemoteExecutor.Invoke(RunTest, providerDump, "Disco").Dispose();
}
[Theory]
@ -98,11 +94,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBitfields<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -111,11 +105,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_Inverted<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -124,11 +116,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_1Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder());
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder());
}
[Theory]
@ -136,11 +126,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_4Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -148,11 +136,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -160,11 +146,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -172,11 +156,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -184,11 +166,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_32BitV4Header_Fast<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -199,11 +179,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel>
{
RleSkippedPixelHandling skippedPixelHandling = TestEnvironment.IsWindows ? RleSkippedPixelHandling.Black : RleSkippedPixelHandling.FirstColorOfPalette;
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = skippedPixelHandling }))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
BmpDecoderOptions options = new() { RleSkippedPixelHandling = skippedPixelHandling };
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -212,11 +192,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel>
{
RleSkippedPixelHandling skippedPixelHandling = TestEnvironment.IsWindows ? RleSkippedPixelHandling.Black : RleSkippedPixelHandling.FirstColorOfPalette;
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = skippedPixelHandling }))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
BmpDecoderOptions options = new() { RleSkippedPixelHandling = skippedPixelHandling };
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -227,13 +207,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_SystemDrawingRefDecoder<TPixel>(TestImageProvider<TPixel> provider)
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);
if (TestEnvironment.IsWindows)
{
image.DebugSave(provider);
if (TestEnvironment.IsWindows)
{
image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder());
}
image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder());
}
}
@ -243,11 +222,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_MagickRefDecoder<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette }))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette };
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -263,11 +241,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
provider.LimitAllocatorBufferCapacity().InBytesSqrt(400);
}
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette }))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette };
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -285,13 +262,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
provider.LimitAllocatorBufferCapacity().InBytesSqrt(400);
}
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.Black }))
{
image.DebugSave(provider);
BmpDecoderOptions options = new() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black };
using Image<TPixel> image = provider.GetImage(BmpDecoder, options);
image.DebugSave(provider);
// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider);
}
// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider);
}
[Theory]
@ -299,13 +275,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeAlphaBitfields<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider);
}
// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider);
}
[Theory]
@ -313,11 +287,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBitmap_WithAlphaChannel<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -325,17 +297,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBitfields_WithUnusualBitmasks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
// Choosing large tolerance of 6.1 here, because for some reason with the MagickReferenceDecoder the alpha channel
// seems to be wrong. This bitmap has an alpha channel of two bits. In many cases this alpha channel has a value of 3,
// which should be remapped to 255 for RGBA32, but the magick decoder has a value of 191 set.
// The total difference without the alpha channel is still: 0.0204%
// 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());
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
// Choosing large tolerance of 6.1 here, because for some reason with the MagickReferenceDecoder the alpha channel
// seems to be wrong. This bitmap has an alpha channel of two bits. In many cases this alpha channel has a value of 3,
// which should be remapped to 255 for RGBA32, but the magick decoder has a value of 191 set.
// The total difference without the alpha channel is still: 0.0204%
// 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());
}
[Theory]
@ -344,13 +314,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBmpv2<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
// Do not validate. Reference files will fail validation.
image.CompareToOriginal(provider, new MagickReferenceDecoder(false));
}
// Do not validate. Reference files will fail validation.
image.CompareToOriginal(provider, new MagickReferenceDecoder(false));
}
[Theory]
@ -358,11 +326,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBmpv3<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -370,11 +336,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeLessThanFullPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -383,13 +347,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeOversizedPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
if (TestEnvironment.IsWindows)
{
image.DebugSave(provider);
if (TestEnvironment.IsWindows)
{
image.CompareToOriginal(provider);
}
image.CompareToOriginal(provider);
}
}
@ -397,39 +359,33 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
[WithFile(InvalidPaletteSize, PixelTypes.Rgba32)]
public void BmpDecoder_ThrowsInvalidImageContentException_OnInvalidPaletteSize<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Assert.Throws<InvalidImageContentException>(() =>
=> Assert.Throws<InvalidImageContentException>(() =>
{
using (provider.GetImage(BmpDecoder))
{
}
});
}
[Theory]
[WithFile(Rgb24jpeg, PixelTypes.Rgba32)]
[WithFile(Rgb24png, PixelTypes.Rgba32)]
public void BmpDecoder_ThrowsNotSupportedException_OnUnsupportedBitmaps<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Assert.Throws<NotSupportedException>(() =>
=> Assert.Throws<NotSupportedException>(() =>
{
using (provider.GetImage(BmpDecoder))
{
}
});
}
[Theory]
[WithFile(Rgb32h52AdobeV3, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeAdobeBmpv3<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -437,11 +393,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeAdobeBmpv3_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -449,11 +403,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBmpv4<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -462,11 +414,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecodeBmpv5<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -474,11 +424,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_RespectsFileHeaderOffset<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -486,11 +434,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -498,11 +444,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode4BytePerEntryPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
@ -521,12 +465,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Identify_DetectsCorrectPixelType(string imagePath, int expectedPixelSize)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedPixelSize, imageInfo.PixelType?.BitsPerPixel);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedPixelSize, imageInfo.PixelType?.BitsPerPixel);
}
[Theory]
@ -541,13 +483,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Identify_DetectsCorrectWidthAndHeight(string imagePath, int expectedWidth, int expectedHeight)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedWidth, imageInfo.Width);
Assert.Equal(expectedHeight, imageInfo.Height);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedWidth, imageInfo.Width);
Assert.Equal(expectedHeight, imageInfo.Height);
}
[Theory]
@ -555,17 +495,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
var decoder = new BmpDecoder();
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, stream, default))
{
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
}
using var stream = new MemoryStream(testFile.Bytes, false);
var decoder = new BmpDecoder();
using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -573,13 +509,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_Os2v2XShortHeader<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
// TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file.
// image.CompareToOriginal(provider);
}
// TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file.
// image.CompareToOriginal(provider);
}
[Theory]
@ -587,15 +521,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_Os2v2Header<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
// TODO: System.Drawing can not decode this image. MagickReferenceDecoder can decode it,
// but i think incorrectly. I have loaded the image with GIMP and exported as PNG.
// The results are the same as the image sharp implementation.
// image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
// TODO: System.Drawing can not decode this image. MagickReferenceDecoder can decode it,
// but i think incorrectly. I have loaded the image with GIMP and exported as PNG.
// The results are the same as the image sharp implementation.
// image.CompareToOriginal(provider, new MagickReferenceDecoder());
}
[Theory]
@ -611,13 +543,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_CanDecode_Os2BitmapArray<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(BmpDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(BmpDecoder);
image.DebugSave(provider);
// TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file.
// image.CompareToOriginal(provider);
}
// TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file.
// image.CompareToOriginal(provider);
}
}
}

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

@ -53,22 +53,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
var options = new BmpEncoder();
var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image())
{
using (var memStream = new MemoryStream())
{
input.Save(memStream, options);
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
}
}
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
input.Save(memStream, options);
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -78,21 +72,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
var options = new BmpEncoder();
var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image())
{
using (var memStream = new MemoryStream())
{
input.Save(memStream, options);
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
BmpMetadata meta = output.Metadata.GetBmpMetadata();
Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel);
}
}
}
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
input.Save(memStream, options);
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
BmpMetadata meta = output.Metadata.GetBmpMetadata();
Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel);
}
[Theory]
@ -237,28 +225,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
return;
}
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
var encoder = new BmpEncoder
{
var encoder = new BmpEncoder
{
BitsPerPixel = BmpBitsPerPixel.Pixel8,
Quantizer = new WuQuantizer()
};
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false);
// Use the default decoder to test our encoded image. This verifies the content.
// We do not verify the reference image though as some are invalid.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder))
{
referenceImage.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.01f),
provider,
extension: "bmp",
appendPixelTypeToFileName: false,
decoder: new MagickReferenceDecoder(false));
}
}
BitsPerPixel = BmpBitsPerPixel.Pixel8,
Quantizer = new WuQuantizer()
};
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false);
// Use the default decoder to test our encoded image. This verifies the content.
// We do not verify the reference image though as some are invalid.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
using FileStream stream = File.OpenRead(actualOutputFile);
using Image<TPixel> referenceImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
referenceImage.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.01f),
provider,
extension: "bmp",
appendPixelTypeToFileName: false,
decoder: new MagickReferenceDecoder(false));
}
[Theory]
@ -271,28 +257,25 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
return;
}
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
var encoder = new BmpEncoder
{
var encoder = new BmpEncoder
{
BitsPerPixel = BmpBitsPerPixel.Pixel8,
Quantizer = new OctreeQuantizer()
};
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false);
// Use the default decoder to test our encoded image. This verifies the content.
// We do not verify the reference image though as some are invalid.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder))
{
referenceImage.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.01f),
provider,
extension: "bmp",
appendPixelTypeToFileName: false,
decoder: new MagickReferenceDecoder(false));
}
}
BitsPerPixel = BmpBitsPerPixel.Pixel8,
Quantizer = new OctreeQuantizer()
};
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false);
// Use the default decoder to test our encoded image. This verifies the content.
// We do not verify the reference image though as some are invalid.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
using FileStream stream = File.OpenRead(actualOutputFile);
using Image<TPixel> referenceImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
referenceImage.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.01f),
provider,
extension: "bmp",
appendPixelTypeToFileName: false,
decoder: new MagickReferenceDecoder(false));
}
[Theory]
@ -306,26 +289,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> input = provider.GetImage(new BmpDecoder()))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream())
{
input.Save(memStream, new BmpEncoder());
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
}
}
using Image<TPixel> input = provider.GetImage(new BmpDecoder(), new());
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using var memStream = new MemoryStream();
input.Save(memStream, new BmpEncoder());
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
[Theory]
@ -346,24 +323,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
ImageComparer customComparer = null)
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.
if (bitsPerPixel != BmpBitsPerPixel.Pixel32)
{
// 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)
{
image.Mutate(c => c.MakeOpaque());
}
var encoder = new BmpEncoder
{
BitsPerPixel = bitsPerPixel,
SupportTransparency = supportTransparency,
Quantizer = quantizer ?? KnownQuantizers.Octree
};
// Does DebugSave & load reference CompareToReferenceInput():
image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, customComparer);
image.Mutate(c => c.MakeOpaque());
}
var encoder = new BmpEncoder
{
BitsPerPixel = bitsPerPixel,
SupportTransparency = supportTransparency,
Quantizer = quantizer ?? KnownQuantizers.Octree
};
// Does DebugSave & load reference CompareToReferenceInput():
image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, customComparer);
}
}
}

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

@ -45,12 +45,10 @@ namespace SixLabors.ImageSharp.Tests.Formats
public void ResolutionShouldChange<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Metadata.VerticalResolution = 150;
image.Metadata.HorizontalResolution = 150;
image.DebugSave(provider);
}
using Image<TPixel> image = provider.GetImage();
image.Metadata.VerticalResolution = 150;
image.Metadata.HorizontalResolution = 150;
image.DebugSave(provider);
}
[Fact]
@ -60,11 +58,9 @@ namespace SixLabors.ImageSharp.Tests.Formats
foreach (TestFile file in Files)
{
using (Image<Rgba32> image = file.CreateRgba32Image())
{
string filename = Path.Combine(path, $"{file.FileNameWithoutExtension}.txt");
File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance));
}
using Image<Rgba32> image = file.CreateRgba32Image();
string filename = Path.Combine(path, $"{file.FileNameWithoutExtension}.txt");
File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance));
}
}
@ -75,10 +71,8 @@ namespace SixLabors.ImageSharp.Tests.Formats
foreach (TestFile file in Files)
{
using (Image<Rgba32> image = file.CreateRgba32Image())
{
image.Save(Path.Combine(path, file.FileName));
}
using Image<Rgba32> image = file.CreateRgba32Image();
image.Save(Path.Combine(path, file.FileName));
}
}
@ -120,42 +114,40 @@ namespace SixLabors.ImageSharp.Tests.Formats
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")))
{
image.SaveAsBmp(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.jpg")))
{
image.SaveAsJpeg(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.pbm")))
{
image.SaveAsPbm(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.png")))
{
image.SaveAsPng(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.gif")))
{
image.SaveAsGif(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.tga")))
{
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.bmp")))
{
image.SaveAsBmp(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.jpg")))
{
image.SaveAsJpeg(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.pbm")))
{
image.SaveAsPbm(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.png")))
{
image.SaveAsPng(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.gif")))
{
image.SaveAsGif(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.tga")))
{
image.SaveAsTga(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.tiff")))
{
image.SaveAsTiff(output);
}
image.SaveAsTga(output);
}
using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.tiff")))
{
image.SaveAsTiff(output);
}
}
}
@ -176,10 +168,8 @@ namespace SixLabors.ImageSharp.Tests.Formats
serialized = memoryStream.ToArray();
}
using (var image2 = Image.Load<Rgba32>(serialized))
{
image2.Save($"{path}{Path.DirectorySeparatorChar}{file.FileName}");
}
using var image2 = Image.Load<Rgba32>(serialized);
image2.Save($"{path}{Path.DirectorySeparatorChar}{file.FileName}");
}
}
@ -213,39 +203,33 @@ namespace SixLabors.ImageSharp.Tests.Formats
public void CanIdentifyImageLoadedFromBytes(int width, int height, string extension)
{
using (var image = Image.LoadPixelData(new Rgba32[width * height], width, height))
{
using (var memoryStream = new MemoryStream())
{
IImageFormat format = GetFormat(extension);
image.Save(memoryStream, format);
memoryStream.Position = 0;
using var image = Image.LoadPixelData<Rgba32>(new Rgba32[width * height], width, height);
using var memoryStream = new MemoryStream();
IImageFormat format = GetFormat(extension);
image.Save(memoryStream, format);
memoryStream.Position = 0;
IImageInfo imageInfo = Image.Identify(memoryStream);
IImageInfo imageInfo = Image.Identify(memoryStream);
Assert.Equal(imageInfo.Width, width);
Assert.Equal(imageInfo.Height, height);
memoryStream.Position = 0;
Assert.Equal(imageInfo.Width, width);
Assert.Equal(imageInfo.Height, height);
memoryStream.Position = 0;
imageInfo = Image.Identify(memoryStream, out IImageFormat detectedFormat);
imageInfo = Image.Identify(memoryStream, out IImageFormat detectedFormat);
Assert.Equal(format, detectedFormat);
}
}
Assert.Equal(format, detectedFormat);
}
[Fact]
public void IdentifyReturnsNullWithInvalidStream()
{
var invalid = new byte[10];
byte[] invalid = new byte[10];
using (var memoryStream = new MemoryStream(invalid))
{
IImageInfo imageInfo = Image.Identify(memoryStream, out IImageFormat format);
using var memoryStream = new MemoryStream(invalid);
IImageInfo imageInfo = Image.Identify(memoryStream, out IImageFormat format);
Assert.Null(imageInfo);
Assert.Null(format);
}
Assert.Null(imageInfo);
Assert.Null(format);
}
private static IImageFormat GetFormat(string format)

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

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

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

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

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

@ -80,17 +80,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
var decoder = new JpegDecoder();
using (Image image = decoder.Decode(Configuration.Default, stream, default))
{
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
}
using var stream = new MemoryStream(testFile.Bytes, false);
var decoder = new JpegDecoder();
using Image image = decoder.Decode(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -98,15 +94,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
var decoder = new JpegDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
using var stream = new MemoryStream(testFile.Bytes, false);
var decoder = new JpegDecoder();
IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -114,13 +108,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Identify_VerifyQuality(string imagePath, int quality)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
var decoder = new JpegDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
}
using var stream = new MemoryStream(testFile.Bytes, false);
var decoder = new JpegDecoder();
IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
}
[Theory]
@ -128,14 +120,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Decode_VerifyQuality(string imagePath, int quality)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
using (Image image = JpegDecoder.Decode(Configuration.Default, stream, default))
{
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
}
}
using var stream = new MemoryStream(testFile.Bytes, false);
using Image image = JpegDecoder.Decode(DecoderOptions.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
}
[Theory]
@ -150,12 +138,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Identify_DetectsCorrectColorType(string imagePath, JpegColorType expectedColorType)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo image = JpegDecoder.Identify(Configuration.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo image = JpegDecoder.Identify(DecoderOptions.Default, stream, default);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType);
}
[Theory]
@ -167,28 +153,24 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Decode_DetectsCorrectColorType<TPixel>(TestImageProvider<TPixel> provider, JpegColorType expectedColorType)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType);
}
private static void TestImageInfo(string imagePath, IImageDecoder decoder, bool useIdentify, Action<IImageInfo> test)
{
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);
test(imageInfo);
}
else
{
using var img = decoder.Decode<Rgba32>(Configuration.Default, stream, default);
test(img);
}
IImageInfo imageInfo = ((IImageInfoDetector)decoder).Identify(DecoderOptions.Default, stream, default);
test(imageInfo);
}
else
{
using Image<Rgba32> img = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
test(img);
}
}
@ -248,23 +230,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(true)]
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:
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.IccProfile);
}
else
{
Assert.NotNull(image.Metadata.ExifProfile);
Assert.NotNull(image.Metadata.IccProfile);
}
Assert.Null(image.Metadata.ExifProfile);
Assert.Null(image.Metadata.IccProfile);
}
else
{
Assert.NotNull(image.Metadata.ExifProfile);
Assert.NotNull(image.Metadata.IccProfile);
}
}
@ -314,7 +294,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Exception ex = Record.Exception(() =>
{
using Image<TPixel> image = provider.GetImage(JpegDecoder);
var clone = image.Metadata.ExifProfile.DeepClone();
ExifProfile clone = image.Metadata.ExifProfile.DeepClone();
});
Assert.Null(ex);
}
@ -357,11 +337,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact]
public void EncodedStringTags_Read()
{
using (var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora_EncodedStrings)))
{
ExifProfile exif = image.Metadata.ExifProfile;
VerifyEncodedStrings(exif);
}
using var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora_EncodedStrings));
ExifProfile exif = image.Metadata.ExifProfile;
VerifyEncodedStrings(exif);
}
private static void VerifyEncodedStrings(ExifProfile exif)

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

@ -6,6 +6,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
@ -73,10 +74,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact]
public void ParseStream_BasicPropertiesAreCorrect()
{
JpegDecoderOptions options = new();
byte[] bytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes;
using var ms = new MemoryStream(bytes);
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);
// 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();
string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var pausedStream = new PausedStream(file);
pausedStream.OnWaiting(s =>
pausedStream.OnWaiting(_ =>
{
cts.Cancel();
pausedStream.Release();
});
var config = Configuration.CreateDefaultInstance();
config.FileSystem = new SingleStreamFileSystem(pausedStream);
var configuration = Configuration.CreateDefaultInstance();
configuration.FileSystem = new SingleStreamFileSystem(pausedStream);
DecoderOptions options = new()
{
Configuration = configuration
};
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);
using var pausedStream = new PausedStream(file);
pausedStream.OnWaiting(s =>
pausedStream.OnWaiting(_ =>
{
cts.Cancel();
pausedStream.Release();
});
var config = Configuration.CreateDefaultInstance();
config.FileSystem = new SingleStreamFileSystem(pausedStream);
var configuration = Configuration.CreateDefaultInstance();
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]
[WithFileCollection(nameof(UnsupportedTestJpegs), PixelTypes.Rgba32)]
public void ThrowsNotSupported_WithUnsupportedJpegs<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Assert.Throws<NotSupportedException>(() =>
=> Assert.Throws<NotSupportedException>(() =>
{
using Image<TPixel> image = provider.GetImage(JpegDecoder);
});
}
// https://github.com/SixLabors/ImageSharp/pull/1732
[Theory]
@ -198,11 +207,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue1732_DecodesWithRgbColorSpace<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
// https://github.com/SixLabors/ImageSharp/issues/2057
@ -211,11 +218,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue2057_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
// https://github.com/SixLabors/ImageSharp/issues/2133
@ -224,11 +229,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue2133_DeduceColorSpace<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
// https://github.com/SixLabors/ImageSharp/issues/2133
@ -237,44 +240,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void Issue2136_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
image.DebugSave(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}");
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
}
}

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

@ -49,8 +49,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
// Calculating data from ImageSharp
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 bufferedStream = new BufferedReadStream(Configuration.Default, ms);
@ -78,8 +79,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// Calculating data from ImageSharp
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 bufferedStream = new BufferedReadStream(Configuration.Default, ms);

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

@ -18,12 +18,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public class SpectralToPixelConversionTests
{
public static readonly string[] BaselineTestJpegs =
{
TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk, TestImages.Jpeg.Baseline.Jpeg400,
TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Testorig420,
TestImages.Jpeg.Baseline.Jpeg420Small, TestImages.Jpeg.Baseline.Bad.BadEOF,
TestImages.Jpeg.Baseline.MultiScanBaselineCMYK
};
{
TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk, TestImages.Jpeg.Baseline.Jpeg400,
TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Testorig420,
TestImages.Jpeg.Baseline.Jpeg420Small, TestImages.Jpeg.Baseline.Bad.BadEOF,
TestImages.Jpeg.Baseline.MultiScanBaselineCMYK
};
public SpectralToPixelConversionTests(ITestOutputHelper output) => this.Output = output;
@ -40,8 +40,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
using var bufferedStream = new BufferedReadStream(Configuration.Default, ms);
// Decoding
JpegDecoderOptions options = new();
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);
decoder.ParseStream(bufferedStream, converter, cancellationToken: default);
@ -50,17 +51,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
provider.Utility.TestName = JpegDecoderTests.DecodeBaselineJpegOutputName;
// Comparison
using (var image = new Image<TPixel>(Configuration.Default, converter.GetPixelBuffer(CancellationToken.None), new ImageMetadata()))
using (Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(appendPixelTypeToFileName: false))
{
ImageSimilarityReport report = ImageComparer.Exact.CompareImagesOrFrames(referenceImage, image);
using var image = new Image<TPixel>(Configuration.Default, converter.GetPixelBuffer(CancellationToken.None), new ImageMetadata());
using Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(appendPixelTypeToFileName: false);
ImageSimilarityReport report = ImageComparer.Exact.CompareImagesOrFrames(referenceImage, image);
this.Output.WriteLine($"*** {provider.SourceFileOrDescription} ***");
this.Output.WriteLine($"Difference: {report.DifferencePercentageString}");
this.Output.WriteLine($"*** {provider.SourceFileOrDescription} ***");
this.Output.WriteLine($"Difference: {report.DifferencePercentageString}");
// ReSharper disable once PossibleInvalidOperationException
Assert.True(report.TotalNormalizedDifference.Value < 0.005f);
}
// ReSharper disable once PossibleInvalidOperationException
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
public static float[] Create8x8FloatData()
{
var result = new float[64];
float[] result = new float[64];
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
// ReSharper disable once InconsistentNaming
public static int[] Create8x8IntData()
{
var result = new int[64];
int[] result = new int[64];
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
// ReSharper disable once InconsistentNaming
public static short[] Create8x8ShortData()
{
var result = new short[64];
short[] result = new short[64];
for (int i = 0; i < 8; i++)
{
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)
{
var rnd = new Random(seed);
var result = new int[64];
int[] result = new int[64];
for (int i = 0; i < 8; i++)
{
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 bufferedStream = new BufferedReadStream(Configuration.Default, ms);
var decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder());
JpegDecoderOptions options = new();
var decoder = new JpegDecoderCore(options);
if (metaDataOnly)
{
decoder.Identify(bufferedStream, cancellationToken: default);

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

@ -4,6 +4,7 @@
using System.Buffers.Binary;
using System.IO;
using System.Text;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
@ -75,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
var decoder = new PngDecoder();
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);
}
@ -83,18 +84,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
private static string GetChunkTypeName(uint value)
{
var data = new byte[4];
byte[] data = new byte[4];
BinaryPrimitives.WriteUInt32BigEndian(data, value);
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.
memStream.Write(Raw1X1PngIhdrAndpHYs, 0, Raw1X1PngIhdrAndpHYs.Length);
}
private static void WriteChunk(MemoryStream memStream, string chunkName)
{

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

@ -111,15 +111,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[WithTestPatternImages(nameof(PngColorTypes), 7, 5, PixelTypes.Rgba32)]
public void WorksWithDifferentSizes<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType)
where TPixel : unmanaged, IPixel<TPixel>
{
TestPngEncoderCore(
=> TestPngEncoderCore(
provider,
pngColorType,
PngFilterMethod.Adaptive,
PngBitDepth.Bit8,
PngInterlaceMode.None,
appendPngColorType: true);
}
[Theory]
[WithTestPatternImages(nameof(PngColorTypes), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)]
@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
return;
}
foreach (var filterMethod in PngFilterMethods)
foreach (object[] filterMethod in PngFilterMethods)
{
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)
where TPixel : unmanaged, IPixel<TPixel>
{
foreach (var filterMethod in PngFilterMethods)
foreach (object[] filterMethod in PngFilterMethods)
{
foreach (PngInterlaceMode interlaceMode in InterlaceMode)
{
@ -284,20 +282,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void InfersColorTypeAndBitDepth<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Stream stream = new MemoryStream())
{
PngEncoder.Encode(provider.GetImage(), stream);
using Stream stream = new MemoryStream();
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();
Assert.Equal(pngColorType, metadata.ColorType);
Assert.Equal(pngBitDepth, metadata.BitDepth);
}
PngMetadata metadata = image.Metadata.GetPngMetadata();
Assert.Equal(pngColorType, metadata.ColorType);
Assert.Equal(pngBitDepth, metadata.BitDepth);
}
[Theory]
@ -329,14 +325,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void WritesFileMarker<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
using (var ms = new MemoryStream())
{
image.Save(ms, PngEncoder);
using Image<TPixel> image = provider.GetImage();
using var ms = new MemoryStream();
image.Save(ms, PngEncoder);
byte[] data = ms.ToArray().Take(8).ToArray();
byte[] expected =
{
byte[] data = ms.ToArray().Take(8).ToArray();
byte[] expected =
{
0x89, // Set the high bit.
0x50, // P
0x4E, // N
@ -347,8 +342,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
0x0A // LF
};
Assert.Equal(expected, data);
}
Assert.Equal(expected, data);
}
[Theory]
@ -356,22 +350,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Encode_PreserveRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image())
{
using (var memStream = new MemoryStream())
{
input.Save(memStream, PngEncoder);
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
}
}
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -379,21 +367,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Encode_PreserveBits(string imagePath, PngBitDepth pngBitDepth)
{
var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image())
{
using (var memStream = new MemoryStream())
{
input.Save(memStream, PngEncoder);
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
PngMetadata meta = output.Metadata.GetPngMetadata();
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
PngMetadata meta = output.Metadata.GetPngMetadata();
Assert.Equal(pngBitDepth, meta.BitDepth);
}
}
}
Assert.Equal(pngBitDepth, meta.BitDepth);
}
[Theory]
@ -437,9 +419,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
memStream.Position = 0;
using var actual = Image.Load<Rgba32>(memStream);
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);
}
@ -467,51 +449,45 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Encode_PreserveTrns(string imagePath, PngBitDepth pngBitDepth, PngColorType pngColorType)
{
var testFile = TestFile.Create(imagePath);
using (Image<Rgba32> input = testFile.CreateRgba32Image())
using Image<Rgba32> input = testFile.CreateRgba32Image();
PngMetadata inMeta = input.Metadata.GetPngMetadata();
Assert.True(inMeta.HasTransparency);
using var memStream = new MemoryStream();
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
PngMetadata outMeta = output.Metadata.GetPngMetadata();
Assert.True(outMeta.HasTransparency);
switch (pngColorType)
{
PngMetadata inMeta = input.Metadata.GetPngMetadata();
Assert.True(inMeta.HasTransparency);
case PngColorType.Grayscale:
if (pngBitDepth.Equals(PngBitDepth.Bit16))
{
Assert.True(outMeta.TransparentL16.HasValue);
Assert.Equal(inMeta.TransparentL16, outMeta.TransparentL16);
}
else
{
Assert.True(outMeta.TransparentL8.HasValue);
Assert.Equal(inMeta.TransparentL8, outMeta.TransparentL8);
}
using (var memStream = new MemoryStream())
{
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
break;
case PngColorType.Rgb:
if (pngBitDepth.Equals(PngBitDepth.Bit16))
{
PngMetadata outMeta = output.Metadata.GetPngMetadata();
Assert.True(outMeta.HasTransparency);
switch (pngColorType)
{
case PngColorType.Grayscale:
if (pngBitDepth.Equals(PngBitDepth.Bit16))
{
Assert.True(outMeta.TransparentL16.HasValue);
Assert.Equal(inMeta.TransparentL16, outMeta.TransparentL16);
}
else
{
Assert.True(outMeta.TransparentL8.HasValue);
Assert.Equal(inMeta.TransparentL8, outMeta.TransparentL8);
}
break;
case PngColorType.Rgb:
if (pngBitDepth.Equals(PngBitDepth.Bit16))
{
Assert.True(outMeta.TransparentRgb48.HasValue);
Assert.Equal(inMeta.TransparentRgb48, outMeta.TransparentRgb48);
}
else
{
Assert.True(outMeta.TransparentRgb24.HasValue);
Assert.Equal(inMeta.TransparentRgb24, outMeta.TransparentRgb24);
}
break;
}
Assert.True(outMeta.TransparentRgb48.HasValue);
Assert.Equal(inMeta.TransparentRgb48, outMeta.TransparentRgb48);
}
}
else
{
Assert.True(outMeta.TransparentRgb24.HasValue);
Assert.Equal(inMeta.TransparentRgb24, outMeta.TransparentRgb24);
}
break;
}
}
@ -591,42 +567,42 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
PngChunkFilter optimizeMethod = PngChunkFilter.None)
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,
FilterMethod = pngFilterMethod,
CompressionLevel = compressionLevel,
BitDepth = bitDepth,
Quantizer = new WuQuantizer(new QuantizerOptions { MaxColors = paletteSize }),
InterlaceMethod = interlaceMode,
ChunkFilter = optimizeMethod,
};
ColorType = pngColorType,
FilterMethod = pngFilterMethod,
CompressionLevel = compressionLevel,
BitDepth = bitDepth,
Quantizer = new WuQuantizer(new QuantizerOptions { MaxColors = paletteSize }),
InterlaceMethod = interlaceMode,
ChunkFilter = optimizeMethod,
};
string pngColorTypeInfo = appendPngColorType ? pngColorType.ToString() : string.Empty;
string pngFilterMethodInfo = appendPngFilterMethod ? pngFilterMethod.ToString() : string.Empty;
string compressionLevelInfo = appendCompressionLevel ? $"_C{compressionLevel}" : string.Empty;
string paletteSizeInfo = appendPaletteSize ? $"_PaletteSize-{paletteSize}" : string.Empty;
string pngBitDepthInfo = appendPngBitDepth ? bitDepth.ToString() : string.Empty;
string pngInterlaceModeInfo = interlaceMode != PngInterlaceMode.None ? $"_{interlaceMode}" : string.Empty;
string pngColorTypeInfo = appendPngColorType ? pngColorType.ToString() : string.Empty;
string pngFilterMethodInfo = appendPngFilterMethod ? pngFilterMethod.ToString() : string.Empty;
string compressionLevelInfo = appendCompressionLevel ? $"_C{compressionLevel}" : string.Empty;
string paletteSizeInfo = appendPaletteSize ? $"_PaletteSize-{paletteSize}" : string.Empty;
string pngBitDepthInfo = appendPngBitDepth ? bitDepth.ToString() : string.Empty;
string pngInterlaceModeInfo = interlaceMode != PngInterlaceMode.None ? $"_{interlaceMode}" : string.Empty;
string debugInfo = $"{pngColorTypeInfo}{pngFilterMethodInfo}{compressionLevelInfo}{paletteSizeInfo}{pngBitDepthInfo}{pngInterlaceModeInfo}";
string debugInfo = $"{pngColorTypeInfo}{pngFilterMethodInfo}{compressionLevelInfo}{paletteSizeInfo}{pngBitDepthInfo}{pngInterlaceModeInfo}";
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType);
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType);
// Compare to the Magick reference decoder.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
// Compare to the Magick reference decoder.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
// We compare using both our decoder and the reference decoder as pixel transformation
// occurs within the encoder itself leaving the input image unaffected.
// This means we are benefiting from testing our decoder also.
using (var imageSharpImage = Image.Load<TPixel>(actualOutputFile, new PngDecoder()))
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder))
{
ImageComparer.Exact.VerifySimilarity(referenceImage, imageSharpImage);
}
}
// We compare using both our decoder and the reference decoder as pixel transformation
// occurs within the encoder itself leaving the input image unaffected.
// This means we are benefiting from testing our decoder also.
using FileStream fileStream = File.OpenRead(actualOutputFile);
using Image<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);
}
}
}

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

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@ -56,11 +57,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decoder_CanReadTextData<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new PngDecoder()))
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta);
}
using Image<TPixel> image = provider.GetImage(new PngDecoder());
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta);
}
[Theory]
@ -69,18 +68,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new PngDecoder();
using (Image<TPixel> input = provider.GetImage(decoder))
using (var memoryStream = new MemoryStream())
{
input.Save(memoryStream, new PngEncoder());
memoryStream.Position = 0;
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, memoryStream, default))
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta);
}
}
using Image<TPixel> input = provider.GetImage(decoder);
using var memoryStream = new MemoryStream();
input.Save(memoryStream, new PngEncoder());
memoryStream.Position = 0;
using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, memoryStream, default);
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta);
}
[Theory]
@ -88,16 +83,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decoder_IgnoresInvalidTextData<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new PngDecoder()))
{
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 "trailing space");
Assert.DoesNotContain(meta.TextData, m => m.Value is "space");
Assert.DoesNotContain(meta.TextData, m => m.Value is "empty");
Assert.DoesNotContain(meta.TextData, m => m.Value is "invalid characters");
Assert.DoesNotContain(meta.TextData, m => m.Value is "too large");
}
using Image<TPixel> image = provider.GetImage(new PngDecoder());
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 "trailing space");
Assert.DoesNotContain(meta.TextData, m => m.Value is "space");
Assert.DoesNotContain(meta.TextData, m => m.Value is "empty");
Assert.DoesNotContain(meta.TextData, m => m.Value is "invalid characters");
Assert.DoesNotContain(meta.TextData, m => m.Value is "too large");
}
[Theory]
@ -106,30 +99,27 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new PngDecoder();
using (Image<TPixel> input = provider.GetImage(decoder))
using (var memoryStream = new MemoryStream())
using Image<TPixel> input = provider.GetImage(decoder);
using var memoryStream = new MemoryStream();
// This will be a zTXt chunk.
var expectedText = new PngTextData("large-text", new string('c', 100), string.Empty, string.Empty);
// This will be a iTXt chunk.
var expectedTextNoneLatin = new PngTextData("large-text-non-latin", new string('Ф', 100), "language-tag", "translated-keyword");
PngMetadata inputMetadata = input.Metadata.GetFormatMetadata(PngFormat.Instance);
inputMetadata.TextData.Add(expectedText);
inputMetadata.TextData.Add(expectedTextNoneLatin);
input.Save(memoryStream, new PngEncoder
{
// This will be a zTXt chunk.
var expectedText = new PngTextData("large-text", new string('c', 100), string.Empty, string.Empty);
// This will be a iTXt chunk.
var expectedTextNoneLatin = new PngTextData("large-text-non-latin", new string('Ф', 100), "language-tag", "translated-keyword");
PngMetadata inputMetadata = input.Metadata.GetFormatMetadata(PngFormat.Instance);
inputMetadata.TextData.Add(expectedText);
inputMetadata.TextData.Add(expectedTextNoneLatin);
input.Save(memoryStream, new PngEncoder
{
TextCompressionThreshold = 50
});
memoryStream.Position = 0;
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, memoryStream, default))
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Contains(meta.TextData, m => m.Equals(expectedText));
Assert.Contains(meta.TextData, m => m.Equals(expectedTextNoneLatin));
}
}
TextCompressionThreshold = 50
});
memoryStream.Position = 0;
using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, memoryStream, default);
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Contains(meta.TextData, m => m.Equals(expectedText));
Assert.Contains(meta.TextData, m => m.Equals(expectedTextNoneLatin));
}
[Theory]
@ -137,17 +127,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_ReadsExifData<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new PngDecoder
DecoderOptions options = new()
{
IgnoreMetadata = false
SkipMetadata = false
};
using (Image<TPixel> image = provider.GetImage(decoder))
{
Assert.NotNull(image.Metadata.ExifProfile);
ExifProfile exif = image.Metadata.ExifProfile;
VerifyExifDataIsPresent(exif);
}
using Image<TPixel> image = provider.GetImage(new PngDecoder(), options);
Assert.NotNull(image.Metadata.ExifProfile);
ExifProfile exif = image.Metadata.ExifProfile;
VerifyExifDataIsPresent(exif);
}
[Theory]
@ -155,53 +143,49 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_IgnoresExifData_WhenIgnoreMetadataIsTrue<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new PngDecoder
DecoderOptions options = new()
{
IgnoreMetadata = true
SkipMetadata = true
};
using (Image<TPixel> image = provider.GetImage(decoder))
{
Assert.Null(image.Metadata.ExifProfile);
}
PngDecoder decoder = new();
using Image<TPixel> image = provider.GetImage(decoder, options);
Assert.Null(image.Metadata.ExifProfile);
}
[Fact]
public void Decode_IgnoreMetadataIsFalse_TextChunkIsRead()
{
var options = new PngDecoder
DecoderOptions options = new()
{
IgnoreMetadata = false
SkipMetadata = false
};
var testFile = TestFile.Create(TestImages.Png.Blur);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options))
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
using Image<Rgba32> image = testFile.CreateRgba32Image(new PngDecoder(), options);
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Equal(1, meta.TextData.Count);
Assert.Equal("Software", meta.TextData[0].Keyword);
Assert.Equal("paint.net 4.0.6", meta.TextData[0].Value);
Assert.Equal(0.4545d, meta.Gamma, precision: 4);
}
Assert.Equal(1, meta.TextData.Count);
Assert.Equal("Software", meta.TextData[0].Keyword);
Assert.Equal("paint.net 4.0.6", meta.TextData[0].Value);
Assert.Equal(0.4545d, meta.Gamma, precision: 4);
}
[Fact]
public void Decode_IgnoreMetadataIsTrue_TextChunksAreIgnored()
{
var options = new PngDecoder
DecoderOptions options = new()
{
IgnoreMetadata = true
SkipMetadata = true
};
var testFile = TestFile.Create(TestImages.Png.PngWithMetadata);
using (Image<Rgba32> image = testFile.CreateRgba32Image(options))
{
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Equal(0, meta.TextData.Count);
}
using Image<Rgba32> image = testFile.CreateRgba32Image(new PngDecoder(), options);
PngMetadata meta = image.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.Equal(0, meta.TextData.Count);
}
[Theory]
@ -209,17 +193,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
var decoder = new PngDecoder();
using (Image<Rgba32> image = decoder.Decode<Rgba32>(Configuration.Default, stream, default))
{
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
}
using var stream = new MemoryStream(testFile.Bytes, false);
var decoder = new PngDecoder();
using Image<Rgba32> image = decoder.Decode<Rgba32>(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -227,26 +207,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> input = provider.GetImage(new PngDecoder()))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream())
{
input.Save(memStream, new PngEncoder());
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
}
}
using Image<TPixel> input = provider.GetImage(new PngDecoder());
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using var memStream = new MemoryStream();
input.Save(memStream, new PngEncoder());
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
[Theory]
@ -254,15 +228,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
var decoder = new PngDecoder();
IImageInfo image = decoder.Identify(Configuration.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
using var stream = new MemoryStream(testFile.Bytes, false);
var decoder = new PngDecoder();
IImageInfo image = decoder.Identify(DecoderOptions.Default, stream, default);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
Assert.Equal(resolutionUnit, meta.ResolutionUnits);
}
[Theory]
@ -270,13 +242,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Identify_ReadsTextData(string imagePath)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
PngMetadata meta = imageInfo.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
PngMetadata meta = imageInfo.Metadata.GetFormatMetadata(PngFormat.Instance);
VerifyTextDataIsPresent(meta);
}
[Theory]
@ -284,14 +254,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Identify_ReadsExifData(string imagePath)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.Metadata.ExifProfile);
ExifProfile exif = imageInfo.Metadata.ExifProfile;
VerifyExifDataIsPresent(exif);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.Metadata.ExifProfile);
ExifProfile exif = imageInfo.Metadata.ExifProfile;
VerifyExifDataIsPresent(exif);
}
private static void VerifyExifDataIsPresent(ExifProfile exif)
@ -323,28 +291,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Identify_ReadsLegacyExifData(string imagePath)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.Metadata.ExifProfile);
PngMetadata meta = imageInfo.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.DoesNotContain(meta.TextData, t => t.Keyword.Equals("Raw profile type exif", StringComparison.OrdinalIgnoreCase));
ExifProfile exif = imageInfo.Metadata.ExifProfile;
Assert.Equal(0, exif.InvalidTags.Count);
Assert.Equal(3, exif.Values.Count);
Assert.Equal(
"A colorful tiling of blue, red, yellow, and green 4x4 pixel blocks.",
exif.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal(
"Duplicated from basn3p02.png, then image metadata modified with exiv2",
exif.GetValue(ExifTag.ImageHistory).Value);
Assert.Equal(42, (int)exif.GetValue(ExifTag.ImageNumber).Value);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.Metadata.ExifProfile);
PngMetadata meta = imageInfo.Metadata.GetFormatMetadata(PngFormat.Instance);
Assert.DoesNotContain(meta.TextData, t => t.Keyword.Equals("Raw profile type exif", StringComparison.OrdinalIgnoreCase));
ExifProfile exif = imageInfo.Metadata.ExifProfile;
Assert.Equal(0, exif.InvalidTags.Count);
Assert.Equal(3, exif.Values.Count);
Assert.Equal(
"A colorful tiling of blue, red, yellow, and green 4x4 pixel blocks.",
exif.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal(
"Duplicated from basn3p02.png, then image metadata modified with exiv2",
exif.GetValue(ExifTag.ImageHistory).Value);
Assert.Equal(42, (int)exif.GetValue(ExifTag.ImageNumber).Value);
}
}
}

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

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

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

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

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

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Metadata;
@ -50,24 +51,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void TiffFrameMetadata_CloneIsDeep<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TiffDecoder))
{
TiffFrameMetadata meta = image.Frames.RootFrame.Metadata.GetTiffMetadata();
var cloneSameAsSampleMetaData = (TiffFrameMetadata)meta.DeepClone();
VerifyExpectedTiffFrameMetaDataIsPresent(cloneSameAsSampleMetaData);
using Image<TPixel> image = provider.GetImage(TiffDecoder);
TiffFrameMetadata meta = image.Frames.RootFrame.Metadata.GetTiffMetadata();
var cloneSameAsSampleMetaData = (TiffFrameMetadata)meta.DeepClone();
VerifyExpectedTiffFrameMetaDataIsPresent(cloneSameAsSampleMetaData);
var clone = (TiffFrameMetadata)meta.DeepClone();
var clone = (TiffFrameMetadata)meta.DeepClone();
clone.BitsPerPixel = TiffBitsPerPixel.Bit8;
clone.Compression = TiffCompression.None;
clone.PhotometricInterpretation = TiffPhotometricInterpretation.CieLab;
clone.Predictor = TiffPredictor.Horizontal;
clone.BitsPerPixel = TiffBitsPerPixel.Bit8;
clone.Compression = TiffCompression.None;
clone.PhotometricInterpretation = TiffPhotometricInterpretation.CieLab;
clone.Predictor = TiffPredictor.Horizontal;
Assert.False(meta.BitsPerPixel == clone.BitsPerPixel);
Assert.False(meta.Compression == clone.Compression);
Assert.False(meta.PhotometricInterpretation == clone.PhotometricInterpretation);
Assert.False(meta.Predictor == clone.Predictor);
}
Assert.False(meta.BitsPerPixel == clone.BitsPerPixel);
Assert.False(meta.Compression == clone.Compression);
Assert.False(meta.PhotometricInterpretation == clone.PhotometricInterpretation);
Assert.False(meta.Predictor == clone.Predictor);
}
private static void VerifyExpectedTiffFrameMetaDataIsPresent(TiffFrameMetadata frameMetaData)
@ -119,23 +118,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void MetadataProfiles<TPixel>(TestImageProvider<TPixel> provider, bool ignoreMetadata)
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();
ImageFrameMetadata rootFrameMetaData = image.Frames.RootFrame.Metadata;
Assert.NotNull(meta);
if (ignoreMetadata)
{
Assert.Null(rootFrameMetaData.XmpProfile);
Assert.Null(rootFrameMetaData.ExifProfile);
}
else
{
TiffMetadata meta = image.Metadata.GetTiffMetadata();
ImageFrameMetadata rootFrameMetaData = image.Frames.RootFrame.Metadata;
Assert.NotNull(meta);
if (ignoreMetadata)
{
Assert.Null(rootFrameMetaData.XmpProfile);
Assert.Null(rootFrameMetaData.ExifProfile);
}
else
{
Assert.NotNull(rootFrameMetaData.XmpProfile);
Assert.NotNull(rootFrameMetaData.ExifProfile);
Assert.Equal(2599, rootFrameMetaData.XmpProfile.Data.Length);
Assert.Equal(26, rootFrameMetaData.ExifProfile.Values.Count);
}
Assert.NotNull(rootFrameMetaData.XmpProfile);
Assert.NotNull(rootFrameMetaData.ExifProfile);
Assert.Equal(2599, rootFrameMetaData.XmpProfile.Data.Length);
Assert.Equal(26, rootFrameMetaData.ExifProfile.Values.Count);
}
}
@ -158,63 +157,61 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void BaselineTags<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TiffDecoder))
{
ImageFrame<TPixel> rootFrame = image.Frames.RootFrame;
Assert.Equal(32, rootFrame.Width);
Assert.Equal(32, rootFrame.Height);
Assert.NotNull(rootFrame.Metadata.XmpProfile);
Assert.Equal(2599, rootFrame.Metadata.XmpProfile.Data.Length);
ExifProfile exifProfile = rootFrame.Metadata.ExifProfile;
TiffFrameMetadata tiffFrameMetadata = rootFrame.Metadata.GetTiffMetadata();
Assert.NotNull(exifProfile);
// The original exifProfile has 30 values, but 4 of those values will be stored in the TiffFrameMetaData
// and removed from the profile on decode.
Assert.Equal(26, exifProfile.Values.Count);
Assert.Equal(TiffBitsPerPixel.Bit4, tiffFrameMetadata.BitsPerPixel);
Assert.Equal(TiffCompression.Lzw, tiffFrameMetadata.Compression);
Assert.Equal("This is Название", exifProfile.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal("This is Изготовитель камеры", exifProfile.GetValue(ExifTag.Make).Value);
Assert.Equal("This is Модель камеры", exifProfile.GetValue(ExifTag.Model).Value);
Assert.Equal("IrfanView", exifProfile.GetValue(ExifTag.Software).Value);
Assert.Null(exifProfile.GetValue(ExifTag.DateTime)?.Value);
Assert.Equal("This is author1;Author2", exifProfile.GetValue(ExifTag.Artist).Value);
Assert.Null(exifProfile.GetValue(ExifTag.HostComputer)?.Value);
Assert.Equal("This is Авторские права", exifProfile.GetValue(ExifTag.Copyright).Value);
Assert.Equal(4, exifProfile.GetValue(ExifTag.Rating).Value);
Assert.Equal(75, exifProfile.GetValue(ExifTag.RatingPercent).Value);
var expectedResolution = new Rational(10000, 1000, simplify: false);
Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.XResolution).Value);
Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.YResolution).Value);
Assert.Equal(new Number[] { 8u }, exifProfile.GetValue(ExifTag.StripOffsets)?.Value, new NumberComparer());
Assert.Equal(new Number[] { 297u }, exifProfile.GetValue(ExifTag.StripByteCounts)?.Value, new NumberComparer());
Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples)?.Value);
Assert.Equal(32u, exifProfile.GetValue(ExifTag.RowsPerStrip).Value);
Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat));
Assert.Equal(TiffPredictor.None, tiffFrameMetadata.Predictor);
Assert.Equal(PixelResolutionUnit.PixelsPerInch, UnitConverter.ExifProfileToResolutionUnit(exifProfile));
ushort[] colorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value;
Assert.NotNull(colorMap);
Assert.Equal(48, colorMap.Length);
Assert.Equal(10537, colorMap[0]);
Assert.Equal(14392, colorMap[1]);
Assert.Equal(58596, colorMap[46]);
Assert.Equal(3855, colorMap[47]);
Assert.Equal(TiffPhotometricInterpretation.PaletteColor, tiffFrameMetadata.PhotometricInterpretation);
Assert.Equal(1u, exifProfile.GetValue(ExifTag.SamplesPerPixel).Value);
ImageMetadata imageMetaData = image.Metadata;
Assert.NotNull(imageMetaData);
Assert.Equal(PixelResolutionUnit.PixelsPerInch, imageMetaData.ResolutionUnits);
Assert.Equal(10, imageMetaData.HorizontalResolution);
Assert.Equal(10, imageMetaData.VerticalResolution);
TiffMetadata tiffMetaData = image.Metadata.GetTiffMetadata();
Assert.NotNull(tiffMetaData);
Assert.Equal(ByteOrder.LittleEndian, tiffMetaData.ByteOrder);
}
using Image<TPixel> image = provider.GetImage(TiffDecoder);
ImageFrame<TPixel> rootFrame = image.Frames.RootFrame;
Assert.Equal(32, rootFrame.Width);
Assert.Equal(32, rootFrame.Height);
Assert.NotNull(rootFrame.Metadata.XmpProfile);
Assert.Equal(2599, rootFrame.Metadata.XmpProfile.Data.Length);
ExifProfile exifProfile = rootFrame.Metadata.ExifProfile;
TiffFrameMetadata tiffFrameMetadata = rootFrame.Metadata.GetTiffMetadata();
Assert.NotNull(exifProfile);
// The original exifProfile has 30 values, but 4 of those values will be stored in the TiffFrameMetaData
// and removed from the profile on decode.
Assert.Equal(26, exifProfile.Values.Count);
Assert.Equal(TiffBitsPerPixel.Bit4, tiffFrameMetadata.BitsPerPixel);
Assert.Equal(TiffCompression.Lzw, tiffFrameMetadata.Compression);
Assert.Equal("This is Название", exifProfile.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal("This is Изготовитель камеры", exifProfile.GetValue(ExifTag.Make).Value);
Assert.Equal("This is Модель камеры", exifProfile.GetValue(ExifTag.Model).Value);
Assert.Equal("IrfanView", exifProfile.GetValue(ExifTag.Software).Value);
Assert.Null(exifProfile.GetValue(ExifTag.DateTime)?.Value);
Assert.Equal("This is author1;Author2", exifProfile.GetValue(ExifTag.Artist).Value);
Assert.Null(exifProfile.GetValue(ExifTag.HostComputer)?.Value);
Assert.Equal("This is Авторские права", exifProfile.GetValue(ExifTag.Copyright).Value);
Assert.Equal(4, exifProfile.GetValue(ExifTag.Rating).Value);
Assert.Equal(75, exifProfile.GetValue(ExifTag.RatingPercent).Value);
var expectedResolution = new Rational(10000, 1000, simplify: false);
Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.XResolution).Value);
Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.YResolution).Value);
Assert.Equal(new Number[] { 8u }, exifProfile.GetValue(ExifTag.StripOffsets)?.Value, new NumberComparer());
Assert.Equal(new Number[] { 297u }, exifProfile.GetValue(ExifTag.StripByteCounts)?.Value, new NumberComparer());
Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples)?.Value);
Assert.Equal(32u, exifProfile.GetValue(ExifTag.RowsPerStrip).Value);
Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat));
Assert.Equal(TiffPredictor.None, tiffFrameMetadata.Predictor);
Assert.Equal(PixelResolutionUnit.PixelsPerInch, UnitConverter.ExifProfileToResolutionUnit(exifProfile));
ushort[] colorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value;
Assert.NotNull(colorMap);
Assert.Equal(48, colorMap.Length);
Assert.Equal(10537, colorMap[0]);
Assert.Equal(14392, colorMap[1]);
Assert.Equal(58596, colorMap[46]);
Assert.Equal(3855, colorMap[47]);
Assert.Equal(TiffPhotometricInterpretation.PaletteColor, tiffFrameMetadata.PhotometricInterpretation);
Assert.Equal(1u, exifProfile.GetValue(ExifTag.SamplesPerPixel).Value);
ImageMetadata imageMetaData = image.Metadata;
Assert.NotNull(imageMetaData);
Assert.Equal(PixelResolutionUnit.PixelsPerInch, imageMetaData.ResolutionUnits);
Assert.Equal(10, imageMetaData.HorizontalResolution);
Assert.Equal(10, imageMetaData.VerticalResolution);
TiffMetadata tiffMetaData = image.Metadata.GetTiffMetadata();
Assert.NotNull(tiffMetaData);
Assert.Equal(ByteOrder.LittleEndian, tiffMetaData.ByteOrder);
}
[Theory]
@ -222,23 +219,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void SubfileType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TiffDecoder))
{
TiffMetadata meta = image.Metadata.GetTiffMetadata();
Assert.NotNull(meta);
using Image<TPixel> image = provider.GetImage(TiffDecoder);
TiffMetadata meta = image.Metadata.GetTiffMetadata();
Assert.NotNull(meta);
Assert.Equal(2, image.Frames.Count);
Assert.Equal(2, image.Frames.Count);
ExifProfile frame0Exif = image.Frames[0].Metadata.ExifProfile;
Assert.Equal(TiffNewSubfileType.FullImage, (TiffNewSubfileType)frame0Exif.GetValue(ExifTag.SubfileType).Value);
Assert.Equal(255, image.Frames[0].Width);
Assert.Equal(255, image.Frames[0].Height);
ExifProfile frame0Exif = image.Frames[0].Metadata.ExifProfile;
Assert.Equal(TiffNewSubfileType.FullImage, (TiffNewSubfileType)frame0Exif.GetValue(ExifTag.SubfileType).Value);
Assert.Equal(255, image.Frames[0].Width);
Assert.Equal(255, image.Frames[0].Height);
ExifProfile frame1Exif = image.Frames[1].Metadata.ExifProfile;
Assert.Equal(TiffNewSubfileType.Preview, (TiffNewSubfileType)frame1Exif.GetValue(ExifTag.SubfileType).Value);
Assert.Equal(255, image.Frames[1].Width);
Assert.Equal(255, image.Frames[1].Height);
}
ExifProfile frame1Exif = image.Frames[1].Metadata.ExifProfile;
Assert.Equal(TiffNewSubfileType.Preview, (TiffNewSubfileType)frame1Exif.GetValue(ExifTag.SubfileType).Value);
Assert.Equal(255, image.Frames[1].Width);
Assert.Equal(255, image.Frames[1].Height);
}
[Theory]
@ -247,7 +242,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
where TPixel : unmanaged, IPixel<TPixel>
{
// 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;
ImageFrame<TPixel> rootFrameInput = image.Frames.RootFrame;

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

@ -3,7 +3,6 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Webp.Lossless;
using SixLabors.ImageSharp.PixelFormats;
#if SUPPORTS_RUNTIME_INTRINSICS
@ -104,7 +103,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(expectedData, transformData);
}
// Test image: Input\Png\Bike.png
private static void RunColorSpaceTransformTestWithBikeImage()
{
// arrange
@ -119,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
// Convert image pixels to bgra array.
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);
int colorTransformBits = 4;

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

@ -2,8 +2,8 @@
// Licensed under the Six Labors Split License.
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
@ -44,14 +44,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
int expectedBitsPerPixel)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedWidth, imageInfo.Width);
Assert.Equal(expectedHeight, imageInfo.Height);
Assert.Equal(expectedBitsPerPixel, imageInfo.PixelType.BitsPerPixel);
}
using var stream = new MemoryStream(testFile.Bytes, false);
IImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedWidth, imageInfo.Width);
Assert.Equal(expectedHeight, imageInfo.Height);
Assert.Equal(expectedBitsPerPixel, imageInfo.PixelType.BitsPerPixel);
}
[Theory]
@ -67,11 +65,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithoutFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -83,11 +79,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithSimpleFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -106,11 +100,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithComplexFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -121,11 +113,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_VerySmall<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -140,11 +130,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithPartitions<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -154,11 +142,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithSegmentation<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -171,11 +157,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithSharpnessLevel<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -196,11 +180,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossy_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -208,11 +190,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -221,11 +201,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithoutTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -240,11 +218,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -256,11 +232,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithColorIndexTransform<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -269,11 +243,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithPredictorTransform<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -282,11 +254,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithCrossColorTransform<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -306,11 +276,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithTwoTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -325,11 +293,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Lossless_WithThreeTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -337,18 +303,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void Decode_AnimatedLossless_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata();
WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata();
image.DebugSaveMultiFrame(provider);
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact);
Assert.Equal(0, webpMetaData.AnimationLoopCount);
Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata();
WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata();
image.DebugSaveMultiFrame(provider);
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact);
Assert.Equal(0, webpMetaData.AnimationLoopCount);
Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count);
}
[Theory]
@ -356,18 +320,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void Decode_AnimatedLossy_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata();
WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata();
image.DebugSaveMultiFrame(provider);
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Tolerant(0.04f));
Assert.Equal(0, webpMetaData.AnimationLoopCount);
Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata();
WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata();
image.DebugSaveMultiFrame(provider);
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Tolerant(0.04f));
Assert.Equal(0, webpMetaData.AnimationLoopCount);
Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count);
}
[Theory]
@ -375,10 +337,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void Decode_AnimatedLossless_WithFrameDecodingModeFirst_OnlyDecodesOneFrame<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new WebpDecoder() { DecodingMode = FrameDecodingMode.First }))
{
Assert.Equal(1, image.Frames.Count);
}
DecoderOptions options = new() { MaxFrames = 1 };
using Image<TPixel> image = provider.GetImage(new WebpDecoder(), options);
Assert.Equal(1, image.Frames.Count);
}
[Theory]
@ -389,10 +350,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
where TPixel : unmanaged, IPixel<TPixel>
{
// Just make sure no exception is thrown. The reference decoder fails to load the image.
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
}
// https://github.com/SixLabors/ImageSharp/issues/1594
@ -401,11 +360,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void WebpDecoder_CanDecode_Issue1594<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<TPixel> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Theory]
@ -424,41 +381,33 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
private static void RunDecodeLossyWithHorizontalFilter()
{
var provider = TestImageProvider<Rgba32>.File(TestImageLossyHorizontalFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<Rgba32> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
private static void RunDecodeLossyWithVerticalFilter()
{
var provider = TestImageProvider<Rgba32>.File(TestImageLossyVerticalFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<Rgba32> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
private static void RunDecodeLossyWithSimpleFilterTest()
{
var provider = TestImageProvider<Rgba32>.File(TestImageLossySimpleFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<Rgba32> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
private static void RunDecodeLossyWithComplexFilterTest()
{
var provider = TestImageProvider<Rgba32>.File(TestImageLossyComplexFilterPath);
using (Image<Rgba32> image = provider.GetImage(WebpDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
using Image<Rgba32> image = provider.GetImage(WebpDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ReferenceDecoder);
}
[Fact]

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

@ -4,6 +4,7 @@
using System;
using System.IO;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
[Trait("Format", "Webp")]
public class WebpMetaDataTests
{
private static WebpDecoder WebpDecoder => new() { IgnoreMetadata = false };
private static WebpDecoder WebpDecoder => new();
[Theory]
[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)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(decoder);
DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(WebpDecoder, options);
if (ignoreMetadata)
{
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)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(decoder);
DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(WebpDecoder, options);
if (ignoreMetadata)
{
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)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(decoder);
DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = provider.GetImage(WebpDecoder, options);
if (ignoreMetadata)
{
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)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new WebpDecoder { IgnoreMetadata = ignoreMetadata };
using Image<TPixel> image = await provider.GetImageAsync(decoder);
DecoderOptions options = new() { SkipMetadata = ignoreMetadata };
using Image<TPixel> image = await provider.GetImageAsync(WebpDecoder, options);
if (ignoreMetadata)
{
Assert.Null(image.Metadata.XmpProfile);
@ -178,29 +175,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
public void Encode_PreservesColorProfile<TPixel>(TestImageProvider<TPixel> provider, WebpFileFormatType fileFormat)
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;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using var memStream = new MemoryStream();
input.Save(memStream, new WebpEncoder()
{
ImageSharp.Metadata.Profiles.Icc.IccProfile expectedProfile = input.Metadata.IccProfile;
byte[] expectedProfileBytes = expectedProfile.ToByteArray();
using (var memStream = new MemoryStream())
{
input.Save(memStream, new WebpEncoder()
{
FileFormat = fileFormat
});
memStream.Position = 0;
using (var output = Image.Load<Rgba32>(memStream))
{
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
}
}
FileFormat = fileFormat
});
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
ImageSharp.Metadata.Profiles.Icc.IccProfile actualProfile = output.Metadata.IccProfile;
byte[] actualProfileBytes = actualProfile.ToByteArray();
Assert.NotNull(actualProfile);
Assert.Equal(expectedProfileBytes, actualProfileBytes);
}
[Theory]

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.
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
@ -15,101 +15,138 @@ namespace SixLabors.ImageSharp.Tests
public class Decode_Cancellation : ImageLoadTestBase
{
private bool isTestStreamSeekable;
private readonly SemaphoreSlim notifyWaitPositionReachedSemaphore = new SemaphoreSlim(0);
private readonly SemaphoreSlim continueSemaphore = new SemaphoreSlim(0);
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private readonly SemaphoreSlim notifyWaitPositionReachedSemaphore = new(0);
private readonly SemaphoreSlim continueSemaphore = new(0);
private readonly CancellationTokenSource cts = new();
public Decode_Cancellation()
{
this.TopLevelConfiguration.StreamProcessingBufferSize = 128;
}
public Decode_Cancellation() => this.TopLevelConfiguration.StreamProcessingBufferSize = 128;
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task LoadAsync_Specific_Stream(bool isInputStreamSeekable)
public Task LoadAsync_Specific_Stream(bool isInputStreamSeekable)
{
this.isTestStreamSeekable = isInputStreamSeekable;
_ = 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]
[InlineData(false)]
[InlineData(true)]
public async Task LoadAsync_Agnostic_Stream(bool isInputStreamSeekable)
public Task LoadAsync_Agnostic_Stream(bool isInputStreamSeekable)
{
this.isTestStreamSeekable = isInputStreamSeekable;
_ = 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]
public async Task LoadAsync_Agnostic_Path()
public Task LoadAsync_Agnostic_Path()
{
this.isTestStreamSeekable = true;
_ = 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]
public async Task LoadAsync_Specific_Path()
public Task LoadAsync_Specific_Path()
{
this.isTestStreamSeekable = true;
_ = 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]
[InlineData(false)]
[InlineData(true)]
public async Task IdentifyAsync_Stream(bool isInputStreamSeekable)
public Task IdentifyAsync_Stream(bool isInputStreamSeekable)
{
this.isTestStreamSeekable = isInputStreamSeekable;
_ = 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]
public async Task IdentifyAsync_CustomConfiguration_Path()
public Task IdentifyAsync_CustomConfiguration_Path()
{
this.isTestStreamSeekable = true;
_ = 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]
[InlineData(false)]
[InlineData(true)]
public async Task IdentifyWithFormatAsync_CustomConfiguration_Stream(bool isInputStreamSeekable)
public Task IdentifyWithFormatAsync_CustomConfiguration_Stream(bool isInputStreamSeekable)
{
this.isTestStreamSeekable = isInputStreamSeekable;
_ = 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]
public async Task IdentifyWithFormatAsync_CustomConfiguration_Path()
public Task IdentifyWithFormatAsync_CustomConfiguration_Path()
{
this.isTestStreamSeekable = true;
_ = 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]
public async Task IdentifyWithFormatAsync_DefaultConfiguration_Stream()
public Task IdentifyWithFormatAsync_DefaultConfiguration_Stream()
{
_ = 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()

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

@ -29,26 +29,23 @@ namespace SixLabors.ImageSharp.Tests
private static readonly IImageFormat ExpectedGlobalFormat =
Configuration.Default.ImageFormatsManager.FindFormatByFileExtension("bmp");
[Theory]
[InlineData(false)]
[InlineData(true)]
public void FromBytes_GlobalConfiguration(bool useSpan)
[Fact]
public void FromBytes_GlobalConfiguration()
{
IImageFormat type = useSpan
? Image.DetectFormat(this.ActualImageSpan)
: Image.DetectFormat(this.ActualImageBytes);
IImageFormat type = Image.DetectFormat(this.ActualImageSpan);
Assert.Equal(ExpectedGlobalFormat, type);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void FromBytes_CustomConfiguration(bool useSpan)
[Fact]
public void FromBytes_CustomConfiguration()
{
IImageFormat type = useSpan
? Image.DetectFormat(this.LocalConfiguration, this.ByteArray.AsSpan())
: Image.DetectFormat(this.LocalConfiguration, this.ByteArray);
DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
IImageFormat type = Image.DetectFormat(options, this.ByteArray);
Assert.Equal(this.LocalImageFormat, type);
}
@ -63,7 +60,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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);
}
@ -80,14 +82,24 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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);
}
[Fact]
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);
}
@ -104,14 +116,24 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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);
}
[Fact]
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);
}
}

105
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 Size ExpectedImageSize = new Size(108, 202);
private static readonly Size ExpectedImageSize = new(108, 202);
private static byte[] ActualImageBytes => TestFile.Create(TestImages.Bmp.F).Bytes;
@ -43,7 +43,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.LocalImageFormat, type);
@ -61,7 +66,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.LocalImageFormat, type);
@ -70,24 +80,20 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void FromStream_GlobalConfiguration()
{
using (var stream = new MemoryStream(ActualImageBytes))
{
IImageInfo info = Image.Identify(stream, out IImageFormat type);
using var stream = new MemoryStream(ActualImageBytes);
IImageInfo info = Image.Identify(stream, out IImageFormat type);
Assert.NotNull(info);
Assert.Equal(ExpectedGlobalFormat, type);
}
Assert.NotNull(info);
Assert.Equal(ExpectedGlobalFormat, type);
}
[Fact]
public void FromStream_GlobalConfiguration_NoFormat()
{
using (var stream = new MemoryStream(ActualImageBytes))
{
IImageInfo info = Image.Identify(stream);
using var stream = new MemoryStream(ActualImageBytes);
IImageInfo info = Image.Identify(stream);
Assert.NotNull(info);
}
Assert.NotNull(info);
}
[Fact]
@ -116,7 +122,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.LocalImageFormat, type);
@ -125,7 +136,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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);
}
@ -133,7 +149,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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(type);
@ -168,26 +189,22 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public async Task FromStreamAsync_GlobalConfiguration_NoFormat()
{
using (var stream = new MemoryStream(ActualImageBytes))
{
var asyncStream = new AsyncStreamWrapper(stream, () => false);
IImageInfo info = await Image.IdentifyAsync(asyncStream);
using var stream = new MemoryStream(ActualImageBytes);
var asyncStream = new AsyncStreamWrapper(stream, () => false);
IImageInfo info = await Image.IdentifyAsync(asyncStream);
Assert.NotNull(info);
}
Assert.NotNull(info);
}
[Fact]
public async Task FromStreamAsync_GlobalConfiguration()
{
using (var stream = new MemoryStream(ActualImageBytes))
{
var asyncStream = new AsyncStreamWrapper(stream, () => false);
(IImageInfo ImageInfo, IImageFormat Format) res = await Image.IdentifyWithFormatAsync(asyncStream);
using var stream = new MemoryStream(ActualImageBytes);
var asyncStream = new AsyncStreamWrapper(stream, () => false);
(IImageInfo ImageInfo, IImageFormat Format) res = await Image.IdentifyWithFormatAsync(asyncStream);
Assert.Equal(ExpectedImageSize, res.ImageInfo.Size());
Assert.Equal(ExpectedGlobalFormat, res.Format);
}
Assert.Equal(ExpectedImageSize, res.ImageInfo.Size());
Assert.Equal(ExpectedGlobalFormat, res.Format);
}
[Fact]
@ -244,14 +261,24 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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);
}
[Fact]
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.Equal(this.LocalImageFormat, info.Format);
}
@ -276,8 +303,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public async Task FromStreamAsync_CustomConfiguration()
{
DecoderOptions options = new()
{
Configuration = this.LocalConfiguration
};
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.LocalImageFormat, info.Format);
@ -286,8 +318,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull()
{
DecoderOptions options = new()
{
Configuration = new()
};
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);
}

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

@ -63,28 +63,27 @@ namespace SixLabors.ImageSharp.Tests
this.localImageFormatMock = new Mock<IImageFormat>();
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.Setup(x => x.Decode<Rgba32>(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.Callback<Configuration, Stream, CancellationToken>((c, s, ct) =>
this.localDecoder
.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())
{
s.CopyTo(ms);
this.DecodedData = ms.ToArray();
}
using var ms = new MemoryStream();
s.CopyTo(ms);
this.DecodedData = ms.ToArray();
})
.Returns(this.localStreamReturnImageRgba32);
this.localDecoder.Setup(x => x.Decode(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.Callback<Configuration, Stream, CancellationToken>((c, s, ct) =>
this.localDecoder
.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())
{
s.CopyTo(ms);
this.DecodedData = ms.ToArray();
}
using var ms = new MemoryStream();
s.CopyTo(ms);
this.DecodedData = ms.ToArray();
})
.Returns(this.localStreamReturnImageAgnostic);

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

@ -16,7 +16,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.Equal(this.TestFormat.Sample<Rgb24>(), img);
@ -27,7 +32,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.Equal(this.TestFormat.SampleAgnostic(), img);
@ -35,28 +45,15 @@ namespace SixLabors.ImageSharp.Tests
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}
[Fact]
public void Configuration_Path_Decoder_Specific()
{
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object);
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);
Assert.NotNull(img);
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);
DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgba32>(options, this.MockFilePath, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
@ -67,7 +64,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.Equal(this.TestFormat, format);
@ -77,23 +79,28 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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]
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.
using System;
using System.IO;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
@ -17,10 +18,7 @@ namespace SixLabors.ImageSharp.Tests
{
private string Path { get; } = TestFile.GetInputFileFullPath(TestImages.Bmp.Bit8);
private static void VerifyDecodedImage(Image img)
{
Assert.Equal(new Size(127, 64), img.Size());
}
private static void VerifyDecodedImage(Image img) => Assert.Equal(new Size(127, 64), img.Size());
[Fact]
public void Path_Specific()
@ -39,49 +37,21 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public async Task Path_Agnostic_Async()
{
using var img = await Image.LoadAsync(this.Path);
using Image img = await Image.LoadAsync(this.Path);
VerifyDecodedImage(img);
}
[Fact]
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);
}
[Fact]
public async Task Path_Agnostic_Configuration_Async()
{
using var 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());
using Image img = await Image.LoadAsync(this.Path);
VerifyDecodedImage(img);
}
@ -103,37 +73,19 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void WhenFileNotFound_Throws()
{
Assert.Throws<System.IO.FileNotFoundException>(
() =>
{
Image.Load<Rgba32>(Guid.NewGuid().ToString());
});
}
=> Assert.Throws<FileNotFoundException>(() => Image.Load<Rgba32>(Guid.NewGuid().ToString()));
[Fact]
public void WhenPathIsNull_Throws()
{
Assert.Throws<ArgumentNullException>(
() =>
{
Image.Load<Rgba32>((string)null);
});
}
=> Assert.Throws<ArgumentNullException>(() => Image.Load<Rgba32>((string)null));
[Fact]
public Task Async_WhenFileNotFound_Throws()
{
return Assert.ThrowsAsync<System.IO.FileNotFoundException>(
() => Image.LoadAsync<Rgba32>(Guid.NewGuid().ToString()));
}
=> Assert.ThrowsAsync<FileNotFoundException>(() => Image.LoadAsync<Rgba32>(Guid.NewGuid().ToString()));
[Fact]
public Task Async_WhenPathIsNull_Throws()
{
return Assert.ThrowsAsync<ArgumentNullException>(
() => Image.LoadAsync<Rgba32>((string)null));
}
=> Assert.ThrowsAsync<ArgumentNullException>(() => Image.LoadAsync<Rgba32>((string)null));
}
}
}

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

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

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

@ -16,81 +16,38 @@ namespace SixLabors.ImageSharp.Tests
{
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)
{
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);
}
}
private static void VerifyDecodedImage(Image img) => Assert.Equal(new Size(127, 64), img.Size());
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Bytes_Decoder_Specific(bool useSpan)
[Fact]
public void Bytes_Specific()
{
using (var img = useSpan ? Image.Load<Rgba32>(ByteSpan, new BmpDecoder()) : Image.Load<Rgba32>(ByteArray, new BmpDecoder()))
{
VerifyDecodedImage(img);
}
using var img = Image.Load<Rgba32>(ByteSpan);
VerifyDecodedImage(img);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Bytes_Decoder_Agnostic(bool useSpan)
[Fact]
public void Bytes_Agnostic()
{
using (var img = useSpan ? Image.Load(ByteSpan, new BmpDecoder()) : Image.Load(ByteArray, new BmpDecoder()))
{
VerifyDecodedImage(img);
}
using var img = Image.Load(ByteSpan);
VerifyDecodedImage(img);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Bytes_OutFormat_Specific(bool useSpan)
[Fact]
public void Bytes_OutFormat_Specific()
{
IImageFormat format;
using (var img = useSpan ? Image.Load<Rgba32>(ByteSpan, out format) : Image.Load<Rgba32>(ByteArray, out format))
{
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
using var img = Image.Load<Rgba32>(ByteSpan, out IImageFormat format);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Bytes_OutFormat_Agnostic(bool useSpan)
[Fact]
public void Bytes_OutFormat_Agnostic()
{
IImageFormat format;
using (var img = useSpan ? Image.Load(ByteSpan, out format) : Image.Load(ByteArray, out format))
{
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
using var img = Image.Load(ByteSpan, out IImageFormat format);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
}
}

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

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.IO;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
@ -17,7 +16,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.Equal(this.TestFormat.Sample<Rgb24>(), img);
@ -28,7 +32,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.Equal(this.TestFormat.SampleAgnostic(), img);
@ -39,8 +48,13 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void NonSeekableStream()
{
DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var stream = new NonSeekableStream(this.DataStream);
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, stream);
var img = Image.Load<Rgba32>(options, stream);
Assert.NotNull(img);
@ -50,38 +64,28 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public async Task NonSeekableStreamAsync()
{
DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
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);
this.TestFormat.VerifySpecificDecodeCall<Rgba32>(this.Marker, this.TopLevelConfiguration);
}
[Fact]
public void Configuration_Stream_Decoder_Specific()
{
var stream = new MemoryStream();
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();
var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object);
Assert.NotNull(img);
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);
DecoderOptions options = new()
{
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgba32>(options, this.DataStream, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
@ -92,7 +96,12 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
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.Equal(this.TestFormat, format);

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

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

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

@ -31,71 +31,43 @@ namespace SixLabors.ImageSharp.Tests
}
private static void VerifyDecodedImage(Image img)
{
Assert.Equal(new Size(127, 64), img.Size());
}
=> Assert.Equal(new Size(127, 64), img.Size());
[Fact]
public void Stream_Specific()
{
using (var img = Image.Load<Rgba32>(this.Stream))
{
VerifyDecodedImage(img);
}
using var img = Image.Load<Rgba32>(this.Stream);
VerifyDecodedImage(img);
}
[Fact]
public void Stream_Agnostic()
{
using (var img = Image.Load(this.Stream))
{
VerifyDecodedImage(img);
}
using var img = Image.Load(this.Stream);
VerifyDecodedImage(img);
}
[Fact]
public void Stream_OutFormat_Specific()
{
using (var img = Image.Load<Rgba32>(this.Stream, out IImageFormat format))
{
VerifyDecodedImage(img);
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);
}
using var img = Image.Load<Rgba32>(this.Stream, out IImageFormat format);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
[Fact]
public void Stream_OutFormat_Agnostic()
{
using (var img = Image.Load(this.Stream, out IImageFormat format))
{
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
using var img = Image.Load(this.Stream, out IImageFormat format);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
}
[Fact]
public async Task Async_Stream_OutFormat_Agnostic()
{
this.AllowSynchronousIO = false;
var formattedImage = await Image.LoadWithFormatAsync(this.Stream);
(Image Image, IImageFormat Format) formattedImage = await Image.LoadWithFormatAsync(this.Stream);
using (formattedImage.Image)
{
VerifyDecodedImage(formattedImage.Image);
@ -107,27 +79,23 @@ namespace SixLabors.ImageSharp.Tests
public async Task Async_Stream_Specific()
{
this.AllowSynchronousIO = false;
using (var img = await Image.LoadAsync<Rgba32>(this.Stream))
{
VerifyDecodedImage(img);
}
using Image<Rgba32> img = await Image.LoadAsync<Rgba32>(this.Stream);
VerifyDecodedImage(img);
}
[Fact]
public async Task Async_Stream_Agnostic()
{
this.AllowSynchronousIO = false;
using (var img = await Image.LoadAsync(this.Stream))
{
VerifyDecodedImage(img);
}
using Image img = await Image.LoadAsync(this.Stream);
VerifyDecodedImage(img);
}
[Fact]
public async Task Async_Stream_OutFormat_Specific()
{
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)
{
VerifyDecodedImage(formattedImage.Image);
@ -135,30 +103,7 @@ namespace SixLabors.ImageSharp.Tests
}
}
[Fact]
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();
}
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 SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Xunit;
@ -62,13 +61,18 @@ namespace SixLabors.ImageSharp.Tests
IImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder(
configuration.ImageFormatsManager.FindFormatByFileExtension(formatInner));
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))
{
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);
Assert.Equal(1, image.GetPixelMemoryGroup().Count);
}

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

@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
WebpLossy
}
private static readonly Dictionary<ExifTag, object> TestProfileValues = new Dictionary<ExifTag, object>
private static readonly Dictionary<ExifTag, object> TestProfileValues = new()
{
{ ExifTag.Software, "Software" },
{ ExifTag.Copyright, "Copyright" },
@ -125,42 +125,40 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
[InlineData(TestImageWriteFormat.WebpLossy)]
public void WriteFraction(TestImageWriteFormat imageFormat)
{
using (var memStream = new MemoryStream())
{
double exposureTime = 1.0 / 1600;
using var memStream = new MemoryStream();
double exposureTime = 1.0 / 1600;
ExifProfile profile = GetExifProfile();
ExifProfile profile = GetExifProfile();
profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime));
profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime));
var image = new Image<Rgba32>(1, 1);
image.Metadata.ExifProfile = profile;
var image = new Image<Rgba32>(1, 1);
image.Metadata.ExifProfile = profile;
image = WriteAndRead(image, imageFormat);
image = WriteAndRead(image, imageFormat);
profile = image.Metadata.ExifProfile;
Assert.NotNull(profile);
profile = image.Metadata.ExifProfile;
Assert.NotNull(profile);
IExifValue<Rational> value = profile.GetValue(ExifTag.ExposureTime);
Assert.NotNull(value);
Assert.NotEqual(exposureTime, value.Value.ToDouble());
IExifValue<Rational> value = profile.GetValue(ExifTag.ExposureTime);
Assert.NotNull(value);
Assert.NotEqual(exposureTime, value.Value.ToDouble());
memStream.Position = 0;
profile = GetExifProfile();
memStream.Position = 0;
profile = GetExifProfile();
profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime, true));
image.Metadata.ExifProfile = profile;
profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime, true));
image.Metadata.ExifProfile = profile;
image = WriteAndRead(image, imageFormat);
image = WriteAndRead(image, imageFormat);
profile = image.Metadata.ExifProfile;
Assert.NotNull(profile);
profile = image.Metadata.ExifProfile;
Assert.NotNull(profile);
value = profile.GetValue(ExifTag.ExposureTime);
Assert.Equal(exposureTime, value.Value.ToDouble());
value = profile.GetValue(ExifTag.ExposureTime);
Assert.Equal(exposureTime, value.Value.ToDouble());
image.Dispose();
}
image.Dispose();
}
[Theory]
@ -553,38 +551,32 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
private static Image<Rgba32> WriteAndReadJpeg(Image<Rgba32> image)
{
using (var memStream = new MemoryStream())
{
image.SaveAsJpeg(memStream);
image.Dispose();
using var memStream = new MemoryStream();
image.SaveAsJpeg(memStream);
image.Dispose();
memStream.Position = 0;
return Image.Load<Rgba32>(memStream);
}
memStream.Position = 0;
return Image.Load<Rgba32>(memStream);
}
private static Image<Rgba32> WriteAndReadPng(Image<Rgba32> image)
{
using (var memStream = new MemoryStream())
{
image.SaveAsPng(memStream);
image.Dispose();
using var memStream = new MemoryStream();
image.SaveAsPng(memStream);
image.Dispose();
memStream.Position = 0;
return Image.Load<Rgba32>(memStream);
}
memStream.Position = 0;
return Image.Load<Rgba32>(memStream);
}
private static Image<Rgba32> WriteAndReadWebp(Image<Rgba32> image, WebpFileFormatType fileFormat)
{
using (var memStream = new MemoryStream())
{
image.SaveAsWebp(memStream, new WebpEncoder() { FileFormat = fileFormat });
image.Dispose();
using var memStream = new MemoryStream();
image.SaveAsWebp(memStream, new WebpEncoder() { FileFormat = fileFormat });
image.Dispose();
memStream.Position = 0;
return Image.Load<Rgba32>(memStream, new WebpDecoder());
}
memStream.Position = 0;
return Image.Load<Rgba32>(memStream);
}
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
{
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()
{
@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
// arrange
var profile = new IptcProfile();
var value = new string('s', tag.MaxLength() + 1);
string value = new('s', tag.MaxLength() + 1);
int expectedLength = tag.MaxLength();
// act
@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
// arrange
var profile = new IptcProfile();
var value = new string('s', tag.MaxLength() + 1);
string value = new('s', tag.MaxLength() + 1);
int expectedLength = value.Length;
// act
@ -164,8 +164,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
// arrange
var profile = new IptcProfile();
var expectedCaptionWriter = "unittest";
var expectedCaption = "test";
const string expectedCaptionWriter = "unittest";
const string expectedCaption = "test";
profile.SetValue(IptcTag.CaptionWriter, expectedCaptionWriter);
profile.SetValue(IptcTag.Caption, expectedCaption);
@ -185,8 +185,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
// arrange
var profile = new IptcProfile();
var captionWriter = "unittest";
var caption = "test";
const string captionWriter = "unittest";
const string caption = "test";
profile.SetValue(IptcTag.CaptionWriter, captionWriter);
profile.SetValue(IptcTag.Caption, caption);
@ -222,8 +222,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
// arrange
var image = new Image<Rgba32>(1, 1);
image.Metadata.IptcProfile = new IptcProfile();
var expectedCaptionWriter = "unittest";
var expectedCaption = "test";
const string expectedCaptionWriter = "unittest";
const string expectedCaption = "test";
image.Metadata.IptcProfile.SetValue(IptcTag.CaptionWriter, expectedCaptionWriter);
image.Metadata.IptcProfile.SetValue(IptcTag.Caption, expectedCaption);
@ -257,8 +257,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
// arrange
var profile = new IptcProfile();
var expectedValue1 = "test";
var expectedValue2 = "another one";
const string expectedValue1 = "test";
const string expectedValue2 = "another one";
profile.SetValue(tag, expectedValue1, false);
// act
@ -309,7 +309,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
// arrange
var profile = new IptcProfile();
var expectedValue = "another one";
const string expectedValue = "another one";
profile.SetValue(tag, "test", false);
// act
@ -330,7 +330,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
profile.SetValue(IptcTag.Byline, "test2");
// act
var result = profile.RemoveValue(IptcTag.Byline);
bool result = profile.RemoveValue(IptcTag.Byline);
// assert
Assert.True(result, "removed result should be true");
@ -346,7 +346,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
profile.SetValue(IptcTag.Byline, "test2");
// act
var result = profile.RemoveValue(IptcTag.Byline, "test2");
bool result = profile.RemoveValue(IptcTag.Byline, "test2");
// assert
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
{
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]
[WithFile(TestImages.Gif.Receipt, PixelTypes.Rgba32)]

19
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.Jpeg420Exif_MidSizeYCbCr, 20 },
@ -38,16 +38,17 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
[MemberData(nameof(DecodeJpegData))]
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)
{
return;
@ -65,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
executionCount,
() =>
{
var img = Image.Load<Rgba32>(bytes, decoder);
var img = Image.Load<Rgba32>(options, bytes);
img.Dispose();
},
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line
@ -123,8 +124,8 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
}
},
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line
// ReSharper disable once ExplicitCallerInfoArgument
$@"Encode {testFiles.Length} images");
// ReSharper disable once ExplicitCallerInfoArgument
$"Encode {testFiles.Length} images");
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
}

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

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

56
tests/ImageSharp.Tests/TestFile.cs

@ -13,18 +13,18 @@ namespace SixLabors.ImageSharp.Tests
/// <summary>
/// A test image file.
/// </summary>
public class TestFile
public sealed class TestFile
{
/// <summary>
/// The test file cache.
/// </summary>
private static readonly ConcurrentDictionary<string, TestFile> Cache = new ConcurrentDictionary<string, TestFile>();
private static readonly ConcurrentDictionary<string, TestFile> Cache = new();
/// <summary>
/// The "Formats" directory, as lazy value
/// </summary>
// 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>
/// The image (lazy initialized value)
@ -40,15 +40,12 @@ namespace SixLabors.ImageSharp.Tests
/// Initializes a new instance of the <see cref="TestFile"/> class.
/// </summary>
/// <param name="file">The file.</param>
private TestFile(string file)
{
this.FullPath = file;
}
private TestFile(string file) => this.FullPath = file;
/// <summary>
/// Gets the image bytes.
/// </summary>
public byte[] Bytes => this.bytes ?? (this.bytes = File.ReadAllBytes(this.FullPath));
public byte[] Bytes => this.bytes ??= File.ReadAllBytes(this.FullPath);
/// <summary>
/// Gets the full path to file.
@ -68,7 +65,7 @@ namespace SixLabors.ImageSharp.Tests
/// <summary>
/// Gets the image with lazy initialization.
/// </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>
/// Gets the input image directory.
@ -85,9 +82,7 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="string"/>.
/// </returns>
public static string GetInputFileFullPath(string file)
{
return Path.Combine(InputImagesDirectory, file).Replace('\\', Path.DirectorySeparatorChar);
}
=> Path.Combine(InputImagesDirectory, file).Replace('\\', Path.DirectorySeparatorChar);
/// <summary>
/// Creates a new test file or returns one from the cache.
@ -97,9 +92,7 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="TestFile"/>.
/// </returns>
public static TestFile Create(string file)
{
return Cache.GetOrAdd(file, (string fileName) => new TestFile(GetInputFileFullPath(file)));
}
=> Cache.GetOrAdd(file, (string fileName) => new TestFile(GetInputFileFullPath(fileName)));
/// <summary>
/// Gets the file name.
@ -109,9 +102,7 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="string"/>.
/// </returns>
public string GetFileName(object value)
{
return $"{this.FileNameWithoutExtension}-{value}{Path.GetExtension(this.FullPath)}";
}
=> $"{this.FileNameWithoutExtension}-{value}{Path.GetExtension(this.FullPath)}";
/// <summary>
/// Gets the file name without extension.
@ -121,30 +112,37 @@ namespace SixLabors.ImageSharp.Tests
/// The <see cref="string"/>.
/// </returns>
public string GetFileNameWithoutExtension(object value)
{
return this.FileNameWithoutExtension + "-" + value;
}
=> this.FileNameWithoutExtension + "-" + value;
/// <summary>
/// Creates a new image.
/// Creates a new <see cref="Rgba32"/> image.
/// </summary>
/// <returns>
/// The <see cref="ImageSharp.Image"/>.
/// The <see cref="Image{Rgba32}"/>.
/// </returns>
public Image<Rgba32> CreateRgba32Image()
{
return this.Image.Clone();
}
=> this.Image.Clone();
/// <summary>
/// Creates a new image.
/// Creates a new <see cref="Rgba32"/> image.
/// </summary>
/// <returns>
/// The <see cref="ImageSharp.Image"/>.
/// The <see cref="Image{Rgba32}"/>.
/// </returns>
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>
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!
// 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)
{
var buffer = new byte[size];
byte[] buffer = new byte[size];
this.header.CopyTo(buffer, 0);
var semaphoreStream = new SemaphoreReadMemoryStream(buffer, waitAfterPosition, notifyWaitPositionReachedSemaphore, continueSemaphore);
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();
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)
{
@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests
{
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)
{
@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.Tests
public TestHeader(TestFormat testFormat) => this.testFormat = testFormat;
}
public class TestDecoder : IImageDecoder, IImageInfoDetector
public class TestDecoder : ImageDecoder<TestDecoderOptions>
{
private readonly TestFormat testFormat;
@ -206,20 +206,21 @@ namespace SixLabors.ImageSharp.Tests
public int HeaderSize => this.testFormat.HeaderSize;
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
=> this.DecodeImpl<TPixel>(configuration, stream);
public bool IsSupportedFileFormat(Span<byte> header) => this.testFormat.IsSupportedFileFormat(header);
private Image<TPixel> DecodeImpl<TPixel>(Configuration config, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
public override IImageInfo IdentifySpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> 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();
stream.CopyTo(ms, config.StreamProcessingBufferSize);
stream.CopyTo(ms, configuration.StreamProcessingBufferSize);
byte[] marker = ms.ToArray().Skip(this.testFormat.header.Length).ToArray();
this.testFormat.DecodeCalls.Add(new DecodeOperation
{
Marker = marker,
Config = config,
Config = configuration,
PixelType = typeof(TPixel)
});
@ -227,12 +228,13 @@ namespace SixLabors.ImageSharp.Tests
return this.testFormat.Sample<TPixel>();
}
public bool IsSupportedFileFormat(Span<byte> header) => this.testFormat.IsSupportedFileFormat(header);
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<TestPixelForAgnosticDecode>(configuration, stream, cancellationToken);
public override Image DecodeSpecialized(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<TestPixelForAgnosticDecode>(options, stream, cancellationToken);
}
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) =>
this.DecodeImpl<Rgba32>(configuration, stream);
public class TestDecoderOptions : ISpecializedDecoderOptions
{
public DecoderOptions GeneralOptions { get; set; } = new();
}
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.Reflection;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Diagnostics;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@ -90,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests
return false;
}
if (!object.Equals(kv.Value, otherVal))
if (!Equals(kv.Value, otherVal))
{
return false;
}
@ -126,7 +125,7 @@ namespace SixLabors.ImageSharp.Tests
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!
// ReSharper disable once UnusedMember.Local
@ -149,35 +148,78 @@ namespace SixLabors.ImageSharp.Tests
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(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.LoadImage(decoder);
return this.DecodeImage(decoder, options);
}
// do not cache so we can track allocation correctly when validating memory
if (MemoryAllocatorValidator.MonitoringAllocations)
{
return this.LoadImage(decoder);
return this.DecodeImage(decoder, options);
}
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);
}
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(options, nameof(options));
options.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);
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)
@ -193,10 +235,23 @@ namespace SixLabors.ImageSharp.Tests
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);
return Image.Load<TPixel>(this.Configuration, testFile.Bytes, decoder);
using Stream stream = new MemoryStream(testFile.Bytes);
return decoder.DecodeSpecialized<TPixel>(options, stream, default);
}
}

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

@ -53,19 +53,17 @@ namespace SixLabors.ImageSharp.Tests
=> new TestPatternProvider(width, height).Init(testMethod, pixelTypeOverride);
public static TestImageProvider<TPixel> Blank(
int width,
int height,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
=> new BlankProvider(width, height).Init(testMethod, pixelTypeOverride);
int width,
int height,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
=> new BlankProvider(width, height).Init(testMethod, pixelTypeOverride);
public static TestImageProvider<TPixel> File(
string filePath,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
{
return new FileProvider(filePath).Init(testMethod, pixelTypeOverride);
}
=> new FileProvider(filePath).Init(testMethod, pixelTypeOverride);
public static TestImageProvider<TPixel> Lambda(
string declaringTypeName,
@ -83,9 +81,7 @@ namespace SixLabors.ImageSharp.Tests
byte a = 255,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
{
return new SolidProvider(width, height, r, g, b, a).Init(testMethod, pixelTypeOverride);
}
=> new SolidProvider(width, height, r, g, b, a).Init(testMethod, pixelTypeOverride);
/// <summary>
/// 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>
public abstract Image<TPixel> GetImage();
public virtual Image<TPixel> GetImage(IImageDecoder decoder)
{
throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!");
}
public Image<TPixel> GetImage(IImageDecoder decoder)
=> this.GetImage(decoder, new());
public virtual Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder)
{
throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!");
}
public Task<Image<TPixel>> GetImageAsync(IImageDecoder decoder)
=> this.GetImageAsync(decoder, new());
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>
/// 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)
{
string subfolder = testMethod?.DeclaringType.GetAttribute<GroupOutputAttribute>()?.Subfolder
?? string.Empty;
string subfolder =
testMethod?.DeclaringType.GetAttribute<GroupOutputAttribute>()?.Subfolder ?? string.Empty;
return this.Init(testMethod?.DeclaringType.Name, testMethod?.Name, subfolder, pixelTypeOverride);
}
public override string ToString()
{
return $"{this.SourceFileOrDescription}[{this.PixelType}]";
}
=> $"{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
{
public class MagickReferenceDecoder : IImageDecoder
public class MagickReferenceDecoder : ImageDecoder<MagickReferenceDecoderOptions>
{
private readonly bool validate;
@ -28,39 +28,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder();
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 Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
public override Image<TPixel> DecodeSpecialized<TPixel>(MagickReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Configuration configuration = options.GeneralOptions.Configuration;
var bmpReadDefines = new BmpReadDefines
{
IgnoreFileSize = !this.validate
@ -100,6 +70,45 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
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();
}
}

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

@ -6,52 +6,53 @@ using System.Threading;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SDBitmap = System.Drawing.Bitmap;
using SDImage = System.Drawing.Image;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{
public class SystemDrawingReferenceDecoder : IImageDecoder, IImageInfoDetector
public class SystemDrawingReferenceDecoder : ImageDecoder<SystemDrawingReferenceDecoderOptions>
{
public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder();
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
public override IImageInfo IdentifySpecialized(SystemDrawingReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{
if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb)
{
return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sourceBitmap);
}
using (var convertedBitmap = new System.Drawing.Bitmap(
sourceBitmap.Width,
sourceBitmap.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
using (var g = System.Drawing.Graphics.FromImage(convertedBitmap))
{
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.DrawImage(sourceBitmap, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
}
return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(convertedBitmap);
}
}
using var sourceBitmap = new SDBitmap(stream);
PixelTypeInfo pixelType = new(SDImage.GetPixelFormatSize(sourceBitmap.PixelFormat));
return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata());
}
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken)
public override Image<TPixel> DecodeSpecialized<TPixel>(SystemDrawingReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
using var sourceBitmap = new SDBitmap(stream);
if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb)
{
return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(sourceBitmap);
}
using var convertedBitmap = new SDBitmap(
sourceBitmap.Width,
sourceBitmap.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (var g = System.Drawing.Graphics.FromImage(convertedBitmap))
{
var pixelType = new PixelTypeInfo(System.Drawing.Image.GetPixelFormatSize(sourceBitmap.PixelFormat));
return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata());
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.DrawImage(sourceBitmap, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
}
return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap<TPixel>(convertedBitmap);
}
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
public override Image DecodeSpecialized(SystemDrawingReferenceDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<Rgba32>(options, 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
{
private static readonly Lazy<Configuration> ConfigurationLazy = new Lazy<Configuration>(CreateDefaultConfiguration);
private static readonly Lazy<Configuration> ConfigurationLazy = new(CreateDefaultConfiguration);
internal static Configuration Configuration => ConfigurationLazy.Value;

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

@ -327,7 +327,8 @@ namespace SixLabors.ImageSharp.Tests
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>(
@ -355,7 +356,8 @@ namespace SixLabors.ImageSharp.Tests
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);
}
@ -383,13 +385,11 @@ namespace SixLabors.ImageSharp.Tests
bool appendPixelTypeToFileName = true)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(
using Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(
testOutputDetails,
extension,
appendPixelTypeToFileName))
{
return comparer.CompareImages(referenceImage, image);
}
appendPixelTypeToFileName);
return comparer.CompareImages(referenceImage, image);
}
public static Image<TPixel> ComparePixelBufferTo<TPixel>(
@ -534,9 +534,10 @@ namespace SixLabors.ImageSharp.Tests
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);
}
@ -559,9 +560,10 @@ namespace SixLabors.ImageSharp.Tests
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);
}
@ -584,23 +586,21 @@ namespace SixLabors.ImageSharp.Tests
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
operation(image);
image.DebugSave(
provider,
testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
image.CompareToReferenceOutput(
comparer,
provider,
testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
}
using Image<TPixel> image = provider.GetImage();
operation(image);
image.DebugSave(
provider,
testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
image.CompareToReferenceOutput(
comparer,
provider,
testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
}
/// <summary>
@ -682,11 +682,11 @@ namespace SixLabors.ImageSharp.Tests
referenceDecoder ??= TestEnvironment.GetReferenceDecoder(actualOutputFile);
using (var encodedImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder))
{
ImageComparer comparer = customComparer ?? ImageComparer.Exact;
comparer.VerifySimilarity(encodedImage, image);
}
using FileStream stream = File.OpenRead(actualOutputFile);
using Image<TPixel> encodedImage = referenceDecoder.Decode<TPixel>(DecoderOptions.Default, stream, default);
ImageComparer comparer = customComparer ?? ImageComparer.Exact;
comparer.VerifySimilarity(encodedImage, image);
}
internal static AllocatorBufferCapacityConfigurator LimitAllocatorBufferCapacity<TPixel>(

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

@ -1,17 +1,17 @@
// Copyright (c) Six Labors.
// 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.Abstractions;
// ReSharper disable InconsistentNaming
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 MagickReferenceCodecTests(ITestOutputHelper output) => this.Output = output;
@ -39,17 +39,19 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
ImageComparer comparer = ImageComparer.Exact;
using (var mImage = Image.Load<TPixel>(path, magickDecoder))
using (var sdImage = Image.Load<TPixel>(path, sdDecoder))
{
ImageSimilarityReport<TPixel, TPixel> report = comparer.CompareImagesOrFrames(mImage, sdImage);
using FileStream mStream = File.OpenRead(path);
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);
mImage.DebugSave(dummyProvider);
mImage.DebugSave(dummyProvider);
if (TestEnvironment.IsWindows)
{
Assert.True(report.IsEmpty);
}
if (TestEnvironment.IsWindows)
{
Assert.True(report.IsEmpty);
}
}
@ -69,18 +71,17 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
// 1020 == 4 * 255 (Equivalent to manhattan distance of 1+1+1+1=4 in Rgba32 space)
var comparer = ImageComparer.TolerantPercentage(1, 1020);
using FileStream mStream = File.OpenRead(path);
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);
using (var mImage = Image.Load<TPixel>(path, magickDecoder))
using (var sdImage = Image.Load<TPixel>(path, sdDecoder))
{
ImageSimilarityReport<TPixel, TPixel> report = comparer.CompareImagesOrFrames(mImage, sdImage);
mImage.DebugSave(dummyProvider);
mImage.DebugSave(dummyProvider);
if (TestEnvironment.IsWindows)
{
Assert.True(report.IsEmpty);
}
if (TestEnvironment.IsWindows)
{
Assert.True(report.IsEmpty);
}
}
}

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

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

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

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