-
-
Notifications
You must be signed in to change notification settings - Fork 888
Async APIs / Fake Async Codecs #1196
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
Changes from 17 commits
9bbd505
4d95e2e
dff8ab6
c69683e
2599275
ef3b71f
e643553
a27eb49
f7beaa1
2fc3058
740d133
6c18639
b505771
1969165
43b0d5e
84c7958
9bbf05d
1f74e31
6361a22
5a8f78a
b8232e4
c8c561b
72257ba
5d4a18f
73cc796
73fed79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| // Licensed under the GNU Affero General Public License, Version 3. | ||
|
|
||
| using System.IO; | ||
| using System.Threading.Tasks; | ||
| using SixLabors.ImageSharp.Memory; | ||
| using SixLabors.ImageSharp.PixelFormats; | ||
|
|
||
|
|
@@ -27,6 +28,26 @@ public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions, IImageInfoDe | |
| /// </summary> | ||
| public RleSkippedPixelHandling RleSkippedPixelHandling { get; set; } = RleSkippedPixelHandling.Black; | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| Guard.NotNull(stream, nameof(stream)); | ||
|
|
||
| var decoder = new BmpDecoderCore(configuration, this); | ||
|
|
||
| try | ||
| { | ||
| return await decoder.DecodeAsync<TPixel>(stream).ConfigureAwait(false); | ||
| } | ||
| catch (InvalidMemoryOperationException ex) | ||
| { | ||
| Size dims = decoder.Dimensions; | ||
|
|
||
| throw new InvalidImageContentException($"Can not decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}. This error can happen for very large RLE bitmaps, which are not supported.", ex); | ||
| } | ||
|
Comment on lines
+35
to
+48
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can DRY away these code duplications with the help of an
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I like this. Can come later though since everything is internal (unless someone is desperately keen to do it). |
||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
|
|
@@ -50,12 +71,23 @@ public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) | |
| /// <inheritdoc /> | ||
| public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream); | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<Image> DecodeAsync(Configuration configuration, Stream stream) => await this.DecodeAsync<Rgba32>(configuration, stream).ConfigureAwait(false); | ||
|
|
||
| /// <inheritdoc/> | ||
| public IImageInfo Identify(Configuration configuration, Stream stream) | ||
| { | ||
| Guard.NotNull(stream, nameof(stream)); | ||
|
|
||
| return new BmpDecoderCore(configuration, this).Identify(stream); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream) | ||
| { | ||
| Guard.NotNull(stream, nameof(stream)); | ||
|
|
||
| return await new BmpDecoderCore(configuration, this).IdentifyAsync(stream).ConfigureAwait(false); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| using System.IO; | ||
| using System.Numerics; | ||
| using System.Runtime.CompilerServices; | ||
| using System.Threading.Tasks; | ||
| using SixLabors.ImageSharp.Common.Helpers; | ||
| using SixLabors.ImageSharp.Memory; | ||
| using SixLabors.ImageSharp.Metadata; | ||
|
|
@@ -130,8 +131,40 @@ public BmpDecoderCore(Configuration configuration, IBmpDecoderOptions options) | |
| /// <para><paramref name="stream"/> is null.</para> | ||
| /// </exception> | ||
| /// <returns>The decoded image.</returns> | ||
| public Image<TPixel> Decode<TPixel>(Stream stream) | ||
| public async Task<Image<TPixel>> DecodeAsync<TPixel>(Stream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| // if we can seek then we arn't in a context that errors on async operations | ||
| if (stream.CanSeek) | ||
| { | ||
| return this.Decode<TPixel>(stream); | ||
| } | ||
| else | ||
| { | ||
| // cheat for now do async copy of the stream into memory stream and use the sync version | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I use a pool backed memory stream that allocates small chunks in .Web. Not sure how performant reading would be though.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is maybe RecyclableMemoryStream an option? Its meant to be a drop in replacement for
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to have a look at a read-only version of this less overhead and should support all out target frameworks.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Whichever we choose, I think it would make sense to integrate our adapted solution with |
||
| // we should use an array pool backed memorystream implementation | ||
| using (var ms = new MemoryStream()) | ||
| { | ||
| await stream.CopyToAsync(ms).ConfigureAwait(false); | ||
| ms.Position = 0; | ||
| return this.Decode<TPixel>(ms); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Decodes the image from the specified this._stream and sets | ||
| /// the data to image. | ||
| /// </summary> | ||
| /// <typeparam name="TPixel">The pixel format.</typeparam> | ||
| /// <param name="stream">The stream, where the image should be | ||
| /// decoded from. Cannot be null (Nothing in Visual Basic).</param> | ||
| /// <exception cref="System.ArgumentNullException"> | ||
| /// <para><paramref name="stream"/> is null.</para> | ||
| /// </exception> | ||
| /// <returns>The decoded image.</returns> | ||
| public Image<TPixel> Decode<TPixel>(Stream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| try | ||
| { | ||
|
|
@@ -218,6 +251,20 @@ public IImageInfo Identify(Stream stream) | |
| return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metadata); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Reads the raw image information from the specified stream. | ||
| /// </summary> | ||
| /// <param name="stream">The <see cref="Stream"/> containing image data.</param> | ||
| public async Task<IImageInfo> IdentifyAsync(Stream stream) | ||
| { | ||
| using (var ms = new MemoryStream()) | ||
| { | ||
| await stream.CopyToAsync(ms).ConfigureAwait(false); | ||
| ms.Position = 0; | ||
| return this.Identify(ms); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Returns the y- value based on the given height. | ||
| /// </summary> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.