Browse Source

Refactor Load APIs

pull/2317/head
James Jackson-South 3 years ago
parent
commit
f421701333
  1. 18
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  2. 17
      src/ImageSharp/Formats/ImageDecoder.cs
  3. 64
      src/ImageSharp/Formats/ImageExtensions.Save.cs
  4. 51
      src/ImageSharp/Formats/ImageFormatManager.cs
  5. 91
      src/ImageSharp/Image.Decode.cs
  6. 166
      src/ImageSharp/Image.FromBytes.cs
  7. 255
      src/ImageSharp/Image.FromFile.cs
  8. 291
      src/ImageSharp/Image.FromStream.cs
  9. 2
      src/ImageSharp/Image.LoadPixelData.cs
  10. 4
      src/ImageSharp/ImageExtensions.cs
  11. 72
      tests/ImageSharp.Tests/Formats/Bmp/ImageExtensionsTest.cs
  12. 9
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
  13. 72
      tests/ImageSharp.Tests/Formats/Gif/ImageExtensionsTest.cs
  14. 8
      tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
  15. 72
      tests/ImageSharp.Tests/Formats/Jpg/ImageExtensionsTest.cs
  16. 42
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
  17. 10
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  18. 72
      tests/ImageSharp.Tests/Formats/Pbm/ImageExtensionsTest.cs
  19. 72
      tests/ImageSharp.Tests/Formats/Png/ImageExtensionsTest.cs
  20. 72
      tests/ImageSharp.Tests/Formats/Tga/ImageExtensionsTest.cs
  21. 2
      tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs
  22. 72
      tests/ImageSharp.Tests/Formats/Tiff/ImageExtensionsTest.cs
  23. 72
      tests/ImageSharp.Tests/Formats/WebP/ImageExtensionsTests.cs
  24. 12
      tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs
  25. 26
      tests/ImageSharp.Tests/Image/ImageTests.Identify.cs
  26. 38
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs
  27. 13
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs
  28. 36
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs
  29. 13
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs
  30. 54
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs
  31. 4
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs
  32. 29
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs
  33. 34
      tests/ImageSharp.Tests/Image/ImageTests.Save.cs
  34. 88
      tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
  35. 72
      tests/ImageSharp.Tests/Image/ImageTests.cs
  36. 2
      tests/ImageSharp.Tests/Image/LargeImageIntegrationTests.cs
  37. 412
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
  38. 4
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs

18
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

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

17
src/ImageSharp/Formats/ImageDecoder.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats;
@ -150,7 +149,7 @@ public abstract class ImageDecoder : IImageDecoder
{
ResizeOptions resizeOptions = new()
{
Size = options.TargetSize.Value,
Size = options.TargetSize!.Value,
Sampler = options.Sampler,
Mode = ResizeMode.Max
};
@ -290,8 +289,18 @@ public abstract class ImageDecoder : IImageDecoder
}
internal void SetDecoderFormat(Configuration configuration, Image image)
=> image.Metadata.DecodedImageFormat = configuration.ImageFormatsManager.FindFormatByDecoder(this);
{
if (configuration.ImageFormatsManager.TryFindFormatByDecoder(this, out IImageFormat? format))
{
image.Metadata.DecodedImageFormat = format;
}
}
internal void SetDecoderFormat(Configuration configuration, ImageInfo info)
=> info.Metadata.DecodedImageFormat = configuration.ImageFormatsManager.FindFormatByDecoder(this);
{
if (configuration.ImageFormatsManager.TryFindFormatByDecoder(this, out IImageFormat? format))
{
info.Metadata.DecodedImageFormat = format;
}
}
}

64
src/ImageSharp/Formats/ImageExtensions.Save.cs

@ -58,7 +58,7 @@ public static partial class ImageExtensions
public static void SaveAsBmp(this Image source, string path, BmpEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Bmp format.
@ -72,7 +72,7 @@ public static partial class ImageExtensions
public static Task SaveAsBmpAsync(this Image source, string path, BmpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance),
cancellationToken);
/// <summary>
@ -105,7 +105,7 @@ public static partial class ImageExtensions
public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Bmp format.
@ -119,7 +119,7 @@ public static partial class ImageExtensions
public static Task SaveAsBmpAsync(this Image source, Stream stream, BmpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance),
cancellationToken);
/// <summary>
@ -160,7 +160,7 @@ public static partial class ImageExtensions
public static void SaveAsGif(this Image source, string path, GifEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Gif format.
@ -174,7 +174,7 @@ public static partial class ImageExtensions
public static Task SaveAsGifAsync(this Image source, string path, GifEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance),
cancellationToken);
/// <summary>
@ -207,7 +207,7 @@ public static partial class ImageExtensions
public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Gif format.
@ -221,7 +221,7 @@ public static partial class ImageExtensions
public static Task SaveAsGifAsync(this Image source, Stream stream, GifEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance),
cancellationToken);
/// <summary>
@ -262,7 +262,7 @@ public static partial class ImageExtensions
public static void SaveAsJpeg(this Image source, string path, JpegEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Jpeg format.
@ -276,7 +276,7 @@ public static partial class ImageExtensions
public static Task SaveAsJpegAsync(this Image source, string path, JpegEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance),
cancellationToken);
/// <summary>
@ -309,7 +309,7 @@ public static partial class ImageExtensions
public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Jpeg format.
@ -323,7 +323,7 @@ public static partial class ImageExtensions
public static Task SaveAsJpegAsync(this Image source, Stream stream, JpegEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance),
cancellationToken);
/// <summary>
@ -364,7 +364,7 @@ public static partial class ImageExtensions
public static void SaveAsPbm(this Image source, string path, PbmEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Pbm format.
@ -378,7 +378,7 @@ public static partial class ImageExtensions
public static Task SaveAsPbmAsync(this Image source, string path, PbmEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance),
cancellationToken);
/// <summary>
@ -411,7 +411,7 @@ public static partial class ImageExtensions
public static void SaveAsPbm(this Image source, Stream stream, PbmEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Pbm format.
@ -425,7 +425,7 @@ public static partial class ImageExtensions
public static Task SaveAsPbmAsync(this Image source, Stream stream, PbmEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance),
cancellationToken);
/// <summary>
@ -466,7 +466,7 @@ public static partial class ImageExtensions
public static void SaveAsPng(this Image source, string path, PngEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Png format.
@ -480,7 +480,7 @@ public static partial class ImageExtensions
public static Task SaveAsPngAsync(this Image source, string path, PngEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance),
cancellationToken);
/// <summary>
@ -513,7 +513,7 @@ public static partial class ImageExtensions
public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Png format.
@ -527,7 +527,7 @@ public static partial class ImageExtensions
public static Task SaveAsPngAsync(this Image source, Stream stream, PngEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance),
cancellationToken);
/// <summary>
@ -568,7 +568,7 @@ public static partial class ImageExtensions
public static void SaveAsTga(this Image source, string path, TgaEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Tga format.
@ -582,7 +582,7 @@ public static partial class ImageExtensions
public static Task SaveAsTgaAsync(this Image source, string path, TgaEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance),
cancellationToken);
/// <summary>
@ -615,7 +615,7 @@ public static partial class ImageExtensions
public static void SaveAsTga(this Image source, Stream stream, TgaEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Tga format.
@ -629,7 +629,7 @@ public static partial class ImageExtensions
public static Task SaveAsTgaAsync(this Image source, Stream stream, TgaEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance),
cancellationToken);
/// <summary>
@ -670,7 +670,7 @@ public static partial class ImageExtensions
public static void SaveAsWebp(this Image source, string path, WebpEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Webp format.
@ -684,7 +684,7 @@ public static partial class ImageExtensions
public static Task SaveAsWebpAsync(this Image source, string path, WebpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance),
cancellationToken);
/// <summary>
@ -717,7 +717,7 @@ public static partial class ImageExtensions
public static void SaveAsWebp(this Image source, Stream stream, WebpEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Webp format.
@ -731,7 +731,7 @@ public static partial class ImageExtensions
public static Task SaveAsWebpAsync(this Image source, Stream stream, WebpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance),
cancellationToken);
/// <summary>
@ -772,7 +772,7 @@ public static partial class ImageExtensions
public static void SaveAsTiff(this Image source, string path, TiffEncoder encoder) =>
source.Save(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Tiff format.
@ -786,7 +786,7 @@ public static partial class ImageExtensions
public static Task SaveAsTiffAsync(this Image source, string path, TiffEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance),
cancellationToken);
/// <summary>
@ -819,7 +819,7 @@ public static partial class ImageExtensions
public static void SaveAsTiff(this Image source, Stream stream, TiffEncoder encoder)
=> source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance));
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance));
/// <summary>
/// Saves the image to the given stream with the Tiff format.
@ -833,7 +833,7 @@ public static partial class ImageExtensions
public static Task SaveAsTiffAsync(this Image source, Stream stream, TiffEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance),
encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance),
cancellationToken);
}

51
src/ImageSharp/Formats/ImageFormatManager.cs

@ -3,6 +3,8 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
namespace SixLabors.ImageSharp.Formats;
@ -129,8 +131,11 @@ public class ImageFormatManager
return format is not null;
}
internal IImageFormat? FindFormatByDecoder(IImageDecoder decoder)
=> this.mimeTypeDecoders.FirstOrDefault(x => x.Value.GetType() == decoder.GetType()).Key;
internal bool TryFindFormatByDecoder(IImageDecoder decoder, [NotNullWhen(true)] out IImageFormat? format)
{
format = this.mimeTypeDecoders.FirstOrDefault(x => x.Value.GetType() == decoder.GetType()).Key;
return format is not null;
}
/// <summary>
/// Sets a specific image encoder as the encoder for a specific image format.
@ -178,32 +183,54 @@ public class ImageFormatManager
/// For the specified mime type find the decoder.
/// </summary>
/// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
public IImageDecoder? FindDecoder(IImageFormat format)
/// <returns>The <see cref="IImageDecoder"/>.</returns>
/// <exception cref="UnknownImageFormatException">The format is not registered.</exception>
public IImageDecoder GetDecoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder? decoder)
? decoder
: null;
if (!this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder? decoder))
{
ThrowInvalidDecoder(this);
}
return decoder;
}
/// <summary>
/// For the specified mime type find the encoder.
/// </summary>
/// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
public IImageEncoder? FindEncoder(IImageFormat format)
/// <returns>The <see cref="IImageEncoder"/>.</returns>
/// <exception cref="UnknownImageFormatException">The format is not registered.</exception>
public IImageEncoder GetEncoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder? encoder)
? encoder
: null;
if (!this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder? encoder))
{
ThrowInvalidDecoder(this);
}
return encoder;
}
/// <summary>
/// Sets the max header size.
/// </summary>
private void SetMaxHeaderSize() => this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize);
[DoesNotReturn]
internal static void ThrowInvalidDecoder(ImageFormatManager manager)
{
StringBuilder sb = new();
sb = sb.AppendLine("Image cannot be loaded. Available decoders:");
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in manager.ImageDecoders)
{
sb = sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
throw new UnknownImageFormatException(sb.ToString());
}
}

91
src/ImageSharp/Image.Decode.cs

