Browse Source

cancellation support for encoders

pull/1296/head
Anton Firszov 6 years ago
parent
commit
874104ea13
  1. 6
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  2. 4
      src/ImageSharp/Advanced/IImageVisitor.cs
  3. 5
      src/ImageSharp/Formats/Bmp/BmpEncoder.cs
  4. 30
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  5. 5
      src/ImageSharp/Formats/Gif/GifEncoder.cs
  6. 23
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  7. 4
      src/ImageSharp/Formats/IImageEncoder.cs
  8. 25
      src/ImageSharp/Formats/IImageEncoderInternals.cs
  9. 43
      src/ImageSharp/Formats/ImageEncoderUtilities.cs
  10. 20
      src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
  11. 8
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  12. 6
      src/ImageSharp/Formats/Png/PngEncoder.cs
  13. 30
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  14. 5
      src/ImageSharp/Formats/Tga/TgaEncoder.cs
  15. 30
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
  16. 21
      src/ImageSharp/Image.cs
  17. 5
      src/ImageSharp/Image{TPixel}.cs
  18. 1
      tests/ImageSharp.Tests/Image/ImageTests.Identify.cs
  19. 2
      tests/ImageSharp.Tests/TestFormat.cs
  20. 3
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs

6
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
@ -73,9 +74,10 @@ namespace SixLabors.ImageSharp.Advanced
/// </summary>
/// <param name="source">The source image.</param>
/// <param name="visitor">The image visitor.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor)
=> source.AcceptAsync(visitor);
public static Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor, CancellationToken cancellationToken)
=> source.AcceptAsync(visitor, cancellationToken);
/// <summary>
/// Gets the configuration for the image.

4
src/ImageSharp/Advanced/IImageVisitor.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.PixelFormats;
@ -31,9 +32,10 @@ namespace SixLabors.ImageSharp.Advanced
/// Provides a pixel-specific implementation for a given operation.
/// </summary>
/// <param name="image">The image.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task VisitAsync<TPixel>(Image<TPixel> image)
Task VisitAsync<TPixel>(Image<TPixel> image, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>;
}
}

5
src/ImageSharp/Formats/Bmp/BmpEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -42,11 +43,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
}
/// <inheritdoc/>
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new BmpEncoderCore(this, image.GetMemoryAllocator());
return encoder.EncodeAsync(image, stream);
return encoder.EncodeAsync(image, stream, cancellationToken);
}
}
}

30
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Common.Helpers;
@ -19,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <summary>
/// Image encoder for writing an image to a stream as a Windows bitmap.
/// </summary>
internal sealed class BmpEncoderCore
internal sealed class BmpEncoderCore : IImageEncoderInternals
{
/// <summary>
/// The amount to pad each row by.
@ -97,32 +98,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
/// <param name="cancellationToken">The token to request cancellation.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
if (stream.CanSeek)
{
this.Encode(image, stream);
}
else
{
using (var ms = new MemoryStream())
{
this.Encode(image, ms);
ms.Position = 0;
await ms.CopyToAsync(stream).ConfigureAwait(false);
}
}
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="ImageFrame{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));

5
src/ImageSharp/Formats/Gif/GifEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -41,11 +42,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
/// <inheritdoc/>
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new GifEncoderCore(image.GetConfiguration(), this);
return encoder.EncodeAsync(image, stream);
return encoder.EncodeAsync(image, stream, cancellationToken);
}
}
}

23
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -6,6 +6,7 @@ using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
@ -18,7 +19,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Implements the GIF encoding protocol.
/// </summary>
internal sealed class GifEncoderCore
internal sealed class GifEncoderCore : IImageEncoderInternals
{
/// <summary>
/// Used for allocating memory during processing operations.
@ -75,25 +76,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
/// <param name="cancellationToken">The token to request cancellation.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var ms = new MemoryStream())
{
this.Encode(image, ms);
ms.Position = 0;
await ms.CopyToAsync(stream).ConfigureAwait(false);
}
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));

