Browse Source

Plumb CancellationToken through IImageDecoder and IImageInfoDetector methods

pull/2006/head
Dan Kroymann 4 years ago
parent
commit
3a11b2f382
  1. 12
      src/ImageSharp/Formats/Bmp/BmpDecoder.cs
  2. 12
      src/ImageSharp/Formats/Gif/GifDecoder.cs
  3. 6
      src/ImageSharp/Formats/IImageDecoder.cs
  4. 3
      src/ImageSharp/Formats/IImageInfoDetector.cs
  5. 18
      src/ImageSharp/Formats/ImageDecoderUtilities.cs
  6. 12
      src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
  7. 12
      src/ImageSharp/Formats/Pbm/PbmDecoder.cs
  8. 40
      src/ImageSharp/Formats/Png/PngDecoder.cs
  9. 12
      src/ImageSharp/Formats/Tga/TgaDecoder.cs
  10. 10
      src/ImageSharp/Formats/Tiff/TiffDecoder.cs
  11. 10
      src/ImageSharp/Formats/Webp/WebpDecoder.cs
  12. 14
      src/ImageSharp/Image.Decode.cs
  13. 6
      tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs
  14. 4
      tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs
  15. 4
      tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs
  16. 10
      tests/ImageSharp.Tests/TestFormat.cs
  17. 6
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
  18. 10
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
  19. 8
      tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs

12
src/ImageSharp/Formats/Bmp/BmpDecoder.cs