@ -44,14 +44,15 @@ public abstract partial class Image
/// <param name="configuration">The general configuration.</param>
/// <param name="stream">The image stream to read the header from.</param>
/// <returns>The mime type or null if none found.</returns>
private static IImageFormat? InternalDetectFormat(Configuration configuration, Stream stream)
/// <exception cref="UnknownImageFormatException">The input format is not recognized.</exception>
private static IImageFormat InternalDetectFormat(Configuration configuration, Stream stream)
{
// We take a minimum of the stream length vs the max header size and always check below
// to ensure that only formats that headers fit within the given buffer length are tested.
int headerSize = (int)Math.Min(configuration.MaxHeaderSize, stream.Length);
if (headerSize <= 0)
{
return null;
ImageFormatManager.ThrowInvalidDecoder(configuration.ImageFormatsManager);
}
// Header sizes are so small, that headersBuffer will be always stackalloc-ed in practice,
@ -85,7 +86,12 @@ public abstract partial class Image
}
}
return format;
if (format is null)
{
ImageFormatManager.ThrowInvalidDecoder(configuration.ImageFormatsManager);
}
return format!;
}
/// <summary>
@ -93,13 +99,11 @@ public abstract partial class Image
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The image stream to read the header from.</param>
/// <returns>The <see cref="IImageDecoder"/> or <see langword="null"/>.</returns>
private static IImageDecoder? DiscoverDecoder(DecoderOptions options, Stream stream)
/// <returns>The <see cref="IImageDecoder"/>.</returns>
private static IImageDecoder DiscoverDecoder(DecoderOptions options, Stream stream)
{
IImageFormat? format = InternalDetectFormat(options.Configuration, stream);
return format is not null
? options.Configuration.ImageFormatsManager.FindDecoder(format)
: null;
IImageFormat format = InternalDetectFormat(options.Configuration, stream);
return options.Configuration.ImageFormatsManager.GetDecoder(format);
}
/// <summary>
@ -111,56 +115,36 @@ public abstract partial class Image
/// <returns>
/// A new <see cref="Image{TPixel}"/>.
/// </returns>
private static Image<TPixel>? Decode<TPixel>(DecoderOptions options, Stream stream)
private static Image<TPixel> Decode<TPixel>(DecoderOptions options, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
IImageDecoder? decoder = DiscoverDecoder(options, stream);
if (decoder is null)
{
return null;
}
IImageDecoder decoder = DiscoverDecoder(options, stream);
return decoder.Decode<TPixel>(options, stream);
}
private static async Task<Image<TPixel>?> DecodeAsync<TPixel>(
private static Task<Image<TPixel>> DecodeAsync<TPixel>(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
IImageDecoder? decoder = DiscoverDecoder(options, stream);
if (decoder is null)
{
return null;
}
return await decoder.DecodeAsync<TPixel>(options, stream, cancellationToken).ConfigureAwait(false);
IImageDecoder decoder = DiscoverDecoder(options, stream);
return decoder.DecodeAsync<TPixel>(options, stream, cancellationToken);
}
private static Image? Decode(DecoderOptions options, Stream stream)
private static Image Decode(DecoderOptions options, Stream stream)
{
IImageDecoder? decoder = DiscoverDecoder(options, stream);
if (decoder is null)
{
return null;
}
IImageDecoder decoder = DiscoverDecoder(options, stream);
return decoder.Decode(options, stream);
}
private static async Task<Image?> DecodeAsync(
private static Task<Image> DecodeAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken)
{
IImageDecoder? decoder = DiscoverDecoder(options, stream);
if (decoder is null)
{
return null;
}
return await decoder.DecodeAsync(options, stream, cancellationToken).ConfigureAwait(false);
IImageDecoder decoder = DiscoverDecoder(options, stream);
return decoder.DecodeAsync(options, stream, cancellationToken);
}
/// <summary>
@ -168,17 +152,10 @@ public abstract partial class Image
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream.</param>
/// <returns>
/// The <see cref="ImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
private static ImageInfo? InternalIdentify(DecoderOptions options, Stream stream)
/// <returns>The <see cref="ImageInfo"/>.</returns>
private static ImageInfo InternalIdentify(DecoderOptions options, Stream stream)
{
IImageDecoder? decoder = DiscoverDecoder(options, stream);
if (decoder is null)
{
return null;
}
IImageDecoder decoder = DiscoverDecoder(options, stream);
return decoder.Identify(options, stream);
}
@ -188,21 +165,13 @@ public abstract partial class Image
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>
/// The <see cref="ImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
private static async Task<ImageInfo?> InternalIdentifyAsync(
/// <returns>The <see cref="ImageInfo"/>.</returns>
private static Task<ImageInfo> InternalIdentifyAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken)
{
IImageDecoder? decoder = DiscoverDecoder(options, stream);
if (decoder is null)
{
return null;
}
return await decoder.IdentifyAsync(options, stream, cancellationToken).ConfigureAwait(false);
IImageDecoder decoder = DiscoverDecoder(options, stream);
return decoder.IdentifyAsync(options, stream, cancellationToken);
}
}

166
src/ImageSharp/Image.FromBytes.cs