4
src/ImageSharp/Formats/IImageEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.PixelFormats;
@ -27,8 +28,9 @@ namespace SixLabors.ImageSharp.Formats
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>;
}
}

25
src/ImageSharp/Formats/IImageEncoderInternals.cs

@ -0,0 +1,25 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats
{
/// <summary>
/// Abstraction for shared internals for ***DecoderCore implementations to be used with <see cref="ImageEncoderUtilities"/>.
/// </summary>
internal interface IImageEncoderInternals
{
/// <summary>
/// Encodes the image.
/// </summary>
/// <param name="image">The image.</param>
/// <param name="stream">The stream.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <typeparam name="TPixel">The pixel type.</typeparam>
void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>;
}
}

43
src/ImageSharp/Formats/ImageEncoderUtilities.cs

@ -0,0 +1,43 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats
{
internal static class ImageEncoderUtilities
{
public static async Task EncodeAsync<TPixel>(
this IImageEncoderInternals encoder,
Image<TPixel> image,
Stream stream,
CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
Configuration configuration = image.GetConfiguration();
if (stream.CanSeek)
{
encoder.Encode(image, stream, cancellationToken);
}
else
{
using var ms = new MemoryStream();
encoder.Encode(image, ms, cancellationToken);
ms.Position = 0;
await ms.CopyToAsync(stream, configuration.StreamProcessingBufferSize, cancellationToken)
.ConfigureAwait(false);
}
}
public static void Encode<TPixel>(
this IImageEncoderInternals encoder,
Image<TPixel> image,
Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> encoder.Encode(image, stream, default);
}
}

20
src/ImageSharp/Formats/Jpeg/JpegEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.PixelFormats;
@ -43,26 +44,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new JpegEncoderCore(this);
if (stream.CanSeek)
{
encoder.Encode(image, stream);
}
else
{
// this hack has to be be here because JpegEncoderCore is unsafe
using (var ms = new MemoryStream())
{
encoder.Encode(image, ms);
ms.Position = 0;
await ms.CopyToAsync(stream).ConfigureAwait(false);
}
}
return encoder.EncodeAsync(image, stream, cancellationToken);
}
}
}

8
src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

@ -6,6 +6,7 @@ using System.Buffers.Binary;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
@ -23,7 +24,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <summary>
/// Image encoder for writing an image to a stream as a jpeg.
/// </summary>
internal sealed unsafe class JpegEncoderCore
internal sealed unsafe class JpegEncoderCore : IImageEncoderInternals
{
/// <summary>
/// The number of quantization tables.
@ -194,8 +195,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The image to write from.</param>
/// <param name="stream">The stream to write to.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
/// <param name="cancellationToken">The token to request cancellation.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));

6
src/ImageSharp/Formats/Png/PngEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -71,13 +72,14 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var encoder = new PngEncoderCore(image.GetMemoryAllocator(), image.GetConfiguration(), new PngEncoderOptions(this)))
{
await encoder.EncodeAsync(image, stream).ConfigureAwait(false);
await encoder.EncodeAsync(image, stream, cancellationToken).ConfigureAwait(false);
}
}
}

30
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -7,6 +7,7 @@ using System.Buffers.Binary;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Png.Chunks;
@ -21,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <summary>
/// Performs the png encoding operation.
/// </summary>
internal sealed class PngEncoderCore : IDisposable
internal sealed class PngEncoderCore : IImageEncoderInternals, IDisposable
{
/// <summary>
/// The maximum block size, defaults at 64k for uncompressed blocks.
@ -127,31 +128,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
if (stream.CanSeek)
{
this.Encode(image, stream);
}
else
{
using (var ms = new MemoryStream())
{
this.Encode(image, ms);
ms.Position = 0;
await ms.CopyToAsync(stream).ConfigureAwait(false);
}
}
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
/// <param name="cancellationToken">The token to request cancellation.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));

5
src/ImageSharp/Formats/Tga/TgaEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -32,11 +33,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
}
/// <inheritdoc/>
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new TgaEncoderCore(this, image.GetMemoryAllocator());
return encoder.EncodeAsync(image, stream);
return encoder.EncodeAsync(image, stream, cancellationToken);
}
}
}

