Skip to content

Fix async image load #2006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4802b4f
Always pre-copy the source stream into an in-memory stream so that th…
kroymann Feb 15, 2022
3a11b2f
Plumb CancellationToken through IImageDecoder and IImageInfoDetector …
kroymann Feb 16, 2022
f874218
Change WithSeekableStreamAsync() so that it executes synchronous acti…
kroymann Feb 16, 2022
eb7b9d9
Remove IImageDecoder.DecodeAsync() and IImageInfoDetector.IdentifyAsy…
kroymann Feb 16, 2022
66dc526
Merge branch 'main' into fix-async-image-load
antonfirsov Feb 16, 2022
fdc9d82
Merge branch 'fix-async-image-load' of https://github.com/kroymann/Im…
kroymann Feb 16, 2022
1c225e9
Make the cancellationToken arguments required
kroymann Feb 16, 2022
840bf82
Restore mistakenly deleted logic for resetting stream position
kroymann Feb 17, 2022
6ed13c3
Fix a bug in LoadAsync(filePath) where the FileStream was being dispo…
kroymann Feb 17, 2022
2ee0c6e
Fix unit tests
kroymann Feb 17, 2022
9f4223d
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Feb 22, 2022
2474aab
Cleanup and normalization
JimBobSquarePants Feb 22, 2022
84a639b
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Feb 22, 2022
95cdd1c
Fix build
JimBobSquarePants Feb 22, 2022
fd4e3a5
Scale allocated chunk sizes to match allocations
JimBobSquarePants Feb 24, 2022
d245a81
Merge remote-tracking branch 'upstream/main' into fix-async-image-load
JimBobSquarePants Feb 28, 2022
226953b
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Feb 28, 2022
77e3986
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Mar 7, 2022
ac1e663
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Mar 8, 2022
2745cf8
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Mar 8, 2022
b54db18
Merge branch 'main' into fix-async-image-load
JimBobSquarePants Mar 13, 2022
faea7d0
AsyncImageSharp option for load testing
antonfirsov Mar 13, 2022
1ad9e56
Use graduated buffers
JimBobSquarePants Mar 14, 2022
e554dca
Update src/ImageSharp/IO/ChunkedMemoryStream.cs
JimBobSquarePants Mar 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/ImageSharp/Advanced/AotCompilerTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,7 @@ private static void AotCompileImageDecoder<TPixel, TDecoder>()
where TPixel : unmanaged, IPixel<TPixel>
where TDecoder : class, IImageDecoder
{
default(TDecoder).Decode<TPixel>(default, default);
default(TDecoder).DecodeAsync<TPixel>(default, default, default);
default(TDecoder).Decode<TPixel>(default, default, default);
}

/// <summary>
Expand Down
38 changes: 6 additions & 32 deletions src/ImageSharp/Formats/Bmp/BmpDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;

namespace SixLabors.ImageSharp.Formats.Bmp
Expand All @@ -31,48 +28,25 @@ public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions, IImageInfoDe
public RleSkippedPixelHandling RleSkippedPixelHandling { get; set; } = RleSkippedPixelHandling.Black;

/// <inheritdoc/>
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>
{
Guard.NotNull(stream, nameof(stream));

var decoder = new BmpDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream);
return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
}

/// <inheritdoc />
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);

/// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(stream, nameof(stream));

var decoder = new BmpDecoderCore(configuration, this);
return decoder.DecodeAsync<TPixel>(configuration, stream, cancellationToken);
}

/// <inheritdoc />
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken)
.ConfigureAwait(false);

/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, nameof(stream));

return new BmpDecoderCore(configuration, this).Identify(configuration, stream);
}

/// <inheritdoc/>
public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(stream, nameof(stream));

return new BmpDecoderCore(configuration, this).IdentifyAsync(configuration, stream, cancellationToken);
return new BmpDecoderCore(configuration, this).Identify(configuration, stream, cancellationToken);
}
}
}
38 changes: 6 additions & 32 deletions src/ImageSharp/Formats/Gif/GifDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;

Expand All @@ -26,48 +24,24 @@ public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions, IImageInfoDe
public FrameDecodingMode DecodingMode { get; set; } = FrameDecodingMode.All;

/// <inheritdoc/>
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>
{
var decoder = new GifDecoderCore(configuration, this);
return decoder.Decode<TPixel>(configuration, stream);
return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
}

/// <inheritdoc />
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);

/// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new GifDecoderCore(configuration, this);
return decoder.DecodeAsync<TPixel>(configuration, stream, cancellationToken);
}

/// <inheritdoc />
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken)
.ConfigureAwait(false);

/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, nameof(stream));

var decoder = new GifDecoderCore(configuration, this);

using var bufferedStream = new BufferedReadStream(configuration, stream);
return decoder.Identify(bufferedStream, default);
}

/// <inheritdoc/>
public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(stream, nameof(stream));

var decoder = new GifDecoderCore(configuration, this);
return decoder.IdentifyAsync(configuration, stream, cancellationToken);
return decoder.Identify(configuration, stream, cancellationToken);
}
}
}
25 changes: 2 additions & 23 deletions src/ImageSharp/Formats/IImageDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.PixelFormats;

namespace SixLabors.ImageSharp.Formats
Expand All @@ -13,26 +12,6 @@ namespace SixLabors.ImageSharp.Formats
/// </summary>
public interface IImageDecoder
{
/// <summary>
/// Decodes the image from the specified stream to an <see cref="Image{TPixel}"/> of a specific pixel type.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
// TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110)
Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>;

/// <summary>
/// Decodes the image from the specified stream to an <see cref="Image"/>.
/// </summary>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The <see cref="Image"/>.</returns>
// TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110)
Image Decode(Configuration configuration, Stream stream);

/// <summary>
/// Decodes the image from the specified stream to an <see cref="Image{TPixel}"/> of a specific pixel type.
/// </summary>
Expand All @@ -42,7 +21,7 @@ Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
// TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110)
Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>;

/// <summary>
Expand All @@ -53,6 +32,6 @@ Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stre
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>The <see cref="Image"/>.</returns>
// TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110)
Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken);
Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken);
}
}
11 changes: 1 addition & 10 deletions src/ImageSharp/Formats/IImageInfoDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace SixLabors.ImageSharp.Formats
{
Expand All @@ -12,21 +11,13 @@ namespace SixLabors.ImageSharp.Formats
/// </summary>
public interface IImageInfoDetector
{
/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The <see cref="PixelTypeInfo"/> object</returns>
IImageInfo Identify(Configuration configuration, Stream stream);

/// <summary>
/// Reads the raw image information from the specified stream.
/// </summary>
/// <param name="configuration">The configuration for the image.</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>
Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken);
IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken);
}
}
Loading