@ -15,21 +15,21 @@ public abstract partial class Image
/// <summary>
/// By reading the header on the provided byte span this calculates the images format.
/// </summary>
/// <param name="data">The byte span containing encoded image data to read the header from.</param>
/// <param name="buffer">The byte span containing encoded image data to read the header from.</param>
/// <param name="format">The format or null if none found.</param>
/// <returns>returns true when format was detected otherwise false.</returns>
public static bool TryDetectFormat(ReadOnlySpan<byte> data, [NotNullWhen(true)] out IImageFormat? format)
=> TryDetectFormat(DecoderOptions.Default, data, out format);
public static bool TryDetectFormat(ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out IImageFormat? format)
=> TryDetectFormat(DecoderOptions.Default, buffer, out format);
/// <summary>
/// By reading the header on the provided byte span this calculates the images format.
/// </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="buffer">The byte span containing encoded image data to read the header from.</param>
/// <param name="format">The mime type or null if none found.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <returns>returns true when format was detected otherwise false.</returns>
public static bool TryDetectFormat(DecoderOptions options, ReadOnlySpan<byte> data, [NotNullWhen(true)] out IImageFormat? format)
public static bool TryDetectFormat(DecoderOptions options, ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out IImageFormat? format)
{
Guard.NotNull(options, nameof(options.Configuration));
@ -43,7 +43,7 @@ public abstract partial class Image
foreach (IImageFormatDetector detector in configuration.ImageFormatsManager.FormatDetectors)
{
if (detector.TryDetectFormat(data, out format))
if (detector.TryDetectFormat(buffer, out format))
{
return true;
}
@ -57,7 +57,7 @@ public abstract partial class Image
/// Reads the raw image information from the specified stream without fully decoding it.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="buffer">The byte array containing encoded image data to read the header from.</param>
/// <param name="info">
/// When this method returns, contains the raw image information;
/// otherwise, the default value for the type of the <paramref name="info"/> parameter.
@ -66,15 +66,15 @@ public abstract partial class Image
/// <returns><see langword="true"/> if the information can be read; otherwise, <see langword="false"/></returns>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
public static bool TryIdentify(ReadOnlySpan<byte> data, [NotNullWhen(true)] out ImageInfo? info)
=> TryIdentify(DecoderOptions.Default, data, out info);
public static bool TryIdentify(ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out ImageInfo? info)
=> TryIdentify(DecoderOptions.Default, buffer, out info);
/// <summary>
/// Reads the raw image information from the specified span of bytes without fully decoding it.
/// A return value indicates whether the operation succeeded.
/// </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="buffer">The byte span containing encoded image data to read the header from.</param>
/// <param name="info">
/// When this method returns, contains the raw image information;
/// otherwise, the default value for the type of the <paramref name="info"/> parameter.
@ -84,141 +84,79 @@ public abstract partial class Image
/// <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>
public static unsafe bool TryIdentify(DecoderOptions options, ReadOnlySpan<byte> data, [NotNullWhen(true)] out ImageInfo? info)
public static unsafe bool TryIdentify(DecoderOptions options, ReadOnlySpan<byte> buffer, [NotNullWhen(true)] out ImageInfo? info)
{
fixed (byte* ptr = data)
fixed (byte* ptr = buffer)
{
using UnmanagedMemoryStream stream = new(ptr, data.Length);
using UnmanagedMemoryStream stream = new(ptr, buffer.Length);
return TryIdentify(options, stream, out info);
}
}
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// Creates a new instance of the <see cref="Image"/> class from the given byte span.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="data">The byte span containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(DecoderOptions.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(ReadOnlySpan<byte> data, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(DecoderOptions.Default, data, out format);
/// <param name="buffer">The byte span containing encoded image data.</param>
/// <returns><see cref="Image"/>.</returns>
/// <exception cref="NotSupportedException">The image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(ReadOnlySpan<byte> buffer)
=> Load(DecoderOptions.Default, buffer);
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// Creates a new instance of the <see cref="Image"/> class from the given byte span.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="data">The byte span containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="buffer">The byte span containing encoded image data.</param>
/// <returns><see cref="Image"/>.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(DecoderOptions options, ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
/// <exception cref="NotSupportedException">The image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static unsafe Image Load(DecoderOptions options, ReadOnlySpan<byte> buffer)
{
fixed (byte* ptr = data)
fixed (byte* ptr = buffer)
{
using UnmanagedMemoryStream stream = new(ptr, data.Length);
return Load<TPixel>(options, stream);
using UnmanagedMemoryStream stream = new(ptr, buffer.Length);
return Load(options, stream);
}
}
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given byte span.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(
DecoderOptions options,
ReadOnlySpan<byte> data,
out IImageFormat format)
/// <param name="data">The byte span containing encoded image data.</param>
/// <returns><see cref="Image{TPixel}"/>.</returns>
/// <exception cref="NotSupportedException">The image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image<TPixel> Load<TPixel>(ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
{
fixed (byte* ptr = data)
{
using UnmanagedMemoryStream stream = new(ptr, data.Length);
return Load<TPixel>(options, stream, out format);
}
}
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(ReadOnlySpan<byte> data)
=> Load(DecoderOptions.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The detected format.</param>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(ReadOnlySpan<byte> data, out IImageFormat format)
=> Load(DecoderOptions.Default, data, out format);
/// <summary>
/// Decodes a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(DecoderOptions options, ReadOnlySpan<byte> data)
=> Load(options, data, out _);
=> Load<TPixel>(DecoderOptions.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given byte span.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="options">The general decoder options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>>
/// <param name="data">The byte span containing encoded image data.</param>
/// <returns><see cref="Image{TPixel}"/>.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static unsafe Image Load(
DecoderOptions options,
ReadOnlySpan<byte> data,
out IImageFormat format)
/// <exception cref="NotSupportedException">The image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static unsafe Image<TPixel> Load<TPixel>(DecoderOptions options, ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
{
fixed (byte* ptr = data)
{
using UnmanagedMemoryStream stream = new(ptr, data.Length);
return Load(options, stream, out format);
return Load<TPixel>(options, stream);
}
}
}

255
src/ImageSharp/Image.FromFile.cs

@ -16,22 +16,22 @@ public abstract partial class Image
/// Detects the encoded image format type from the specified file.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="format">
/// When this method returns, contains the format that matches the given file;
/// otherwise, the default value for the type of the <paramref name="format"/> parameter.
/// This parameter is passed uninitialized.
/// </param>
/// <returns><see langword="true"/> if a match is found; otherwise, <see langword="false"/></returns>
public static bool TryDetectFormat(string filePath, [NotNullWhen(true)] out IImageFormat? format)
=> TryDetectFormat(DecoderOptions.Default, filePath, out format);
public static bool TryDetectFormat(string path, [NotNullWhen(true)] out IImageFormat? format)
=> TryDetectFormat(DecoderOptions.Default, path, out format);
/// <summary>
/// Detects the encoded image format type from the specified file.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="format">
/// When this method returns, contains the format that matches the given file;
/// otherwise, the default value for the type of the <paramref name="format"/> parameter.
@ -39,11 +39,11 @@ public abstract partial class Image
/// </param>
/// <returns><see langword="true"/> if a match is found; otherwise, <see langword="false"/></returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
public static bool TryDetectFormat(DecoderOptions options, string filePath, [NotNullWhen(true)] out IImageFormat? format)
public static bool TryDetectFormat(DecoderOptions options, string path, [NotNullWhen(true)] out IImageFormat? format)
{
Guard.NotNull(options, nameof(options));
using Stream file = options.Configuration.FileSystem.OpenRead(filePath);
using Stream file = options.Configuration.FileSystem.OpenRead(path);
return TryDetectFormat(options, file, out format);
}
@ -51,31 +51,31 @@ public abstract partial class Image
/// Detects the encoded image format type from the specified file.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task{Attempt}"/> representing the asynchronous operation.</returns>
public static Task<Attempt<IImageFormat>> TryDetectFormatAsync(
string filePath,
string path,
CancellationToken cancellationToken = default)
=> TryDetectFormatAsync(DecoderOptions.Default, filePath, cancellationToken);
=> TryDetectFormatAsync(DecoderOptions.Default, path, cancellationToken);
/// <summary>
/// Detects the encoded image format type from the specified file.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <returns>A <see cref="Task{Attempt}"/> representing the asynchronous operation.</returns>
public static async Task<Attempt<IImageFormat>> TryDetectFormatAsync(
DecoderOptions options,
string filePath,
string path,
CancellationToken cancellationToken = default)
{
Guard.NotNull(options, nameof(options));
using Stream stream = options.Configuration.FileSystem.OpenRead(filePath);
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
return await TryDetectFormatAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
@ -83,22 +83,22 @@ public abstract partial class Image
/// Reads the raw image information from the specified file path without fully decoding it.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="info">
/// When this method returns, contains the raw image information;
/// otherwise, the default value for the type of the <paramref name="info"/> parameter.
/// This parameter is passed uninitialized.
/// </param>
/// <returns><see langword="true"/> if the information can be read; otherwise, <see langword="false"/></returns>
public static bool TryIdentify(string filePath, [NotNullWhen(true)] out ImageInfo? info)
=> TryIdentify(DecoderOptions.Default, filePath, out info);
public static bool TryIdentify(string path, [NotNullWhen(true)] out ImageInfo? info)
=> TryIdentify(DecoderOptions.Default, path, out info);
/// <summary>
/// Reads the raw image information from the specified file path without fully decoding it.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="info">
/// When this method returns, contains the raw image information;
/// otherwise, the default value for the type of the <paramref name="info"/> parameter.
@ -106,11 +106,11 @@ public abstract partial class Image
/// </param>
/// <returns><see langword="true"/> if the information can be read; otherwise, <see langword="false"/></returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
public static bool TryIdentify(DecoderOptions options, string filePath, [NotNullWhen(true)] out ImageInfo? info)
public static bool TryIdentify(DecoderOptions options, string path, [NotNullWhen(true)] out ImageInfo? info)
{
Guard.NotNull(options, nameof(options));
using Stream stream = options.Configuration.FileSystem.OpenRead(filePath);
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
return TryIdentify(options, stream, out info);
}
@ -118,197 +118,134 @@ public abstract partial class Image
/// Reads the raw image information from the specified stream without fully decoding it.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <returns>
/// The <see cref="Task{Attempt}"/> representing the asynchronous operation.
/// </returns>
public static Task<Attempt<ImageInfo>> TryIdentifyAsync(
string filePath,
string path,
CancellationToken cancellationToken = default)
=> TryIdentifyAsync(DecoderOptions.Default, filePath, cancellationToken);
=> TryIdentifyAsync(DecoderOptions.Default, path, cancellationToken);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// A return value indicates whether the operation succeeded.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="path">The image file to open and to read the header from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <returns>
/// The <see cref="Task{Attempt}"/> representing the asynchronous operation.
/// </returns>
public static async Task<Attempt<ImageInfo>> TryIdentifyAsync(
DecoderOptions options,
string filePath,
string path,
CancellationToken cancellationToken = default)
{
Guard.NotNull(options, nameof(options));
using Stream stream = options.Configuration.FileSystem.OpenRead(filePath);
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
return await TryIdentifyAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// Creates a new instance of the <see cref="Image"/> class from the given file path.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>The <see cref="Image"/>.</returns>
/// <returns><see cref="Image"/>.</returns>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image Load(string path)
=> Load(DecoderOptions.Default, path);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>A new <see cref="Image{Rgba32}"/>.</returns>
public static Image Load(string path, out IImageFormat format)
=> Load(DecoderOptions.Default, path, out format);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// Creates a new instance of the <see cref="Image"/> class from the given file path.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="path">The file path to the image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns><see cref="Image"/>.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image Load(DecoderOptions options, string path)
=> Load(options, path, out _);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static async Task<Image> LoadAsync(
DecoderOptions options,
string path,
CancellationToken cancellationToken = default)
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(path, nameof(path));
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
(Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken)
.ConfigureAwait(false);
return img;
return Load(options, stream);
}
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// Creates a new instance of the <see cref="Image"/> class from the given file path.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Task<Image> LoadAsync(string path, CancellationToken cancellationToken = default)
=> LoadAsync(DecoderOptions.Default, path, cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static Task<Image<TPixel>> LoadAsync<TPixel>(string path, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
=> LoadAsync<TPixel>(DecoderOptions.Default, path, cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// Creates a new instance of the <see cref="Image"/> class from the given file path.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static async Task<Image<TPixel>> LoadAsync<TPixel>(
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static async Task<Image> LoadAsync(
DecoderOptions options,
string path,
CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(options, nameof(options));
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
(Image<TPixel> img, _) =
await LoadWithFormatAsync<TPixel>(options, stream, cancellationToken).ConfigureAwait(false);
return img;
return await LoadAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given file path.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="path">The file path to the image.</param>
/// <returns><see cref="Image{TPixel}"/>.</returns>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image<TPixel> Load<TPixel>(string path)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(DecoderOptions.Default, path);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given file path.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(string path, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(DecoderOptions.Default, path, out format);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="path">The file path to the image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns><see cref="Image{TPixel}"/>.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image<TPixel> Load<TPixel>(DecoderOptions options, string path)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -320,47 +257,43 @@ public abstract partial class Image
}
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given file path.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(DecoderOptions options, string path, out IImageFormat format)
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Task<Image<TPixel>> LoadAsync<TPixel>(string path, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(path, nameof(path));
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
return Load<TPixel>(options, stream, out format);
}
=> LoadAsync<TPixel>(DecoderOptions.Default, path, cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// The pixel type is selected by the decoder.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given file path.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="options">The general decoder options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="NotSupportedException">Image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image Load(DecoderOptions options, string path, out IImageFormat format)
/// <exception cref="NotSupportedException">The file stream is not readable or the image format is not supported.</exception>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static async Task<Image<TPixel>> LoadAsync<TPixel>(
DecoderOptions options,
string path,
CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(path, nameof(path));
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
return Load(options, stream, out format);
return await LoadAsync<TPixel>(options, stream, cancellationToken).ConfigureAwait(false);
}
}

291
src/ImageSharp/Image.FromStream.cs

@ -2,8 +2,6 @@
// Licensed under the Six Labors Split License.
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats;
@ -136,7 +134,6 @@ public abstract partial class Image
/// </summary>
/// <param name="stream">The image stream to read the information from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
@ -177,296 +174,130 @@ public abstract partial class Image
}
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Stream stream, out IImageFormat format)
=> Load(DecoderOptions.Default, stream, out format);
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// Creates a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns><see cref="Image"/>.</returns>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default)
=> LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken);
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image Load(Stream stream)
=> Load(DecoderOptions.Default, stream);
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// Creates a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <returns><see cref="Image"/>.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Stream stream) => Load(DecoderOptions.Default, stream);
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image Load(DecoderOptions options, Stream stream)
=> WithSeekableStream(options, stream, s => Decode(options, s));
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// Creates a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Task<Image> LoadAsync(Stream stream, CancellationToken cancellationToken = default)
=> LoadAsync(DecoderOptions.Default, stream, cancellationToken);
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image Load(DecoderOptions options, Stream stream)
=> Load(options, stream, out _);
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// Creates a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is automatically determined by the decoder.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static async Task<Image> LoadAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
=> (await LoadWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false)).Image;
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Task<Image> LoadAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken = default)
=> WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync(options, s, ct), cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="stream">The stream containing image information.</param>
/// <returns><see cref="Image{TPixel}"/>.</returns>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image<TPixel> Load<TPixel>(Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(DecoderOptions.Default, stream);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
=> LoadAsync<TPixel>(DecoderOptions.Default, stream, cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(DecoderOptions.Default, stream, out format);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static Task<(Image<TPixel> Image, IImageFormat Format)> LoadWithFormatAsync<TPixel>(Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
=> LoadWithFormatAsync<TPixel>(DecoderOptions.Default, stream, cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <returns><see cref="Image{TPixel}"/>.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Image<TPixel> Load<TPixel>(DecoderOptions options, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(options, stream, out IImageFormat _);
=> WithSeekableStream(options, stream, s => Decode<TPixel>(options, s));
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static Image<TPixel> Load<TPixel>(DecoderOptions options, Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
Image<TPixel>? image = WithSeekableStream(options, stream, s => Decode<TPixel>(options, s));
if (image is null)
{
ThrowNotLoaded(options);
}
format = image.Metadata.DecodedImageFormat!;
return image;
}
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given stream.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken = default)
{
Image? image = await WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync(options, s, ct), cancellationToken)
.ConfigureAwait(false);
if (image is null)
{
ThrowNotLoaded(options);
}
return new(image, image.Metadata.DecodedImageFormat!);
}
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static async Task<(Image<TPixel> Image, IImageFormat Format)> LoadWithFormatAsync<TPixel>(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken = default)
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
{
Image<TPixel>? image = await WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync<TPixel>(options, s, ct), cancellationToken)
.ConfigureAwait(false);
if (image is null)
{
ThrowNotLoaded(options);
}
return new(image, image.Metadata.DecodedImageFormat!);
}
=> LoadAsync<TPixel>(DecoderOptions.Default, stream, cancellationToken);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// Creates a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static async Task<Image<TPixel>> LoadAsync<TPixel>(
/// <exception cref="InvalidImageContentException">The encoded image contains invalid content.</exception>
/// <exception cref="UnknownImageFormatException">The encoded image format is unknown.</exception>
public static Task<Image<TPixel>> LoadAsync<TPixel>(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>
{
(Image<TPixel> img, _) = await LoadWithFormatAsync<TPixel>(options, stream, cancellationToken)
.ConfigureAwait(false);
return img;
}
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// </summary>
/// <param name="options">The general decoder options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The options are null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable or the image format is not supported.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format)
{
Image? image = WithSeekableStream(options, stream, s => Decode(options, s));
if (image is null)
{
ThrowNotLoaded(options);
}
format = image.Metadata.DecodedImageFormat!;
return image;
}
=> WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync<TPixel>(options, s, ct), cancellationToken);
/// <summary>
/// Performs the given action against the stream ensuring that it is seekable.
@ -549,18 +380,4 @@ public abstract partial class Image
return await action(memoryStream, cancellationToken).ConfigureAwait(false);
}
[DoesNotReturn]
private static void ThrowNotLoaded(DecoderOptions options)
{
StringBuilder sb = new();
sb.AppendLine("Image cannot be loaded. Available decoders:");
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in options.Configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
throw new UnknownImageFormatException(sb.ToString());
}
}