@ -31,18 +31,18 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public RleSkippedPixelHandling RleSkippedPixelHandling { get; set; } = RleSkippedPixelHandling.Black; public RleSkippedPixelHandling RleSkippedPixelHandling { get; set; } = RleSkippedPixelHandling.Black;
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
var decoder = new BmpDecoderCore(configuration, this); var decoder = new BmpDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
=> this.Decode<Rgba32>(configuration, stream); => this.Decode<Rgba32>(configuration, stream, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
@ -60,11 +60,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
.ConfigureAwait(false); .ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
return new BmpDecoderCore(configuration, this).Identify(configuration, stream); return new BmpDecoderCore(configuration, this).Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

12
src/ImageSharp/Formats/Gif/GifDecoder.cs

@ -27,16 +27,16 @@ namespace SixLabors.ImageSharp.Formats.Gif
public FrameDecodingMode DecodingMode { get; set; } = FrameDecodingMode.All; public FrameDecodingMode DecodingMode { get; set; } = FrameDecodingMode.All;
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var decoder = new GifDecoderCore(configuration, this); var decoder = new GifDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
=> this.Decode<Rgba32>(configuration, stream); => this.Decode<Rgba32>(configuration, stream, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
@ -52,14 +52,14 @@ namespace SixLabors.ImageSharp.Formats.Gif
.ConfigureAwait(false); .ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
var decoder = new GifDecoderCore(configuration, this); var decoder = new GifDecoderCore(configuration, this);
using var bufferedStream = new BufferedReadStream(configuration, stream); using var bufferedStream = new BufferedReadStream(configuration, stream);
return decoder.Identify(bufferedStream, default); return decoder.Identify(bufferedStream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

6
src/ImageSharp/Formats/IImageDecoder.cs

@ -19,9 +19,10 @@ namespace SixLabors.ImageSharp.Formats
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="configuration">The configuration for the image.</param> /// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param> /// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="Image{TPixel}"/>.</returns>
// TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110) // TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110)
Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel>; where TPixel : unmanaged, IPixel<TPixel>;
/// <summary> /// <summary>
@ -29,9 +30,10 @@ namespace SixLabors.ImageSharp.Formats
/// </summary> /// </summary>
/// <param name="configuration">The configuration for the image.</param> /// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param> /// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The <see cref="Image"/>.</returns> /// <returns>The <see cref="Image"/>.</returns>
// TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110) // TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110)
Image Decode(Configuration configuration, Stream stream); Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Decodes the image from the specified stream to an <see cref="Image{TPixel}"/> of a specific pixel type. /// Decodes the image from the specified stream to an <see cref="Image{TPixel}"/> of a specific pixel type.

3
src/ImageSharp/Formats/IImageInfoDetector.cs

@ -17,8 +17,9 @@ namespace SixLabors.ImageSharp.Formats
/// </summary> /// </summary>
/// <param name="configuration">The configuration for the image.</param> /// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param> /// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The <see cref="PixelTypeInfo"/> object</returns> /// <returns>The <see cref="PixelTypeInfo"/> object</returns>
IImageInfo Identify(Configuration configuration, Stream stream); IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Reads the raw image information from the specified stream. /// Reads the raw image information from the specified stream.

18
src/ImageSharp/Formats/ImageDecoderUtilities.cs

@ -130,13 +130,14 @@ namespace SixLabors.ImageSharp.Formats
public static IImageInfo Identify( public static IImageInfo Identify(
this IImageDecoderInternals decoder, this IImageDecoderInternals decoder,
Configuration configuration, Configuration configuration,
Stream stream) Stream stream,
CancellationToken cancellationToken = default)
{ {
using var bufferedReadStream = new BufferedReadStream(configuration, stream); using var bufferedReadStream = new BufferedReadStream(configuration, stream);
try try
{ {
return decoder.Identify(bufferedReadStream, default); return decoder.Identify(bufferedReadStream, cancellationToken);
} }
catch (InvalidMemoryOperationException ex) catch (InvalidMemoryOperationException ex)
{ {
@ -144,22 +145,27 @@ namespace SixLabors.ImageSharp.Formats
} }
} }
public static Image<TPixel> Decode<TPixel>(this IImageDecoderInternals decoder, Configuration configuration, Stream stream) public static Image<TPixel> Decode<TPixel>(
this IImageDecoderInternals decoder,
Configuration configuration,
Stream stream,
CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
=> decoder.Decode<TPixel>(configuration, stream, DefaultLargeImageExceptionFactory); => decoder.Decode<TPixel>(configuration, stream, DefaultLargeImageExceptionFactory, cancellationToken);
public static Image<TPixel> Decode<TPixel>( public static Image<TPixel> Decode<TPixel>(
this IImageDecoderInternals decoder, this IImageDecoderInternals decoder,
Configuration configuration, Configuration configuration,
Stream stream, Stream stream,
Func<InvalidMemoryOperationException, Size, InvalidImageContentException> largeImageExceptionFactory) Func<InvalidMemoryOperationException, Size, InvalidImageContentException> largeImageExceptionFactory,
CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using var bufferedReadStream = new BufferedReadStream(configuration, stream); using var bufferedReadStream = new BufferedReadStream(configuration, stream);
try try
{ {
return decoder.Decode<TPixel>(bufferedReadStream, default); return decoder.Decode<TPixel>(bufferedReadStream, cancellationToken);
} }
catch (InvalidMemoryOperationException ex) catch (InvalidMemoryOperationException ex)
{ {

12
src/ImageSharp/Formats/Jpeg/JpegDecoder.cs

@ -17,18 +17,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
public bool IgnoreMetadata { get; set; } public bool IgnoreMetadata { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
using var decoder = new JpegDecoderCore(configuration, this); using var decoder = new JpegDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
=> this.Decode<Rgb24>(configuration, stream); => this.Decode<Rgb24>(configuration, stream, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
@ -46,12 +46,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
.ConfigureAwait(false); .ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
using var decoder = new JpegDecoderCore(configuration, this); using var decoder = new JpegDecoderCore(configuration, this);
return decoder.Identify(configuration, stream); return decoder.Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

12
src/ImageSharp/Formats/Pbm/PbmDecoder.cs

@ -30,18 +30,18 @@ namespace SixLabors.ImageSharp.Formats.Pbm
public sealed class PbmDecoder : IImageDecoder, IImageInfoDetector public sealed class PbmDecoder : IImageDecoder, IImageInfoDetector
{ {
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
var decoder = new PbmDecoderCore(configuration); var decoder = new PbmDecoderCore(configuration);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
=> this.Decode<Rgb24>(configuration, stream); => this.Decode<Rgb24>(configuration, stream, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
@ -59,12 +59,12 @@ namespace SixLabors.ImageSharp.Formats.Pbm
.ConfigureAwait(false); .ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
var decoder = new PbmDecoderCore(configuration); var decoder = new PbmDecoderCore(configuration);
return decoder.Identify(configuration, stream); return decoder.Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

40
src/ImageSharp/Formats/Png/PngDecoder.cs

@ -17,18 +17,18 @@ namespace SixLabors.ImageSharp.Formats.Png
public bool IgnoreMetadata { get; set; } public bool IgnoreMetadata { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
PngDecoderCore decoder = new(configuration, this); PngDecoderCore decoder = new(configuration, this);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
PngDecoderCore decoder = new(configuration, true); PngDecoderCore decoder = new(configuration, true);
IImageInfo info = decoder.Identify(configuration, stream); IImageInfo info = decoder.Identify(configuration, stream, cancellationToken);
stream.Position = 0; stream.Position = 0;
PngMetadata meta = info.Metadata.GetPngMetadata(); PngMetadata meta = info.Metadata.GetPngMetadata();
@ -40,41 +40,41 @@ namespace SixLabors.ImageSharp.Formats.Png
if (bits == PngBitDepth.Bit16) if (bits == PngBitDepth.Bit16)
{ {
return !meta.HasTransparency return !meta.HasTransparency
? this.Decode<L16>(configuration, stream) ? this.Decode<L16>(configuration, stream, cancellationToken)
: this.Decode<La32>(configuration, stream); : this.Decode<La32>(configuration, stream, cancellationToken);
} }
return !meta.HasTransparency return !meta.HasTransparency
? this.Decode<L8>(configuration, stream) ? this.Decode<L8>(configuration, stream, cancellationToken)
: this.Decode<La16>(configuration, stream); : this.Decode<La16>(configuration, stream, cancellationToken);
case PngColorType.Rgb: case PngColorType.Rgb:
if (bits == PngBitDepth.Bit16) if (bits == PngBitDepth.Bit16)
{ {
return !meta.HasTransparency return !meta.HasTransparency
? this.Decode<Rgb48>(configuration, stream) ? this.Decode<Rgb48>(configuration, stream, cancellationToken)
: this.Decode<Rgba64>(configuration, stream); : this.Decode<Rgba64>(configuration, stream, cancellationToken);
} }
return !meta.HasTransparency return !meta.HasTransparency
? this.Decode<Rgb24>(configuration, stream) ? this.Decode<Rgb24>(configuration, stream, cancellationToken)
: this.Decode<Rgba32>(configuration, stream); : this.Decode<Rgba32>(configuration, stream, cancellationToken);
case PngColorType.Palette: case PngColorType.Palette:
return this.Decode<Rgba32>(configuration, stream); return this.Decode<Rgba32>(configuration, stream, cancellationToken);
case PngColorType.GrayscaleWithAlpha: case PngColorType.GrayscaleWithAlpha:
return (bits == PngBitDepth.Bit16) return (bits == PngBitDepth.Bit16)
? this.Decode<La32>(configuration, stream) ? this.Decode<La32>(configuration, stream, cancellationToken)
: this.Decode<La16>(configuration, stream); : this.Decode<La16>(configuration, stream, cancellationToken);
case PngColorType.RgbWithAlpha: case PngColorType.RgbWithAlpha:
return (bits == PngBitDepth.Bit16) return (bits == PngBitDepth.Bit16)
? this.Decode<Rgba64>(configuration, stream) ? this.Decode<Rgba64>(configuration, stream, cancellationToken)
: this.Decode<Rgba32>(configuration, stream); : this.Decode<Rgba32>(configuration, stream, cancellationToken);
default: default:
return this.Decode<Rgba32>(configuration, stream); return this.Decode<Rgba32>(configuration, stream, cancellationToken);
} }
} }
@ -141,10 +141,10 @@ namespace SixLabors.ImageSharp.Formats.Png
} }
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
PngDecoderCore decoder = new(configuration, this); PngDecoderCore decoder = new(configuration, this);
return decoder.Identify(configuration, stream); return decoder.Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

12
src/ImageSharp/Formats/Tga/TgaDecoder.cs

@ -16,18 +16,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
public sealed class TgaDecoder : IImageDecoder, ITgaDecoderOptions, IImageInfoDetector public sealed class TgaDecoder : IImageDecoder, ITgaDecoderOptions, IImageInfoDetector
{ {
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
var decoder = new TgaDecoderCore(configuration, this); var decoder = new TgaDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
=> this.Decode<Rgba32>(configuration, stream); => this.Decode<Rgba32>(configuration, stream, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
@ -45,11 +45,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
.ConfigureAwait(false); .ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
return new TgaDecoderCore(configuration, this).Identify(configuration, stream); return new TgaDecoderCore(configuration, this).Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

10
src/ImageSharp/Formats/Tiff/TiffDecoder.cs

@ -19,17 +19,17 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public bool IgnoreMetadata { get; set; } public bool IgnoreMetadata { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(stream, "stream"); Guard.NotNull(stream, "stream");
var decoder = new TiffDecoderCore(configuration, this); var decoder = new TiffDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
@ -47,12 +47,12 @@ namespace SixLabors.ImageSharp.Formats.Tiff
.ConfigureAwait(false); .ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
var decoder = new TiffDecoderCore(configuration, this); var decoder = new TiffDecoderCore(configuration, this);
return decoder.Identify(configuration, stream); return decoder.Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc/> /// <inheritdoc/>

10
src/ImageSharp/Formats/Webp/WebpDecoder.cs

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
public bool IgnoreMetadata { get; set; } public bool IgnoreMetadata { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
try try
{ {
return decoder.Decode<TPixel>(configuration, stream); return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
} }
catch (InvalidMemoryOperationException ex) catch (InvalidMemoryOperationException ex)
{ {
@ -41,15 +41,15 @@ namespace SixLabors.ImageSharp.Formats.Webp
} }
/// <inheritdoc/> /// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken = default)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
return new WebpDecoderCore(configuration, this).Identify(configuration, stream); return new WebpDecoderCore(configuration, this).Identify(configuration, stream, cancellationToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken = default) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
/// <inheritdoc /> /// <inheritdoc />
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)

14
src/ImageSharp/Image.Decode.cs

@ -148,11 +148,12 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
/// <param name="stream">The stream.</param> /// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param> /// <param name="config">the configuration.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns> /// <returns>
/// A new <see cref="Image{TPixel}"/>. /// A new <see cref="Image{TPixel}"/>.
/// </returns> /// </returns>
private static (Image<TPixel> Image, IImageFormat Format) Decode<TPixel>(Stream stream, Configuration config) private static (Image<TPixel> Image, IImageFormat Format) Decode<TPixel>(Stream stream, Configuration config, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
@ -161,7 +162,7 @@ namespace SixLabors.ImageSharp
return (null, null); return (null, null);
} }
Image<TPixel> img = decoder.Decode<TPixel>(config, stream); Image<TPixel> img = decoder.Decode<TPixel>(config, stream, cancellationToken);
return (img, format); return (img, format);
} }
@ -191,7 +192,7 @@ namespace SixLabors.ImageSharp
return (img, format); return (img, format);
} }
private static (Image Image, IImageFormat Format) Decode(Stream stream, Configuration config) private static (Image Image, IImageFormat Format) Decode(Stream stream, Configuration config, CancellationToken cancellationToken = default)
{ {
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
if (decoder is null) if (decoder is null)
@ -199,7 +200,7 @@ namespace SixLabors.ImageSharp
return (null, null); return (null, null);
} }
Image img = decoder.Decode(config, stream); Image img = decoder.Decode(config, stream, cancellationToken);
return (img, format); return (img, format);
} }
@ -220,10 +221,11 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
/// <param name="stream">The stream.</param> /// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param> /// <param name="config">the configuration.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns> /// <returns>
/// The <see cref="IImageInfo"/> or null if a suitable info detector is not found. /// The <see cref="IImageInfo"/> or null if a suitable info detector is not found.
/// </returns> /// </returns>
private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(Stream stream, Configuration config) private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(Stream stream, Configuration config, CancellationToken cancellationToken = default)
{ {
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
@ -232,7 +234,7 @@ namespace SixLabors.ImageSharp
return (null, null); return (null, null);
} }
IImageInfo info = detector?.Identify(config, stream); IImageInfo info = detector?.Identify(config, stream, cancellationToken);
return (info, format); return (info, format);
} }

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

@ -63,11 +63,11 @@ namespace SixLabors.ImageSharp.Tests
this.localImageFormatMock = new Mock<IImageFormat>(); this.localImageFormatMock = new Mock<IImageFormat>();
var detector = new Mock<IImageInfoDetector>(); var detector = new Mock<IImageInfoDetector>();
detector.Setup(x => x.Identify(It.IsAny<Configuration>(), It.IsAny<Stream>())).Returns(this.localImageInfoMock.Object); detector.Setup(x => x.Identify(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>())).Returns(this.localImageInfoMock.Object);
detector.Setup(x => x.IdentifyAsync(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>())).ReturnsAsync(this.localImageInfoMock.Object); detector.Setup(x => x.IdentifyAsync(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>())).ReturnsAsync(this.localImageInfoMock.Object);
this.localDecoder = detector.As<IImageDecoder>(); this.localDecoder = detector.As<IImageDecoder>();
this.localDecoder.Setup(x => x.Decode<Rgba32>(It.IsAny<Configuration>(), It.IsAny<Stream>())) this.localDecoder.Setup(x => x.Decode<Rgba32>(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.Callback<Configuration, Stream>((c, s) => .Callback<Configuration, Stream>((c, s) =>
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests
}) })
.Returns(this.localStreamReturnImageRgba32); .Returns(this.localStreamReturnImageRgba32);
this.localDecoder.Setup(x => x.Decode(It.IsAny<Configuration>(), It.IsAny<Stream>())) this.localDecoder.Setup(x => x.Decode(It.IsAny<Configuration>(), It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.Callback<Configuration, Stream>((c, s) => .Callback<Configuration, Stream>((c, s) =>
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())

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

@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); var img = Image.Load<Rgba32>(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object);
Assert.NotNull(img); Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(this.TopLevelConfiguration, this.DataStream)); this.localDecoder.Verify(x => x.Decode<Rgba32>(this.TopLevelConfiguration, this.DataStream, default));
} }
[Fact] [Fact]
@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests
var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object);
Assert.NotNull(img); Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, this.DataStream)); this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, this.DataStream, default));
} }
[Fact] [Fact]

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

