diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index e3a5938e2..185ac9cc4 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using SixLabors.ImageSharp.Formats; @@ -76,8 +74,8 @@ namespace SixLabors.ImageSharp.Advanced /// The source. /// The visitor. /// A representing the asynchronous operation. - public static Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor) - => source.AcceptAsync(visitor); + public static async Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor) + => await source.AcceptAsync(visitor).ConfigureAwait(false); /// /// Gets the configuration for the image. diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs index 52b87ef27..70023ffc1 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs @@ -42,11 +42,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - public Task EncodeAsync(Image image, Stream stream) + public async Task EncodeAsync(Image image, Stream stream) where TPixel : unmanaged, IPixel { var encoder = new BmpEncoderCore(this, image.GetMemoryAllocator()); - return encoder.EncodeAsync(image, stream); + await encoder.EncodeAsync(image, stream).ConfigureAwait(false); } } } diff --git a/src/ImageSharp/Formats/Gif/GifEncoder.cs b/src/ImageSharp/Formats/Gif/GifEncoder.cs index 8d4c33eff..78e78a81f 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoder.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoder.cs @@ -41,11 +41,11 @@ namespace SixLabors.ImageSharp.Formats.Gif } /// - public Task EncodeAsync(Image image, Stream stream) + public async Task EncodeAsync(Image image, Stream stream) where TPixel : unmanaged, IPixel { var encoder = new GifEncoderCore(image.GetConfiguration(), this); - return encoder.EncodeAsync(image, stream); + await encoder.EncodeAsync(image, stream).ConfigureAwait(false); } } } diff --git a/src/ImageSharp/Formats/Tga/TgaDecoder.cs b/src/ImageSharp/Formats/Tga/TgaDecoder.cs index 5cd7ca7b0..f977623f4 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoder.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoder.cs @@ -74,11 +74,11 @@ namespace SixLabors.ImageSharp.Formats.Tga } /// - public Task IdentifyAsync(Configuration configuration, Stream stream) + public async Task IdentifyAsync(Configuration configuration, Stream stream) { Guard.NotNull(stream, nameof(stream)); - return new TgaDecoderCore(configuration, this).IdentifyAsync(stream); + return await new TgaDecoderCore(configuration, this).IdentifyAsync(stream).ConfigureAwait(false); } } } diff --git a/src/ImageSharp/Formats/Tga/TgaEncoder.cs b/src/ImageSharp/Formats/Tga/TgaEncoder.cs index 058dd3559..449a724bf 100644 --- a/src/ImageSharp/Formats/Tga/TgaEncoder.cs +++ b/src/ImageSharp/Formats/Tga/TgaEncoder.cs @@ -32,11 +32,11 @@ namespace SixLabors.ImageSharp.Formats.Tga } /// - public Task EncodeAsync(Image image, Stream stream) + public async Task EncodeAsync(Image image, Stream stream) where TPixel : unmanaged, IPixel { var encoder = new TgaEncoderCore(this, image.GetMemoryAllocator()); - return encoder.EncodeAsync(image, stream); + await encoder.EncodeAsync(image, stream).ConfigureAwait(false); } } } diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 1adcc4a79..9623e6e43 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp /// The mime type or null if none found. private static Task InternalDetectFormatAsync(Stream stream, Configuration config) { - // we are going to cheat here because we know that by this point we have been wrapped in a + // We are going to cheat here because we know that by this point we have been wrapped in a // seekable stream then we are free to use sync APIs this is potentially brittle and may // need a better fix in the future. return Task.FromResult(InternalDetectFormat(stream, config)); @@ -184,7 +184,7 @@ namespace SixLabors.ImageSharp return (null, null); } - var info = detector?.Identify(config, stream); + IImageInfo info = detector?.Identify(config, stream); return new FormattedImageInfo(info, format); } @@ -203,7 +203,12 @@ namespace SixLabors.ImageSharp return (null, null); } - var info = await detector?.IdentifyAsync(config, stream); + if (detector is null) + { + return (null, format); + } + + IImageInfo info = await detector.IdentifyAsync(config, stream).ConfigureAwait(false); return new FormattedImageInfo(info, format); } } diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index cdd44a4fd..bb36b1462 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -57,8 +57,12 @@ namespace SixLabors.ImageSharp /// The stream is null. /// The stream is not readable. /// The format type or null if none found. - public static Task DetectFormatAsync(Configuration configuration, Stream stream) - => WithSeekableStreamAsync(configuration, stream, s => InternalDetectFormatAsync(s, configuration)); + public static async Task DetectFormatAsync(Configuration configuration, Stream stream) + => await WithSeekableStreamAsync( + configuration, + stream, + async s => await InternalDetectFormatAsync(s, configuration).ConfigureAwait(false)) + .ConfigureAwait(false); /// /// Reads the raw image information from the specified stream without fully decoding it. @@ -180,8 +184,12 @@ namespace SixLabors.ImageSharp /// /// The with set to null if suitable info detector is not found. /// - public static Task IdentifyWithFormatAsync(Configuration configuration, Stream stream) - => WithSeekableStreamAsync(configuration, stream, s => InternalIdentityAsync(s, configuration ?? Configuration.Default)); + public static async Task IdentifyWithFormatAsync(Configuration configuration, Stream stream) + => await WithSeekableStreamAsync( + configuration, + stream, + async s => await InternalIdentityAsync(s, configuration ?? Configuration.Default)) + .ConfigureAwait(false); /// /// Decode a new instance of the class from the given stream. @@ -330,7 +338,7 @@ namespace SixLabors.ImageSharp /// A new .> public static async Task LoadAsync(Configuration configuration, Stream stream) { - var fmt = await LoadWithFormatAsync(configuration, stream).ConfigureAwait(false); + FormattedImage fmt = await LoadWithFormatAsync(configuration, stream).ConfigureAwait(false); return fmt.Image; } @@ -387,9 +395,9 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static Task> LoadWithFormatAsync(Stream stream) + public static async Task> LoadWithFormatAsync(Stream stream) where TPixel : unmanaged, IPixel - => LoadWithFormatAsync(Configuration.Default, stream); + => await LoadWithFormatAsync(Configuration.Default, stream).ConfigureAwait(false); /// /// Create a new instance of the class from the given stream. @@ -417,9 +425,13 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// The pixel format. /// A new .> - public static Task> LoadAsync(Stream stream, IImageDecoder decoder) + public static async Task> LoadAsync(Stream stream, IImageDecoder decoder) where TPixel : unmanaged, IPixel - => WithSeekableStreamAsync(Configuration.Default, stream, s => decoder.DecodeAsync(Configuration.Default, s)); + => await WithSeekableStreamAsync( + Configuration.Default, + stream, + async s => await decoder.DecodeAsync(Configuration.Default, s).ConfigureAwait(false)) + .ConfigureAwait(false); /// /// Create a new instance of the class from the given stream. @@ -451,9 +463,13 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// The pixel format. /// A new .> - public static Task> LoadAsync(Configuration configuration, Stream stream, IImageDecoder decoder) + public static async Task> LoadAsync(Configuration configuration, Stream stream, IImageDecoder decoder) where TPixel : unmanaged, IPixel - => WithSeekableStreamAsync(configuration, stream, s => decoder.DecodeAsync(configuration, s)); + => await WithSeekableStreamAsync( + configuration, + stream, + async s => await decoder.DecodeAsync(configuration, s).ConfigureAwait(false)) + .ConfigureAwait(false); /// /// Create a new instance of the class from the given stream. @@ -520,7 +536,11 @@ namespace SixLabors.ImageSharp /// A new . public static async Task LoadWithFormatAsync(Configuration configuration, Stream stream) { - (Image img, IImageFormat format) data = await WithSeekableStreamAsync(configuration, stream, s => DecodeAsync(s, configuration)); + (Image img, IImageFormat format) data = await WithSeekableStreamAsync( + configuration, + stream, + async s => await DecodeAsync(s, configuration).ConfigureAwait(false)) + .ConfigureAwait(false); if (data.img != null) { @@ -553,7 +573,12 @@ namespace SixLabors.ImageSharp public static async Task> LoadWithFormatAsync(Configuration configuration, Stream stream) where TPixel : unmanaged, IPixel { - (Image img, IImageFormat format) data = await WithSeekableStreamAsync(configuration, stream, s => DecodeAsync(s, configuration)); + (Image img, IImageFormat format) data = + await WithSeekableStreamAsync( + configuration, + stream, + async s => await DecodeAsync(s, configuration).ConfigureAwait(false)) + .ConfigureAwait(false); if (data.img != null) { @@ -646,6 +671,9 @@ namespace SixLabors.ImageSharp } // We want to be able to load images from things like HttpContext.Request.Body + // TODO: Should really find a nice way to use a pool for these. + // Investigate readonly version of the linked implementation. + // https://github.com/mgravell/Pipelines.Sockets.Unofficial/compare/mgravell:24482d4...mgravell:6740ea4 using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); @@ -655,7 +683,10 @@ namespace SixLabors.ImageSharp } } - private static async Task WithSeekableStreamAsync(Configuration configuration, Stream stream, Func> action) + private static async Task WithSeekableStreamAsync( + Configuration configuration, + Stream stream, + Func> action) { Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(stream, nameof(stream)); @@ -665,8 +696,9 @@ namespace SixLabors.ImageSharp throw new NotSupportedException("Cannot read from the stream."); } - // to make sure we don't trigger anything with aspnetcore then we just need to make sure we are seekable and we make the copy using CopyToAsync - // if the stream is seekable then we arn't using one of the aspnetcore wrapped streams that error on sync api calls and we can use it with out + // To make sure we don't trigger anything with aspnetcore then we just need to make sure we are + // seekable and we make the copy using CopyToAsync if the stream is seekable then we arn't using + // one of the aspnetcore wrapped streams that error on sync api calls and we can use it without // having to further wrap if (stream.CanSeek) { @@ -678,7 +710,8 @@ namespace SixLabors.ImageSharp return await action(stream).ConfigureAwait(false); } - using (var memoryStream = new MemoryStream()) // should really find a nice way to use a pool for these!! + // TODO: See above comment. + using (var memoryStream = new MemoryStream()) { await stream.CopyToAsync(memoryStream).ConfigureAwait(false); memoryStream.Position = 0; diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index fd2fb1f87..167847360 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -105,13 +105,13 @@ namespace SixLabors.ImageSharp /// The encoder to save the image with. /// Thrown if the stream or encoder is null. /// A representing the asynchronous operation. - public Task SaveAsync(Stream stream, IImageEncoder encoder) + public async Task SaveAsync(Stream stream, IImageEncoder encoder) { Guard.NotNull(stream, nameof(stream)); Guard.NotNull(encoder, nameof(encoder)); this.EnsureNotDisposed(); - return this.AcceptVisitorAsync(new EncodeVisitor(encoder, stream)); + await this.AcceptVisitorAsync(new EncodeVisitor(encoder, stream)).ConfigureAwait(false); } /// @@ -177,16 +177,11 @@ namespace SixLabors.ImageSharp } public void Visit(Image image) - where TPixel : unmanaged, IPixel - { - this.encoder.Encode(image, this.stream); - } + where TPixel : unmanaged, IPixel => this.encoder.Encode(image, this.stream); - public Task VisitAsync(Image image) + public async Task VisitAsync(Image image) where TPixel : unmanaged, IPixel - { - return this.encoder.EncodeAsync(image, this.stream).ConfigureAwait(false); - } + => await this.encoder.EncodeAsync(image, this.stream).ConfigureAwait(false); } } }