2
src/ImageSharp/Image.LoadPixelData.cs

@ -72,7 +72,7 @@ public abstract partial class Image
int count = width * height;
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
var image = new Image<TPixel>(configuration, width, height);
Image<TPixel> image = new(configuration, width, height);
data = data[..count];
data.CopyTo(image.Frames.RootFrame.PixelBuffer.FastMemoryGroup);

4
src/ImageSharp/ImageExtensions.cs

@ -95,7 +95,7 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream.");
}
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.GetEncoder(format);
if (encoder is null)
{
@ -139,7 +139,7 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream.");
}
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.GetEncoder(format);
if (encoder is null)
{

72
tests/ImageSharp.Tests/Formats/Bmp/ImageExtensionsTest.cs

@ -15,15 +15,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsBmp_Path.bmp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsBmp(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
@ -32,15 +30,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsBmpAsync_Path.bmp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsBmpAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
@ -49,15 +45,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsBmp_Path_Encoder.bmp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsBmp(file, new BmpEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
@ -66,86 +60,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsBmpAsync_Path_Encoder.bmp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsBmpAsync(file, new BmpEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
public void SaveAsBmp_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsBmp(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
public async Task SaveAsBmpAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsBmpAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
public void SaveAsBmp_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsBmp(memoryStream, new BmpEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is BmpFormat);
}
[Fact]
public async Task SaveAsBmpAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsBmpAsync(memoryStream, new BmpEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/bmp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is BmpFormat);
}
}

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

@ -207,10 +207,10 @@ public class GeneralFormatTests
foreach (TestFile file in Files)
{
byte[] serialized;
using (Image image = Image.Load(file.Bytes, out IImageFormat mimeType))
using (Image image = Image.Load(file.Bytes))
using (MemoryStream memoryStream = new())
{
image.Save(memoryStream, mimeType);
image.Save(memoryStream, image.Metadata.DecodedImageFormat);
memoryStream.Flush();
serialized = memoryStream.ToArray();
}
@ -264,14 +264,13 @@ public class GeneralFormatTests
}
[Fact]
public void IdentifyReturnsNullWithInvalidStream()
public void Identify_UnknownImageFormatException_WithInvalidStream()
{
byte[] invalid = new byte[10];
using MemoryStream memoryStream = new(invalid);
Image.TryIdentify(memoryStream, out ImageInfo imageInfo);
Assert.Null(imageInfo);
Assert.Throws<UnknownImageFormatException>(() => Image.TryIdentify(invalid, out ImageInfo imageInfo));
}
private static IImageFormat GetFormat(string format)

72
tests/ImageSharp.Tests/Formats/Gif/ImageExtensionsTest.cs

@ -15,15 +15,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsGif_Path.gif");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsGif(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
@ -32,15 +30,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsGifAsync_Path.gif");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsGifAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
@ -49,15 +45,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsGif_Path_Encoder.gif");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsGif(file, new GifEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
@ -66,86 +60,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsGifAsync_Path_Encoder.gif");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsGifAsync(file, new GifEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
public void SaveAsGif_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsGif(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
public async Task SaveAsGifAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsGifAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
public void SaveAsGif_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsGif(memoryStream, new GifEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is GifFormat);
}
[Fact]
public async Task SaveAsGifAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsGifAsync(memoryStream, new GifEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/gif", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is GifFormat);
}
}

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

@ -74,12 +74,12 @@ public class ImageFormatManagerTests
{
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1);
IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
IImageEncoder found = this.FormatsManagerEmpty.GetEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder1, found);
IImageEncoder encoder2 = new Mock<IImageEncoder>().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2);
IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
IImageEncoder found2 = this.FormatsManagerEmpty.GetEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder2, found2);
Assert.NotEqual(found, found2);
}
@ -89,12 +89,12 @@ public class ImageFormatManagerTests
{
IImageDecoder decoder1 = new Mock<IImageDecoder>().Object;
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1);
IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat);
IImageDecoder found = this.FormatsManagerEmpty.GetDecoder(TestFormat.GlobalTestFormat);
Assert.Equal(decoder1, found);
IImageDecoder decoder2 = new Mock<IImageDecoder>().Object;
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2);
IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat);
IImageDecoder found2 = this.FormatsManagerEmpty.GetDecoder(TestFormat.GlobalTestFormat);
Assert.Equal(decoder2, found2);
Assert.NotEqual(found, found2);
}

72
tests/ImageSharp.Tests/Formats/Jpg/ImageExtensionsTest.cs

@ -16,15 +16,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsJpeg_Path.jpg");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsJpeg(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
@ -33,15 +31,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsJpegAsync_Path.jpg");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsJpegAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
@ -50,15 +46,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsJpeg_Path_Encoder.jpg");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsJpeg(file, new JpegEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
@ -67,86 +61,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsJpegAsync_Path_Encoder.jpg");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsJpegAsync(file, new JpegEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
public void SaveAsJpeg_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsJpeg(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
public async Task SaveAsJpegAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsJpegAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
public void SaveAsJpeg_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsJpeg(memoryStream, new JpegEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is JpegFormat);
}
[Fact]
public async Task SaveAsJpegAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsJpegAsync(memoryStream, new JpegEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/jpeg", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is JpegFormat);
}
}

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

@ -75,8 +75,8 @@ public partial class JpegDecoderTests
[MemberData(nameof(RatioFiles))]
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);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
using Image image = JpegDecoder.Instance.Decode(DecoderOptions.Default, stream);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
@ -88,8 +88,8 @@ public partial class JpegDecoderTests
[MemberData(nameof(RatioFiles))]
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);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
ImageInfo image = JpegDecoder.Instance.Identify(DecoderOptions.Default, stream);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
@ -101,8 +101,8 @@ public partial class JpegDecoderTests
[MemberData(nameof(RatioFiles))]
public async Task Identify_VerifyRatioAsync(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
ImageInfo image = await JpegDecoder.Instance.IdentifyAsync(DecoderOptions.Default, stream);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
@ -114,8 +114,8 @@ public partial class JpegDecoderTests
[MemberData(nameof(QualityFiles))]
public void Identify_VerifyQuality(string imagePath, int quality)
{
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
ImageInfo image = JpegDecoder.Instance.Identify(DecoderOptions.Default, stream);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
@ -125,8 +125,8 @@ public partial class JpegDecoderTests
[MemberData(nameof(QualityFiles))]
public void Decode_VerifyQuality(string imagePath, int quality)
{
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
using Image image = JpegDecoder.Instance.Decode(DecoderOptions.Default, stream);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
@ -136,8 +136,8 @@ public partial class JpegDecoderTests
[MemberData(nameof(QualityFiles))]
public async Task Decode_VerifyQualityAsync(string imagePath, int quality)
{
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
using Image image = await JpegDecoder.Instance.DecodeAsync(DecoderOptions.Default, stream);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(quality, meta.Quality);
@ -153,8 +153,8 @@ public partial class JpegDecoderTests
[InlineData(TestImages.Jpeg.Baseline.Jpeg411, JpegEncodingColor.YCbCrRatio411)]
public void Identify_DetectsCorrectColorType(string imagePath, JpegEncodingColor expectedColorType)
{
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
ImageInfo image = JpegDecoder.Instance.Identify(DecoderOptions.Default, stream);
JpegMetadata meta = image.Metadata.GetJpegMetadata();
Assert.Equal(expectedColorType, meta.ColorType);
@ -176,8 +176,8 @@ public partial class JpegDecoderTests
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);
TestFile testFile = TestFile.Create(imagePath);
using MemoryStream stream = new(testFile.Bytes, false);
if (useIdentify)
{
ImageInfo imageInfo = decoder.Identify(DecoderOptions.Default, stream);
@ -318,10 +318,10 @@ public partial class JpegDecoderTests
[Fact]
public void EncodedStringTags_WriteAndRead()
{
using var memoryStream = new MemoryStream();
using (var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora)))
using MemoryStream memoryStream = new();
using (Image image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora)))
{
var exif = new ExifProfile();
ExifProfile exif = new();
exif.SetValue(ExifTag.GPSDateStamp, "2022-01-06");
@ -343,7 +343,7 @@ public partial class JpegDecoderTests
}
memoryStream.Seek(0, SeekOrigin.Begin);
using (var image = Image.Load(memoryStream))
using (Image image = Image.Load(memoryStream))
{
ExifProfile exif = image.Metadata.ExifProfile;
VerifyEncodedStrings(exif);
@ -353,7 +353,7 @@ public partial class JpegDecoderTests
[Fact]
public void EncodedStringTags_Read()
{
using var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora_EncodedStrings));
using Image image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora_EncodedStrings));
ExifProfile exif = image.Metadata.ExifProfile;
VerifyEncodedStrings(exif);
}

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

@ -35,7 +35,7 @@ public partial class JpegDecoderTests
if (!CustomToleranceValues.TryGetValue(file, out float tolerance))
{
bool baseline = file.IndexOf("baseline", StringComparison.OrdinalIgnoreCase) >= 0;
bool baseline = file.Contains("baseline", StringComparison.OrdinalIgnoreCase);
tolerance = baseline ? BaselineTolerance : ProgressiveTolerance;
}
@ -68,9 +68,9 @@ public partial class JpegDecoderTests
{
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(options);
using MemoryStream ms = new(bytes);
using BufferedReadStream bufferedStream = new(Configuration.Default, ms);
using JpegDecoderCore decoder = new(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
@ -85,7 +85,7 @@ public partial class JpegDecoderTests
public void Decode_NonGeneric_CreatesRgb24Image()
{
string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var image = Image.Load(file);
using Image image = Image.Load(file);
Assert.IsType<Image<Rgb24>>(image);
}

72
tests/ImageSharp.Tests/Formats/Pbm/ImageExtensionsTest.cs

@ -15,15 +15,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsPbm_Path.pbm");
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
image.SaveAsPbm(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
@ -32,15 +30,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsPbmAsync_Path.pbm");
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
await image.SaveAsPbmAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
@ -49,15 +45,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsPbm_Path_Encoder.pbm");
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
image.SaveAsPbm(file, new PbmEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
@ -66,86 +60,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsPbmAsync_Path_Encoder.pbm");
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
await image.SaveAsPbmAsync(file, new PbmEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
public void SaveAsPbm_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
image.SaveAsPbm(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
public async Task SaveAsPbmAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
await image.SaveAsPbmAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
public void SaveAsPbm_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
image.SaveAsPbm(memoryStream, new PbmEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PbmFormat);
}
[Fact]
public async Task SaveAsPbmAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<L8>(10, 10))
using (Image<L8> image = new(10, 10))
{
await image.SaveAsPbmAsync(memoryStream, new PbmEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/x-portable-pixmap", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PbmFormat);
}
}

72
tests/ImageSharp.Tests/Formats/Png/ImageExtensionsTest.cs

@ -16,15 +16,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsPng_Path.png");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsPng(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
@ -33,15 +31,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsPngAsync_Path.png");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsPngAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
@ -50,15 +46,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsPng_Path_Encoder.png");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsPng(file, new PngEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
@ -67,86 +61,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsPngAsync_Path_Encoder.png");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsPngAsync(file, new PngEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public void SaveAsPng_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsPng(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public async Task SaveAsPngAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsPngAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public void SaveAsPng_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsPng(memoryStream, new PngEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public async Task SaveAsPngAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsPngAsync(memoryStream, new PngEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is PngFormat);
}
}

72
tests/ImageSharp.Tests/Formats/Tga/ImageExtensionsTest.cs

@ -15,15 +15,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsTga_Path.tga");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTga(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
@ -32,15 +30,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsTgaAsync_Path.tga");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTgaAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
@ -49,15 +45,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsTga_Path_Encoder.tga");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTga(file, new TgaEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
@ -66,86 +60,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsTgaAsync_Path_Encoder.tga");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTgaAsync(file, new TgaEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
public void SaveAsTga_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTga(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
public async Task SaveAsTgaAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTgaAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
public void SaveAsTga_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTga(memoryStream, new TgaEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TgaFormat);
}
[Fact]
public async Task SaveAsTgaAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTgaAsync(memoryStream, new TgaEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tga", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TgaFormat);
}
}

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

@ -26,7 +26,7 @@ public class TgaFileHeaderTests
Assert.Throws<UnknownImageFormatException>(() =>
{
using (Image.Load(DecoderOptions.Default, stream, out IImageFormat _))
using (Image.Load(DecoderOptions.Default, stream))
{
}
});

72
tests/ImageSharp.Tests/Formats/Tiff/ImageExtensionsTest.cs

@ -16,15 +16,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsTiff_Path.tiff");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTiff(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
@ -33,15 +31,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsTiffAsync_Path.tiff");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTiffAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
@ -50,15 +46,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsTiff_Path_Encoder.tiff");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTiff(file, new TiffEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
@ -67,86 +61,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsTiffAsync_Path_Encoder.tiff");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTiffAsync(file, new TiffEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
public void SaveAsTiff_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTiff(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
public async Task SaveAsTiffAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTiffAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
public void SaveAsTiff_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsTiff(memoryStream, new TiffEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TiffFormat);
}
[Fact]
public async Task SaveAsTiffAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsTiffAsync(memoryStream, new TiffEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/tiff", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is TiffFormat);
}
}