@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Tests
var img = Image.Load<Rgba32>(this.TopLevelConfiguration, stream, this.localDecoder.Object); var img = Image.Load<Rgba32>(this.TopLevelConfiguration, stream, this.localDecoder.Object);
Assert.NotNull(img); Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(this.TopLevelConfiguration, stream)); this.localDecoder.Verify(x => x.Decode<Rgba32>(this.TopLevelConfiguration, stream, default));
} }
[Fact] [Fact]
@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests
var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object); var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object);
Assert.NotNull(img); Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, stream)); this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, stream, default));
} }
[Fact] [Fact]

10
tests/ImageSharp.Tests/TestFormat.cs

@ -212,9 +212,9 @@ namespace SixLabors.ImageSharp.Tests
public int HeaderSize => this.testFormat.HeaderSize; public int HeaderSize => this.testFormat.HeaderSize;
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
=> this.DecodeImpl<TPixel>(configuration, stream, default).GetAwaiter().GetResult(); => this.DecodeImpl<TPixel>(configuration, stream, cancellationToken).GetAwaiter().GetResult();
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
@ -239,13 +239,13 @@ namespace SixLabors.ImageSharp.Tests
public bool IsSupportedFileFormat(Span<byte> header) => this.testFormat.IsSupportedFileFormat(header); public bool IsSupportedFileFormat(Span<byte> header) => this.testFormat.IsSupportedFileFormat(header);
public Image Decode(Configuration configuration, Stream stream) => this.Decode<TestPixelForAgnosticDecode>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<TestPixelForAgnosticDecode>(configuration, stream, cancellationToken);
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<TestPixelForAgnosticDecode>(configuration, stream, cancellationToken); => await this.DecodeAsync<TestPixelForAgnosticDecode>(configuration, stream, cancellationToken);
public IImageInfo Identify(Configuration configuration, Stream stream) => public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) =>
this.IdentifyAsync(configuration, stream, default).GetAwaiter().GetResult(); this.IdentifyAsync(configuration, stream, cancellationToken).GetAwaiter().GetResult();
public async Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public async Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeImpl<Rgba32>(configuration, stream, cancellationToken); => await this.DecodeImpl<Rgba32>(configuration, stream, cancellationToken);

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