30
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers.Binary;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <summary>
/// Image encoder for writing an image to a stream as a truevision targa image.
/// </summary>
internal sealed class TgaEncoderCore
internal sealed class TgaEncoderCore : IImageEncoderInternals
{
/// <summary>
/// Used for allocating memory during processing operations.
@ -61,31 +62,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
if (stream.CanSeek)
{
this.Encode(image, stream);
}
else
{
using (var ms = new MemoryStream())
{
this.Encode(image, ms);
ms.Position = 0;
await ms.CopyToAsync(stream).ConfigureAwait(false);
}
}
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="ImageFrame{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
/// <param name="cancellationToken">The token to request cancellation.</param>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));

21
src/ImageSharp/Image.cs

@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
@ -106,12 +107,23 @@ namespace SixLabors.ImageSharp
/// <exception cref="ArgumentNullException">Thrown if the stream or encoder is null.</exception>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public Task SaveAsync(Stream stream, IImageEncoder encoder)
=> this.SaveAsync(stream, encoder, default);
/// <summary>
/// Saves the image to the given stream using the given image encoder.
/// </summary>
/// <param name="stream">The stream to save the image to.</param>
/// <param name="encoder">The encoder to save the image with.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <exception cref="ArgumentNullException">Thrown if the stream or encoder is null.</exception>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public Task SaveAsync(Stream stream, IImageEncoder encoder, CancellationToken cancellationToken)
{
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder));
this.EnsureNotDisposed();
return this.AcceptVisitorAsync(new EncodeVisitor(encoder, stream));
return this.AcceptVisitorAsync(new EncodeVisitor(encoder, stream), cancellationToken);
}
/// <summary>
@ -162,7 +174,8 @@ namespace SixLabors.ImageSharp
/// with the pixel type of the image.
/// </summary>
/// <param name="visitor">The visitor.</param>
internal abstract Task AcceptAsync(IImageVisitorAsync visitor);
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
internal abstract Task AcceptAsync(IImageVisitorAsync visitor, CancellationToken cancellationToken);
private class EncodeVisitor : IImageVisitor, IImageVisitorAsync
{
@ -179,8 +192,8 @@ namespace SixLabors.ImageSharp
public void Visit<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel> => this.encoder.Encode(image, this.stream);
public Task VisitAsync<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel> => this.encoder.EncodeAsync(image, this.stream);
public Task VisitAsync<TPixel>(Image<TPixel> image, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> => this.encoder.EncodeAsync(image, this.stream, cancellationToken);
}
}
}

5
src/ImageSharp/Image{TPixel}.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
@ -290,11 +291,11 @@ namespace SixLabors.ImageSharp
}
/// <inheritdoc />
internal override Task AcceptAsync(IImageVisitorAsync visitor)
internal override Task AcceptAsync(IImageVisitorAsync visitor, CancellationToken cancellationToken)
{
this.EnsureNotDisposed();
return visitor.VisitAsync(this);
return visitor.VisitAsync(this, cancellationToken);
}
/// <summary>

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

@ -172,7 +172,6 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(ExpectedImageSize, info.Size());
}
[Fact]
public async Task FromStreamAsync_CustomConfiguration()
{

2
tests/ImageSharp.Tests/TestFormat.cs

@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp.Tests
// TODO record this happened so we can verify it.
}
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
// TODO record this happened so we can verify it.

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

@ -3,6 +3,7 @@
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
@ -31,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
}
}
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image))

Loading…
Cancel
Save