72
tests/ImageSharp.Tests/Formats/WebP/ImageExtensionsTests.cs

@ -16,15 +16,13 @@ public class ImageExtensionsTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTests));
string file = Path.Combine(dir, "SaveAsWebp_Path.webp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsWebp(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
@ -33,15 +31,13 @@ public class ImageExtensionsTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTests));
string file = Path.Combine(dir, "SaveAsWebpAsync_Path.webp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsWebpAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
@ -50,15 +46,13 @@ public class ImageExtensionsTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsWebp_Path_Encoder.webp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsWebp(file, new WebpEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
@ -67,86 +61,76 @@ public class ImageExtensionsTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsWebpAsync_Path_Encoder.webp");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsWebpAsync(file, new WebpEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
public void SaveAsWebp_Stream()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsWebp(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
public async Task SaveAsWebpAsync_StreamAsync()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsWebpAsync(memoryStream);
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
public void SaveAsWebp_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.SaveAsWebp(memoryStream, new WebpEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is WebpFormat);
}
[Fact]
public async Task SaveAsWebpAsync_Stream_Encoder()
{
using var memoryStream = new MemoryStream();
using MemoryStream memoryStream = new();
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsWebpAsync(memoryStream, new WebpEncoder());
}
memoryStream.Position = 0;
using (Image.Load(memoryStream, out IImageFormat mime))
{
Assert.Equal("image/webp", mime.DefaultMimeType);
}
Image.TryDetectFormat(memoryStream, out IImageFormat format);
Assert.True(format is WebpFormat);
}
}

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

@ -125,17 +125,14 @@ public partial class ImageTests
}
[Fact]
public void WhenNoMatchingFormatFound_ReturnsNull()
public void WhenNoMatchingFormatFound_Throws_UnknownImageFormatException()
{
DecoderOptions options = new()
{
Configuration = new()
};
bool result = Image.TryDetectFormat(options, this.DataStream, out IImageFormat type);
Assert.False(result);
Assert.Null(type);
Assert.Throws<UnknownImageFormatException>(() => Image.TryDetectFormat(options, this.DataStream, out IImageFormat type));
}
[Fact]
@ -159,15 +156,14 @@ public partial class ImageTests
}
[Fact]
public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull()
public Task WhenNoMatchingFormatFoundAsync_Throws_UnknownImageFormatException()
{
DecoderOptions options = new()
{
Configuration = new()
};
Attempt<IImageFormat> attempt = await Image.TryDetectFormatAsync(options, new AsyncStreamWrapper(this.DataStream, () => false));
Assert.Null(attempt.Value);
return Assert.ThrowsAsync<UnknownImageFormatException>(async () => await Image.TryDetectFormatAsync(options, new AsyncStreamWrapper(this.DataStream, () => false)));
}
}
}

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

@ -21,8 +21,6 @@ public partial class ImageTests
private static byte[] ActualImageBytes => TestFile.Create(TestImages.Bmp.F).Bytes;
private IImageFormat LocalImageFormat => this.localImageFormatMock.Object;
private static IImageFormat ExpectedGlobalFormat
{
get
@ -131,16 +129,15 @@ public partial class ImageTests
}
[Fact]
public void WhenNoMatchingFormatFound_ReturnsNull()
public void WhenNoMatchingFormatFound_Throws_UnknownImageFormatException()
{
DecoderOptions options = new() { Configuration = new() };
Assert.False(Image.TryIdentify(options, this.DataStream, out ImageInfo info));
Assert.Null(info);
Assert.Throws<UnknownImageFormatException>(() => Image.TryIdentify(options, this.DataStream, out ImageInfo info));
}
[Fact]
public void FromStream_ZeroLength_ReturnsNull()
public void FromStream_ZeroLength_Throws_UnknownImageFormatException()
{
// https://github.com/SixLabors/ImageSharp/issues/1903
using ZipArchive zipFile = new(new MemoryStream(
@ -159,8 +156,7 @@ public partial class ImageTests
}));
using Stream stream = zipFile.Entries[0].Open();
Assert.False(Image.TryIdentify(stream, out ImageInfo info));
Assert.Null(info);
Assert.Throws<UnknownImageFormatException>(() => Image.TryIdentify(stream, out ImageInfo info));
}
[Fact]
@ -215,7 +211,7 @@ public partial class ImageTests
}
[Fact]
public async Task FromStreamAsync_ZeroLength_ReturnsNull()
public async Task FromStreamAsync_ZeroLength_Throws_UnknownImageFormatException()
{
// https://github.com/SixLabors/ImageSharp/issues/1903
using ZipArchive zipFile = new(new MemoryStream(
@ -234,10 +230,7 @@ public partial class ImageTests
}));
using Stream stream = zipFile.Entries[0].Open();
Attempt<ImageInfo> attempt = await Image.TryIdentifyAsync(stream);
Assert.False(attempt.Success);
Assert.Null(attempt.Value);
await Assert.ThrowsAsync<UnknownImageFormatException>(async () => await Image.TryIdentifyAsync(stream));
}
[Fact]
@ -293,15 +286,12 @@ public partial class ImageTests
}
[Fact]
public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull()
public Task WhenNoMatchingFormatFoundAsync_Throws_UnknownImageFormatException()
{
DecoderOptions options = new() { Configuration = new() };
AsyncStreamWrapper asyncStream = new(this.DataStream, () => false);
Attempt<ImageInfo> attempt = await Image.TryIdentifyAsync(options, asyncStream);
Assert.False(attempt.Success);
Assert.Null(attempt.Value);
return Assert.ThrowsAsync<UnknownImageFormatException>(async () => await Image.TryIdentifyAsync(options, asyncStream));
}
}
}

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

@ -18,10 +18,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgb24>(options, this.MockFilePath);
Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
using (Image<Rgb24> img = Image.Load<Rgb24>(options, this.MockFilePath))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
}
this.TestFormat.VerifySpecificDecodeCall<Rgb24>(this.Marker, this.TopLevelConfiguration);
}
@ -34,10 +35,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.MockFilePath);
Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img);
using (Image img = Image.Load(options, this.MockFilePath))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img);
}
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}
@ -50,10 +52,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgba32>(options, this.MockFilePath, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
using (Image<Rgba32> img = Image.Load<Rgba32>(options, this.MockFilePath))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat, img.Metadata.DecodedImageFormat);
}
this.TestFormat.VerifySpecificDecodeCall<Rgba32>(this.Marker, this.TopLevelConfiguration);
}
@ -66,17 +69,18 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.MockFilePath, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
using (Image img = Image.Load(options, this.MockFilePath))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat, img.Metadata.DecodedImageFormat);
}
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}
[Fact]
public void WhenFileNotFound_Throws()
=> Assert.Throws<System.IO.FileNotFoundException>(
=> Assert.Throws<FileNotFoundException>(
() =>
{
DecoderOptions options = new()

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

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.PixelFormats;
@ -18,14 +17,14 @@ public partial class ImageTests
[Fact]
public void Path_Specific()
{
using var img = Image.Load<Rgba32>(this.Path);
using Image<Rgba32> img = Image.Load<Rgba32>(this.Path);
VerifyDecodedImage(img);
}
[Fact]
public void Path_Agnostic()
{
using var img = Image.Load(this.Path);
using Image img = Image.Load(this.Path);
VerifyDecodedImage(img);
}
@ -53,17 +52,17 @@ public partial class ImageTests
[Fact]
public void Path_OutFormat_Specific()
{
using var img = Image.Load<Rgba32>(this.Path, out IImageFormat format);
using Image<Rgba32> img = Image.Load<Rgba32>(this.Path);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
Assert.IsType<BmpFormat>(img.Metadata.DecodedImageFormat);
}
[Fact]
public void Path_OutFormat_Agnostic()
{
using var img = Image.Load(this.Path, out IImageFormat format);
using Image img = Image.Load(this.Path);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
Assert.IsType<BmpFormat>(img.Metadata.DecodedImageFormat);
}
[Fact]

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

@ -20,10 +20,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgb24>(options, this.ByteSpan);
Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
using (Image<Rgb24> img = Image.Load<Rgb24>(options, this.ByteSpan))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
}
this.TestFormat.VerifySpecificDecodeCall<Rgb24>(this.Marker, this.TopLevelConfiguration);
}
@ -36,10 +37,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.ByteSpan);
Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img);
using (Image img = Image.Load(options, this.ByteSpan))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img);
}
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}
@ -52,10 +54,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Bgr24>(options, this.ByteSpan, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
using (Image<Bgr24> img = Image.Load<Bgr24>(options, this.ByteSpan))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat, img.Metadata.DecodedImageFormat);
}
this.TestFormat.VerifySpecificDecodeCall<Bgr24>(this.Marker, this.TopLevelConfiguration);
}
@ -68,10 +71,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.ByteSpan, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
using (Image img = Image.Load(options, this.ByteSpan))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat, img.Metadata.DecodedImageFormat);
}
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}

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

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.PixelFormats;
@ -20,31 +19,31 @@ public partial class ImageTests
[Fact]
public void Bytes_Specific()
{
using var img = Image.Load<Rgba32>(ByteSpan);
using Image<Rgba32> img = Image.Load<Rgba32>(ByteSpan);
VerifyDecodedImage(img);
}
[Fact]
public void Bytes_Agnostic()
{
using var img = Image.Load(ByteSpan);
using Image img = Image.Load(ByteSpan);
VerifyDecodedImage(img);
}
[Fact]
public void Bytes_OutFormat_Specific()
{
using var img = Image.Load<Rgba32>(ByteSpan, out IImageFormat format);
using Image<Rgba32> img = Image.Load<Rgba32>(ByteSpan);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
Assert.IsType<BmpFormat>(img.Metadata.DecodedImageFormat);
}
[Fact]
public void Bytes_OutFormat_Agnostic()
{
using var img = Image.Load(ByteSpan, out IImageFormat format);
using Image img = Image.Load(ByteSpan);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
Assert.IsType<BmpFormat>(img.Metadata.DecodedImageFormat);
}
}
}

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