@ -61,9 +61,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel> where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
=> Task.FromResult(this.Decode<TPixel>(configuration, stream)); => Task.FromResult(this.Decode<TPixel>(configuration, stream, cancellationToken));
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel> where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel<TPixel>
{ {
var bmpReadDefines = new BmpReadDefines var bmpReadDefines = new BmpReadDefines
@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
return new Image<TPixel>(configuration, new ImageMetadata(), framesList); return new Image<TPixel>(configuration, new ImageMetadata(), framesList);
} }
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken); => await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken);

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

@ -17,9 +17,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
=> Task.FromResult(this.Decode<TPixel>(configuration, stream)); => Task.FromResult(this.Decode<TPixel>(configuration, stream, cancellationToken));
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (var sourceBitmap = new System.Drawing.Bitmap(stream)) using (var sourceBitmap = new System.Drawing.Bitmap(stream))
@ -50,9 +50,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
} }
public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> Task.FromResult(this.Identify(configuration, stream)); => Task.FromResult(this.Identify(configuration, stream, cancellationToken));
public IImageInfo Identify(Configuration configuration, Stream stream) public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken)
{ {
using (var sourceBitmap = new System.Drawing.Bitmap(stream)) using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{ {
@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
} }
} }
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken); => await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken);

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

@ -365,7 +365,7 @@ namespace SixLabors.ImageSharp.Tests
} }
} }
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
InvocationCounts[this.callerName]++; InvocationCounts[this.callerName]++;
@ -390,7 +390,7 @@ namespace SixLabors.ImageSharp.Tests
InvocationCountsAsync[name] = 0; InvocationCountsAsync[name] = 0;
} }
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken); => await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken);
@ -420,7 +420,7 @@ namespace SixLabors.ImageSharp.Tests
} }
} }
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
InvocationCounts[this.callerName]++; InvocationCounts[this.callerName]++;
@ -445,7 +445,7 @@ namespace SixLabors.ImageSharp.Tests
InvocationCountsAsync[name] = 0; InvocationCountsAsync[name] = 0;
} }
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) => this.Decode<Rgba32>(configuration, stream, cancellationToken);
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken); => await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken);

Loading…
Cancel
Save