@ -18,10 +18,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgb24>(options, this.DataStream);
Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
using (Image<Rgb24> img = Image.Load<Rgb24>(options, this.DataStream))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat.Sample<Rgb24>(), img);
}
this.TestFormat.VerifySpecificDecodeCall<Rgb24>(this.Marker, this.TopLevelConfiguration);
}
@ -34,10 +35,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.DataStream);
Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img);
using (Image img = Image.Load(options, this.DataStream))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat.SampleAgnostic(), img);
}
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}
@ -50,10 +52,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var stream = new NonSeekableStream(this.DataStream);
var img = Image.Load<Rgba32>(options, stream);
Assert.NotNull(img);
NonSeekableStream stream = new(this.DataStream);
using (Image<Rgba32> img = Image.Load<Rgba32>(options, stream))
{
Assert.NotNull(img);
}
this.TestFormat.VerifySpecificDecodeCall<Rgba32>(this.Marker, this.TopLevelConfiguration);
}
@ -66,10 +69,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var stream = new NonSeekableStream(this.DataStream);
Image<Rgba32> img = await Image.LoadAsync<Rgba32>(options, stream);
Assert.NotNull(img);
NonSeekableStream stream = new(this.DataStream);
using (Image<Rgba32> img = await Image.LoadAsync<Rgba32>(options, stream))
{
Assert.NotNull(img);
}
this.TestFormat.VerifySpecificDecodeCall<Rgba32>(this.Marker, this.TopLevelConfiguration);
}
@ -82,10 +86,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load<Rgba32>(options, this.DataStream, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
using (Image<Rgba32> img = Image.Load<Rgba32>(options, this.DataStream))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat, img.Metadata.DecodedImageFormat);
}
this.TestFormat.VerifySpecificDecodeCall<Rgba32>(this.Marker, this.TopLevelConfiguration);
}
@ -98,10 +103,11 @@ public partial class ImageTests
Configuration = this.TopLevelConfiguration
};
var img = Image.Load(options, this.DataStream, out IImageFormat format);
Assert.NotNull(img);
Assert.Equal(this.TestFormat, format);
using (Image img = Image.Load(options, this.DataStream))
{
Assert.NotNull(img);
Assert.Equal(this.TestFormat, img.Metadata.DecodedImageFormat);
}
this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration);
}

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

@ -18,7 +18,7 @@ public partial class ImageTests
public void Image_Load_Throws_UnknownImageFormatException()
=> Assert.Throws<UnknownImageFormatException>(() =>
{
using (Image.Load(DecoderOptions.Default, this.Stream, out IImageFormat format))
using (Image.Load(DecoderOptions.Default, this.Stream))
{
}
});
@ -27,7 +27,7 @@ public partial class ImageTests
public void Image_Load_T_Throws_UnknownImageFormatException()
=> Assert.Throws<UnknownImageFormatException>(() =>
{
using (Image.Load<Rgba32>(DecoderOptions.Default, this.Stream, out IImageFormat format))
using (Image.Load<Rgba32>(DecoderOptions.Default, this.Stream))
{
}
});

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

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities;
@ -32,42 +31,42 @@ public partial class ImageTests
[Fact]
public void Stream_Specific()
{
using var img = Image.Load<Rgba32>(this.Stream);
using Image<Rgba32> img = Image.Load<Rgba32>(this.Stream);
VerifyDecodedImage(img);
}
[Fact]
public void Stream_Agnostic()
{
using var img = Image.Load(this.Stream);
using Image img = Image.Load(this.Stream);
VerifyDecodedImage(img);
}
[Fact]
public void Stream_OutFormat_Specific()
{
using var img = Image.Load<Rgba32>(this.Stream, out IImageFormat format);
using Image<Rgba32> img = Image.Load<Rgba32>(this.Stream);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
Assert.IsType<BmpFormat>(img.Metadata.DecodedImageFormat);
}
[Fact]
public void Stream_OutFormat_Agnostic()
{
using var img = Image.Load(this.Stream, out IImageFormat format);
using Image img = Image.Load(this.Stream);
VerifyDecodedImage(img);
Assert.IsType<BmpFormat>(format);
Assert.IsType<BmpFormat>(img.Metadata.DecodedImageFormat);
}
[Fact]
public async Task Async_Stream_OutFormat_Agnostic()
{
this.AllowSynchronousIO = false;
(Image Image, IImageFormat Format) formattedImage = await Image.LoadWithFormatAsync(this.Stream);
using (formattedImage.Image)
Image image = await Image.LoadAsync(this.Stream);
using (image)
{
VerifyDecodedImage(formattedImage.Image);
Assert.IsType<BmpFormat>(formattedImage.Format);
VerifyDecodedImage(image);
Assert.IsType<BmpFormat>(image.Metadata.DecodedImageFormat);
}
}
@ -91,11 +90,11 @@ public partial class ImageTests
public async Task Async_Stream_OutFormat_Specific()
{
this.AllowSynchronousIO = false;
(Image<Rgba32> Image, IImageFormat Format) formattedImage = await Image.LoadWithFormatAsync<Rgba32>(this.Stream);
using (formattedImage.Image)
Image<Rgba32> image = await Image.LoadAsync<Rgba32>(this.Stream);
using (image)
{
VerifyDecodedImage(formattedImage.Image);
Assert.IsType<BmpFormat>(formattedImage.Format);
VerifyDecodedImage(image);
Assert.IsType<BmpFormat>(image.Metadata.DecodedImageFormat);
}
}

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

@ -19,30 +19,26 @@ public partial class ImageTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = Path.Combine(dir, "DetectedEncoding.png");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.Save(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public void WhenExtensionIsUnknown_Throws()
public void WhenExtensionIsUnknown_Throws_UnknownImageFormatException()
{
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = Path.Combine(dir, "UnknownExtensionsEncoding_Throws.tmp");
Assert.Throws<NotSupportedException>(
Assert.Throws<UnknownImageFormatException>(
() =>
{
using (var image = new Image<Rgba32>(10, 10))
{
image.Save(file);
}
using Image<Rgba32> image = new(10, 10);
image.Save(file);
});
}
@ -52,27 +48,23 @@ public partial class ImageTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = Path.Combine(dir, "SetEncoding.dat");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
image.Save(file, new PngEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public void ThrowsWhenDisposed()
{
using var image = new Image<Rgba32>(5, 5);
using Image<Rgba32> image = new(5, 5);
image.Dispose();
IImageEncoder encoder = Mock.Of<IImageEncoder>();
using (var stream = new MemoryStream())
{
Assert.Throws<ObjectDisposedException>(() => image.Save(stream, encoder));
}
using MemoryStream stream = new();
Assert.Throws<ObjectDisposedException>(() => image.Save(stream, encoder));
}
}
}

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

@ -21,30 +21,26 @@ public partial class ImageTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = Path.Combine(dir, "DetectedEncodingAsync.png");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsync(file);
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Fact]
public async Task WhenExtensionIsUnknown_Throws()
public Task WhenExtensionIsUnknown_Throws_UnknownImageFormatException()
{
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = Path.Combine(dir, "UnknownExtensionsEncoding_Throws.tmp");
await Assert.ThrowsAsync<NotSupportedException>(
return Assert.ThrowsAsync<UnknownImageFormatException>(
async () =>
{
using (var image = new Image<Rgba32>(10, 10))
{
await image.SaveAsync(file);
}
using Image<Rgba32> image = new(10, 10);
await image.SaveAsync(file);
});
}
@ -54,15 +50,13 @@ public partial class ImageTests
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = Path.Combine(dir, "SetEncoding.dat");
using (var image = new Image<Rgba32>(10, 10))
using (Image<Rgba32> image = new(10, 10))
{
await image.SaveAsync(file, new PngEncoder());
}
using (Image.Load(file, out IImageFormat mime))
{
Assert.Equal("image/png", mime.DefaultMimeType);
}
Image.TryDetectFormat(file, out IImageFormat format);
Assert.True(format is PngFormat);
}
[Theory]
@ -74,39 +68,29 @@ public partial class ImageTests
[InlineData("test.gif", "image/gif")]
public async Task SaveStreamWithMime(string filename, string mimeType)
{
using (var image = new Image<Rgba32>(5, 5))
{
string ext = Path.GetExtension(filename);
image.GetConfiguration().ImageFormatsManager.TryFindFormatByFileExtension(ext, out IImageFormat format);
Assert.Equal(mimeType, format!.DefaultMimeType);
using (var stream = new MemoryStream())
{
var asyncStream = new AsyncStreamWrapper(stream, () => false);
await image.SaveAsync(asyncStream, format);
using Image<Rgba32> image = new(5, 5);
string ext = Path.GetExtension(filename);
image.GetConfiguration().ImageFormatsManager.TryFindFormatByFileExtension(ext, out IImageFormat format);
Assert.Equal(mimeType, format!.DefaultMimeType);
stream.Position = 0;
using MemoryStream stream = new();
AsyncStreamWrapper asyncStream = new(stream, () => false);
await image.SaveAsync(asyncStream, format);
(Image Image, IImageFormat Format) imf = await Image.LoadWithFormatAsync(stream);
stream.Position = 0;
Assert.Equal(format, imf.Format);
Assert.Equal(mimeType, imf.Format.DefaultMimeType);
imf.Image.Dispose();
}
}
Image.TryDetectFormat(stream, out IImageFormat format2);
Assert.Equal(format, format2);
}
[Fact]
public async Task ThrowsWhenDisposed()
{
var image = new Image<Rgba32>(5, 5);
Image<Rgba32> image = new(5, 5);
image.Dispose();
IImageEncoder encoder = Mock.Of<IImageEncoder>();
using (var stream = new MemoryStream())
{
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await image.SaveAsync(stream, encoder));
}
using MemoryStream stream = new();
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await image.SaveAsync(stream, encoder));
}
[Theory]
@ -118,27 +102,23 @@ public partial class ImageTests
[InlineData("test.gif")]
public async Task SaveAsync_NeverCallsSyncMethods(string filename)
{
using (var image = new Image<Rgba32>(5, 5))
{
IImageEncoder encoder = image.DetectEncoder(filename);
using (var stream = new MemoryStream())
{
var asyncStream = new AsyncStreamWrapper(stream, () => false);
await image.SaveAsync(asyncStream, encoder);
}
}
using Image<Rgba32> image = new(5, 5);
IImageEncoder encoder = image.DetectEncoder(filename);
using MemoryStream stream = new();
AsyncStreamWrapper asyncStream = new(stream, () => false);
await image.SaveAsync(asyncStream, encoder);
}
[Fact]
public async Task SaveAsync_WithNonSeekableStream_IsCancellable()
{
using var image = new Image<Rgba32>(4000, 4000);
var encoder = new PngEncoder() { CompressionLevel = PngCompressionLevel.BestCompression };
using var stream = new MemoryStream();
var asyncStream = new AsyncStreamWrapper(stream, () => false);
var cts = new CancellationTokenSource();
using Image<Rgba32> image = new(4000, 4000);
PngEncoder encoder = new() { CompressionLevel = PngCompressionLevel.BestCompression };
using MemoryStream stream = new();
AsyncStreamWrapper asyncStream = new(stream, () => false);
CancellationTokenSource cts = new();
var pausedStream = new PausedStream(asyncStream);
PausedStream pausedStream = new(asyncStream);
pausedStream.OnWaiting(s =>
{
cts.Cancel();

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

@ -23,7 +23,7 @@ public partial class ImageTests
[Fact]
public void Width_Height()
{
using (var image = new Image<Rgba32>(11, 23))
using (Image<Rgba32> image = new(11, 23))
{
Assert.Equal(11, image.Width);
Assert.Equal(23, image.Height);
@ -40,7 +40,7 @@ public partial class ImageTests
{
Configuration configuration = Configuration.Default.Clone();
using (var image = new Image<Rgba32>(configuration, 11, 23))
using (Image<Rgba32> image = new(configuration, 11, 23))
{
Assert.Equal(11, image.Width);
Assert.Equal(23, image.Height);
@ -58,7 +58,7 @@ public partial class ImageTests
Configuration configuration = Configuration.Default.Clone();
Rgba32 color = Color.Aquamarine;
using (var image = new Image<Rgba32>(configuration, 11, 23, color))
using (Image<Rgba32> image = new(configuration, 11, 23, color))
{
Assert.Equal(11, image.Width);
Assert.Equal(23, image.Height);
@ -77,9 +77,9 @@ public partial class ImageTests
byte dirtyValue = 123;
configuration.MemoryAllocator = new TestMemoryAllocator(dirtyValue);
var metadata = new ImageMetadata();
ImageMetadata metadata = new();
using (var image = Image.CreateUninitialized<L8>(configuration, 21, 22, metadata))
using (Image<L8> image = Image.CreateUninitialized<L8>(configuration, 21, 22, metadata))
{
Assert.Equal(21, image.Width);
Assert.Equal(22, image.Height);
@ -108,7 +108,7 @@ public partial class ImageTests
this.LimitBufferCapacity(100);
}
using var image = new Image<Rgba32>(this.configuration, 10, 10);
using Image<Rgba32> image = new(this.configuration, 10, 10);
Rgba32 val = image[3, 4];
Assert.Equal(default(Rgba32), val);
image[3, 4] = Color.Red;
@ -116,7 +116,7 @@ public partial class ImageTests
Assert.Equal(Color.Red.ToRgba32(), val);
}
public static TheoryData<bool, int> OutOfRangeData = new TheoryData<bool, int>()
public static TheoryData<bool, int> OutOfRangeData = new()
{
{ false, -1 },
{ false, 10 },
@ -133,7 +133,7 @@ public partial class ImageTests
this.LimitBufferCapacity(100);
}
using var image = new Image<Rgba32>(this.configuration, 10, 10);
using Image<Rgba32> image = new(this.configuration, 10, 10);
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => _ = image[x, 3]);
Assert.Equal("x", ex.ParamName);
}
@ -147,7 +147,7 @@ public partial class ImageTests
this.LimitBufferCapacity(100);
}
using var image = new Image<Rgba32>(this.configuration, 10, 10);
using Image<Rgba32> image = new(this.configuration, 10, 10);
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => image[x, 3] = default);
Assert.Equal("x", ex.ParamName);
}
@ -161,7 +161,7 @@ public partial class ImageTests
this.LimitBufferCapacity(100);
}
using var image = new Image<Rgba32>(this.configuration, 10, 10);
using Image<Rgba32> image = new(this.configuration, 10, 10);
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => image[3, y] = default);
Assert.Equal("y", ex.ParamName);
}
@ -178,7 +178,7 @@ public partial class ImageTests
this.LimitBufferCapacity(20);
}
using var image = new Image<La16>(this.configuration, 10, 10);
using Image<La16> image = new(this.configuration, 10, 10);
if (disco)
{
Assert.True(image.GetPixelMemoryGroup().Count > 1);
@ -204,7 +204,7 @@ public partial class ImageTests
[InlineData(true)]
public void CopyPixelDataTo_DestinationTooShort_Throws(bool byteSpan)
{
using var image = new Image<La16>(this.configuration, 10, 10);
using Image<La16> image = new(this.configuration, 10, 10);
Assert.ThrowsAny<ArgumentOutOfRangeException>(() =>
{
@ -243,7 +243,7 @@ public partial class ImageTests
[Fact]
public void NullReference_Throws()
{
using var img = new Image<Rgb24>(1, 1);
using Image<Rgb24> img = new(1, 1);
Assert.Throws<ArgumentNullException>(() => img.ProcessPixelRows(null));
@ -262,7 +262,7 @@ public partial class ImageTests
public void MultipleDisposeCalls()
{
var image = new Image<Rgba32>(this.configuration, 10, 10);
Image<Rgba32> image = new(this.configuration, 10, 10);
image.Dispose();
image.Dispose();
}
@ -270,24 +270,24 @@ public partial class ImageTests
[Fact]
public void NonPrivateProperties_ObjectDisposedException()
{
var image = new Image<Rgba32>(this.configuration, 10, 10);
var genericImage = (Image)image;
Image<Rgba32> image = new(this.configuration, 10, 10);
Image genericImage = (Image)image;
image.Dispose();
// Image<TPixel>
Assert.Throws<ObjectDisposedException>(() => { var prop = image.Frames; });
Assert.Throws<ObjectDisposedException>(() => { ImageFrameCollection<Rgba32> prop = image.Frames; });
// Image
Assert.Throws<ObjectDisposedException>(() => { var prop = genericImage.Frames; });
Assert.Throws<ObjectDisposedException>(() => { ImageFrameCollection prop = genericImage.Frames; });
}
[Fact]
public void Save_ObjectDisposedException()
{
using var stream = new MemoryStream();
var image = new Image<Rgba32>(this.configuration, 10, 10);
var encoder = new JpegEncoder();
using MemoryStream stream = new();
Image<Rgba32> image = new(this.configuration, 10, 10);
JpegEncoder encoder = new();
image.Dispose();
@ -307,18 +307,18 @@ public partial class ImageTests
[Fact]
public void NonPrivateMethods_ObjectDisposedException()
{
var image = new Image<Rgba32>(this.configuration, 10, 10);
var genericImage = (Image)image;
Image<Rgba32> image = new(this.configuration, 10, 10);
Image genericImage = (Image)image;
image.Dispose();
// Image<TPixel>
Assert.Throws<ObjectDisposedException>(() => { var res = image.Clone(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { var res = image.CloneAs<Rgba32>(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { var res = image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> _); });
Assert.Throws<ObjectDisposedException>(() => { Image<Rgba32> res = image.Clone(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { Image<Rgba32> res = image.CloneAs<Rgba32>(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { bool res = image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> _); });
// Image
Assert.Throws<ObjectDisposedException>(() => { var res = genericImage.CloneAs<Rgba32>(this.configuration); });
Assert.Throws<ObjectDisposedException>(() => { Image<Rgba32> res = genericImage.CloneAs<Rgba32>(this.configuration); });
}
}
@ -327,29 +327,29 @@ public partial class ImageTests
[Fact]
public void KnownExtension_ReturnsEncoder()
{
using var image = new Image<L8>(1, 1);
using Image<L8> image = new(1, 1);
IImageEncoder encoder = image.DetectEncoder("dummy.png");
Assert.NotNull(encoder);
Assert.IsType<PngEncoder>(encoder);
}
[Fact]
public void UnknownExtension_ThrowsNotSupportedException()
public void UnknownExtension_ThrowsUnknownImageFormatException()
{
using var image = new Image<L8>(1, 1);
Assert.Throws<NotSupportedException>(() => image.DetectEncoder("dummy.yolo"));
using Image<L8> image = new(1, 1);
Assert.Throws<UnknownImageFormatException>(() => image.DetectEncoder("dummy.yolo"));
}
[Fact]
public void NoDetectorRegisteredForKnownExtension_ThrowsNotSupportedException()
public void NoDetectorRegisteredForKnownExtension_ThrowsUnknownImageFormatException()
{
var configuration = new Configuration();
var format = new TestFormat();
Configuration configuration = new();
TestFormat format = new();
configuration.ImageFormatsManager.AddImageFormat(format);
configuration.ImageFormatsManager.AddImageFormatDetector(new MockImageFormatDetector(format));
using var image = new Image<L8>(configuration, 1, 1);
Assert.Throws<NotSupportedException>(() => image.DetectEncoder($"dummy.{format.Extension}"));
using Image<L8> image = new(configuration, 1, 1);
Assert.Throws<UnknownImageFormatException>(() => image.DetectEncoder($"dummy.{format.Extension}"));
}
}
}

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

@ -56,7 +56,7 @@ public class LargeImageIntegrationTests
Configuration configuration = Configuration.Default.Clone();
configuration.PreferContiguousImageBuffers = true;
configuration.ImageFormatsManager.TryFindFormatByFileExtension(formatInner, out IImageFormat format);
IImageEncoder encoder = configuration.ImageFormatsManager.FindEncoder(format!);
IImageEncoder encoder = configuration.ImageFormatsManager.GetEncoder(format!);
string dir = TestEnvironment.CreateOutputDirectory(".Temp");
string path = Path.Combine(dir, $"{Guid.NewGuid()}.{formatInner}");
using (Image<Rgba32> temp = new(2048, 2048))

412
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs

@ -38,15 +38,13 @@ public class ResizeTests
{
string filePath = TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora);
using (var image = Image.Load(filePath))
{
image.Mutate(x => x.Resize(image.Size() / 2));
string path = System.IO.Path.Combine(
TestEnvironment.CreateOutputDirectory(nameof(ResizeTests)),
nameof(this.Resize_PixelAgnostic) + ".png");
using Image image = Image.Load(filePath);
image.Mutate(x => x.Resize(image.Size() / 2));
string path = Path.Combine(
TestEnvironment.CreateOutputDirectory(nameof(ResizeTests)),
nameof(this.Resize_PixelAgnostic) + ".png");
image.Save(path);
}
image.Save(path);
}
[Theory(Skip = "Debug only, enable manually")]
@ -63,11 +61,9 @@ public class ResizeTests
provider.Configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInKilobytes * 1024;
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(destSize, destSize));
image.DebugSave(provider, appendPixelTypeToFileName: false);
}
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(destSize, destSize));
image.DebugSave(provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -81,14 +77,12 @@ public class ResizeTests
// [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] means:
// resizing: (15, 12) -> (10, 6)
// kernel dimensions: (3, 4)
using (Image<TPixel> image = provider.GetImage())
{
var destSize = new Size(image.Width * wN / wD, image.Height * hN / hD);
image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false));
FormattableString outputInfo = $"({wN}÷{wD},{hN}÷{hD})";
image.DebugSave(provider, outputInfo, appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(provider, outputInfo, appendPixelTypeToFileName: false);
}
using Image<TPixel> image = provider.GetImage();
Size destSize = new Size(image.Width * wN / wD, image.Height * hN / hD);
image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false));
FormattableString outputInfo = $"({wN}÷{wD},{hN}÷{hD})";
image.DebugSave(provider, outputInfo, appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(provider, outputInfo, appendPixelTypeToFileName: false);
}
private static readonly int SizeOfVector4 = Unsafe.SizeOf<Vector4>();
@ -106,48 +100,44 @@ public class ResizeTests
int workingBufferLimitInRows)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image0 = provider.GetImage())
{
Size destSize = image0.Size() / 4;
var configuration = Configuration.CreateDefaultInstance();
int workingBufferSizeHintInBytes = workingBufferLimitInRows * destSize.Width * SizeOfVector4;
var allocator = new TestMemoryAllocator();
allocator.EnableNonThreadSafeLogging();
configuration.MemoryAllocator = allocator;
configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInBytes;
var verticalKernelMap = ResizeKernelMap.Calculate<BicubicResampler>(
default,
destSize.Height,
image0.Height,
Configuration.Default.MemoryAllocator);
int minimumWorkerAllocationInBytes = verticalKernelMap.MaxDiameter * 2 * destSize.Width * SizeOfVector4;
verticalKernelMap.Dispose();
using (Image<TPixel> image = image0.Clone(configuration))
{
image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false));
image.DebugSave(
provider,
testOutputDetails: workingBufferLimitInRows,
appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.004f),
provider,
testOutputDetails: workingBufferLimitInRows,
appendPixelTypeToFileName: false);
using Image<TPixel> image0 = provider.GetImage();
Size destSize = image0.Size() / 4;
Configuration configuration = Configuration.CreateDefaultInstance();
int workingBufferSizeHintInBytes = workingBufferLimitInRows * destSize.Width * SizeOfVector4;
TestMemoryAllocator allocator = new TestMemoryAllocator();
allocator.EnableNonThreadSafeLogging();
configuration.MemoryAllocator = allocator;
configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInBytes;
ResizeKernelMap verticalKernelMap = ResizeKernelMap.Calculate<BicubicResampler>(
default,
destSize.Height,
image0.Height,
Configuration.Default.MemoryAllocator);
int minimumWorkerAllocationInBytes = verticalKernelMap.MaxDiameter * 2 * destSize.Width * SizeOfVector4;
verticalKernelMap.Dispose();
using Image<TPixel> image = image0.Clone(configuration);
image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false));
image.DebugSave(
provider,
testOutputDetails: workingBufferLimitInRows,
appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(
ImageComparer.TolerantPercentage(0.004f),
provider,
testOutputDetails: workingBufferLimitInRows,
appendPixelTypeToFileName: false);
Assert.NotEmpty(allocator.AllocationLog);
Assert.NotEmpty(allocator.AllocationLog);
int maxAllocationSize = allocator.AllocationLog.Where(
e => e.ElementType == typeof(Vector4)).Max(e => e.LengthInBytes);
int maxAllocationSize = allocator.AllocationLog.Where(
e => e.ElementType == typeof(Vector4)).Max(e => e.LengthInBytes);
Assert.True(maxAllocationSize <= Math.Max(workingBufferSizeHintInBytes, minimumWorkerAllocationInBytes));
}
}
Assert.True(maxAllocationSize <= Math.Max(workingBufferSizeHintInBytes, minimumWorkerAllocationInBytes));
}
[Theory]
@ -188,13 +178,11 @@ public class ResizeTests
public void Resize_Compand<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(image.Size() / 2, true));
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(image.Size() / 2, true));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider);
}
[Theory]
@ -223,7 +211,7 @@ public class ResizeTests
provider.RunValidatingProcessorTest(
x =>
{
var resizeOptions = new ResizeOptions()
ResizeOptions resizeOptions = new ResizeOptions()
{
Size = x.GetCurrentSize() / 2,
Mode = ResizeMode.Crop,
@ -243,13 +231,11 @@ public class ResizeTests
public void Resize_IsAppliedToAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, KnownResamplers.Bicubic));
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, KnownResamplers.Bicubic));
// Comparer fights decoder with gif-s. Could not use CompareToReferenceOutput here :(
image.DebugSave(provider, extension: "gif");
}
// Comparer fights decoder with gif-s. Could not use CompareToReferenceOutput here :(
image.DebugSave(provider, extension: "gif");
}
[Theory]
@ -265,17 +251,13 @@ public class ResizeTests
public void Resize_ThrowsForWrappedMemoryImage<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image0 = provider.GetImage())
{
Assert.True(image0.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imageMem));
var mmg = TestMemoryManager<TPixel>.CreateAsCopyOf(imageMem.Span);
using Image<TPixel> image0 = provider.GetImage();
Assert.True(image0.DangerousTryGetSinglePixelMemory(out Memory<TPixel> imageMem));
TestMemoryManager<TPixel> mmg = TestMemoryManager<TPixel>.CreateAsCopyOf(imageMem.Span);
using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height))
{
Assert.ThrowsAny<Exception>(
() => { image1.Mutate(x => x.Resize(image0.Width / 2, image0.Height / 2, true)); });
}
}
using Image<TPixel> image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height);
Assert.ThrowsAny<Exception>(
() => { image1.Mutate(x => x.Resize(image0.Width / 2, image0.Height / 2, true)); });
}
[Theory]
@ -341,7 +323,7 @@ public class ResizeTests
&& TestEnvironment.NetCoreVersion == null
&& sampler is NearestNeighborResampler;
var comparer = ImageComparer.TolerantPercentage(allowHigherInaccuracy ? 0.3f : 0.017f);
ImageComparer comparer = ImageComparer.TolerantPercentage(allowHigherInaccuracy ? 0.3f : 0.017f);
// Let's make the working buffer size non-default:
provider.Configuration.WorkingBufferSizeHintInBytes = 16 * 1024 * SizeOfVector4;
@ -382,27 +364,25 @@ public class ResizeTests
public void ResizeFromSourceRectangle<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
var sourceRectangle = new Rectangle(
image.Width / 8,
image.Height / 8,
image.Width / 4,
image.Height / 4);
var destRectangle = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2);
image.Mutate(
x => x.Resize(
image.Width,
image.Height,
KnownResamplers.Bicubic,
sourceRectangle,
destRectangle,
false));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
using Image<TPixel> image = provider.GetImage();
Rectangle sourceRectangle = new Rectangle(
image.Width / 8,
image.Height / 8,
image.Width / 4,
image.Height / 4);
Rectangle destRectangle = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2);
image.Mutate(
x => x.Resize(
image.Width,
image.Height,
KnownResamplers.Bicubic,
sourceRectangle,
destRectangle,
false));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -410,13 +390,11 @@ public class ResizeTests
public void ResizeHeightAndKeepAspect<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(0, image.Height / 3, false));
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(0, image.Height / 3, false));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -424,12 +402,10 @@ public class ResizeTests
public void ResizeHeightCannotKeepAspectKeepsOnePixel<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(0, 5));
Assert.Equal(1, image.Width);
Assert.Equal(5, image.Height);
}
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(0, 5));
Assert.Equal(1, image.Width);
Assert.Equal(5, image.Height);
}
[Theory]
@ -437,13 +413,11 @@ public class ResizeTests
public void ResizeWidthAndKeepAspect<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(image.Width / 3, 0, false));
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(image.Width / 3, 0, false));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -451,12 +425,10 @@ public class ResizeTests
public void ResizeWidthCannotKeepAspectKeepsOnePixel<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Resize(5, 0));
Assert.Equal(5, image.Width);
Assert.Equal(1, image.Height);
}
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Resize(5, 0));
Assert.Equal(5, image.Width);
Assert.Equal(1, image.Height);
}
[Theory]
@ -464,20 +436,18 @@ public class ResizeTests
public void ResizeWithBoxPadMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions
{
var options = new ResizeOptions
{
Size = new Size(image.Width + 200, image.Height + 200),
Mode = ResizeMode.BoxPad,
PadColor = Color.HotPink
};
Size = new Size(image.Width + 200, image.Height + 200),
Mode = ResizeMode.BoxPad,
PadColor = Color.HotPink
};
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -485,15 +455,13 @@ public class ResizeTests
public void ResizeWithCropHeightMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
var options = new ResizeOptions { Size = new Size(image.Width, image.Height / 2) };
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions { Size = new Size(image.Width, image.Height / 2) };
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -501,15 +469,13 @@ public class ResizeTests
public void ResizeWithCropWidthMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
var options = new ResizeOptions { Size = new Size(image.Width / 2, image.Height) };
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions { Size = new Size(image.Width / 2, image.Height) };
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -517,19 +483,17 @@ public class ResizeTests
public void CanResizeLargeImageWithCropMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions
{
var options = new ResizeOptions
{
Size = new Size(480, 600),
Mode = ResizeMode.Crop
};
Size = new Size(480, 600),
Mode = ResizeMode.Crop
};
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -537,15 +501,13 @@ public class ResizeTests
public void ResizeWithMaxMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
var options = new ResizeOptions { Size = new Size(300, 300), Mode = ResizeMode.Max };
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions { Size = new Size(300, 300), Mode = ResizeMode.Max };
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -553,19 +515,17 @@ public class ResizeTests
public void ResizeWithMinMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions
{
var options = new ResizeOptions
{
Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)),
Mode = ResizeMode.Min
};
Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)),
Mode = ResizeMode.Min
};
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -573,20 +533,18 @@ public class ResizeTests
public void ResizeWithPadMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions
{
var options = new ResizeOptions
{
Size = new Size(image.Width + 200, image.Height),
Mode = ResizeMode.Pad,
PadColor = Color.Lavender
};
Size = new Size(image.Width + 200, image.Height),
Mode = ResizeMode.Pad,
PadColor = Color.Lavender
};
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -594,19 +552,17 @@ public class ResizeTests
public void ResizeWithStretchMode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
using Image<TPixel> image = provider.GetImage();
ResizeOptions options = new ResizeOptions
{
var options = new ResizeOptions
{
Size = new Size(image.Width / 2, image.Height),
Mode = ResizeMode.Stretch
};
Size = new Size(image.Width / 2, image.Height),
Mode = ResizeMode.Stretch
};
image.Mutate(x => x.Resize(options));
image.Mutate(x => x.Resize(options));
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
image.DebugSave(provider);
image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false);
}
[Theory]
@ -622,27 +578,23 @@ public class ResizeTests
return;
}
using (Image<TPixel> image = provider.GetImage())
{
// Don't bother saving, we're testing the EXIF metadata updates.
image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2));
}
using Image<TPixel> image = provider.GetImage();
// Don't bother saving, we're testing the EXIF metadata updates.
image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2));
}
[Fact]
public void Issue1195()
{
using (var image = new Image<Rgba32>(2, 300))
{
var size = new Size(50, 50);
image.Mutate(x => x
.Resize(
new ResizeOptions
{
Size = size,
Mode = ResizeMode.Max
}));
}
using Image<Rgba32> image = new Image<Rgba32>(2, 300);
Size size = new Size(50, 50);
image.Mutate(x => x
.Resize(
new ResizeOptions
{
Size = size,
Mode = ResizeMode.Max
}));
}
[Theory]
@ -653,20 +605,18 @@ public class ResizeTests
[InlineData(3, 7)]
public void Issue1342(int width, int height)
{
using (var image = new Image<Rgba32>(1, 1))
{
var size = new Size(width, height);
image.Mutate(x => x
.Resize(
new ResizeOptions
{
Size = size,
Sampler = KnownResamplers.NearestNeighbor
}));
using Image<Rgba32> image = new Image<Rgba32>(1, 1);
Size size = new Size(width, height);
image.Mutate(x => x
.Resize(
new ResizeOptions
{
Size = size,
Sampler = KnownResamplers.NearestNeighbor
}));
Assert.Equal(width, image.Width);
Assert.Equal(height, image.Height);
}
Assert.Equal(width, image.Width);
Assert.Equal(height, image.Height);
}
[Theory]

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

@ -24,13 +24,13 @@ public static partial class TestEnvironment
internal static IImageDecoder GetReferenceDecoder(string filePath)
{
IImageFormat format = GetImageFormat(filePath);
return Configuration.ImageFormatsManager.FindDecoder(format);
return Configuration.ImageFormatsManager.GetDecoder(format);
}
internal static IImageEncoder GetReferenceEncoder(string filePath)
{
IImageFormat format = GetImageFormat(filePath);
return Configuration.ImageFormatsManager.FindEncoder(format);
return Configuration.ImageFormatsManager.GetEncoder(format);
}
internal static IImageFormat GetImageFormat(string filePath)

Loading…
Cancel
Save