Browse Source

async await where required

pull/1574/head
James Jackson-South 6 years ago
parent
commit
dd9aa7908e
  1. 6
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  2. 4
      src/ImageSharp/Formats/Bmp/BmpEncoder.cs
  3. 4
      src/ImageSharp/Formats/Gif/GifEncoder.cs
  4. 4
      src/ImageSharp/Formats/Tga/TgaDecoder.cs
  5. 4
      src/ImageSharp/Formats/Tga/TgaEncoder.cs
  6. 11
      src/ImageSharp/Image.Decode.cs
  7. 67
      src/ImageSharp/Image.FromStream.cs
  8. 15
      src/ImageSharp/Image.cs

6
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -4,8 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
@ -76,8 +74,8 @@ namespace SixLabors.ImageSharp.Advanced
/// <param name="source">The source.</param> /// <param name="source">The source.</param>
/// <param name="visitor">The visitor.</param> /// <param name="visitor">The visitor.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor) public static async Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor)
=> source.AcceptAsync(visitor); => await source.AcceptAsync(visitor).ConfigureAwait(false);
/// <summary> /// <summary>
/// Gets the configuration for the image. /// Gets the configuration for the image.

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

@ -42,11 +42,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream) public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var encoder = new BmpEncoderCore(this, image.GetMemoryAllocator()); var encoder = new BmpEncoderCore(this, image.GetMemoryAllocator());
return encoder.EncodeAsync(image, stream); await encoder.EncodeAsync(image, stream).ConfigureAwait(false);
} }
} }
} }

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

@ -41,11 +41,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream) public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var encoder = new GifEncoderCore(image.GetConfiguration(), this); var encoder = new GifEncoderCore(image.GetConfiguration(), this);
return encoder.EncodeAsync(image, stream); await encoder.EncodeAsync(image, stream).ConfigureAwait(false);
} }
} }
} }

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

@ -74,11 +74,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream) public async Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
return new TgaDecoderCore(configuration, this).IdentifyAsync(stream); return await new TgaDecoderCore(configuration, this).IdentifyAsync(stream).ConfigureAwait(false);
} }
} }
} }

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

@ -32,11 +32,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream) public async Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var encoder = new TgaEncoderCore(this, image.GetMemoryAllocator()); var encoder = new TgaEncoderCore(this, image.GetMemoryAllocator());
return encoder.EncodeAsync(image, stream); await encoder.EncodeAsync(image, stream).ConfigureAwait(false);
} }
} }
} }

11
src/ImageSharp/Image.Decode.cs

@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp
/// <returns>The mime type or null if none found.</returns> /// <returns>The mime type or null if none found.</returns>
private static Task<IImageFormat> InternalDetectFormatAsync(Stream stream, Configuration config) private static Task<IImageFormat> 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 // seekable stream then we are free to use sync APIs this is potentially brittle and may
// need a better fix in the future. // need a better fix in the future.
return Task.FromResult(InternalDetectFormat(stream, config)); return Task.FromResult(InternalDetectFormat(stream, config));
@ -184,7 +184,7 @@ namespace SixLabors.ImageSharp
return (null, null); return (null, null);
} }
var info = detector?.Identify(config, stream); IImageInfo info = detector?.Identify(config, stream);
return new FormattedImageInfo(info, format); return new FormattedImageInfo(info, format);
} }
@ -203,7 +203,12 @@ namespace SixLabors.ImageSharp
return (null, null); 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); return new FormattedImageInfo(info, format);
} }
} }

67
src/ImageSharp/Image.FromStream.cs

@ -57,8 +57,12 @@ namespace SixLabors.ImageSharp
/// <exception cref="ArgumentNullException">The stream is null.</exception> /// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception> /// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <returns>The format type or null if none found.</returns> /// <returns>The format type or null if none found.</returns>
public static Task<IImageFormat> DetectFormatAsync(Configuration configuration, Stream stream) public static async Task<IImageFormat> DetectFormatAsync(Configuration configuration, Stream stream)
=> WithSeekableStreamAsync(configuration, stream, s => InternalDetectFormatAsync(s, configuration)); => await WithSeekableStreamAsync(
configuration,
stream,
async s => await InternalDetectFormatAsync(s, configuration).ConfigureAwait(false))
.ConfigureAwait(false);
/// <summary> /// <summary>
/// Reads the raw image information from the specified stream without fully decoding it. /// Reads the raw image information from the specified stream without fully decoding it.
@ -180,8 +184,12 @@ namespace SixLabors.ImageSharp
/// <returns> /// <returns>
/// The <see cref="FormattedImageInfo"/> with <see cref="FormattedImageInfo.ImageInfo"/> set to null if suitable info detector is not found. /// The <see cref="FormattedImageInfo"/> with <see cref="FormattedImageInfo.ImageInfo"/> set to null if suitable info detector is not found.
/// </returns> /// </returns>
public static Task<FormattedImageInfo> IdentifyWithFormatAsync(Configuration configuration, Stream stream) public static async Task<FormattedImageInfo> IdentifyWithFormatAsync(Configuration configuration, Stream stream)
=> WithSeekableStreamAsync(configuration, stream, s => InternalIdentityAsync(s, configuration ?? Configuration.Default)); => await WithSeekableStreamAsync(
configuration,
stream,
async s => await InternalIdentityAsync(s, configuration ?? Configuration.Default))
.ConfigureAwait(false);
/// <summary> /// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream. /// Decode a new instance of the <see cref="Image"/> class from the given stream.
@ -330,7 +338,7 @@ namespace SixLabors.ImageSharp
/// <returns>A new <see cref="Image"/>.</returns>> /// <returns>A new <see cref="Image"/>.</returns>>
public static async Task<Image> LoadAsync(Configuration configuration, Stream stream) public static async Task<Image> LoadAsync(Configuration configuration, Stream stream)
{ {
var fmt = await LoadWithFormatAsync(configuration, stream).ConfigureAwait(false); FormattedImage fmt = await LoadWithFormatAsync(configuration, stream).ConfigureAwait(false);
return fmt.Image; return fmt.Image;
} }
@ -387,9 +395,9 @@ namespace SixLabors.ImageSharp
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception> /// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static Task<FormattedImage<TPixel>> LoadWithFormatAsync<TPixel>(Stream stream) public static async Task<FormattedImage<TPixel>> LoadWithFormatAsync<TPixel>(Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
=> LoadWithFormatAsync<TPixel>(Configuration.Default, stream); => await LoadWithFormatAsync<TPixel>(Configuration.Default, stream).ConfigureAwait(false);
/// <summary> /// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream. /// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@ -417,9 +425,13 @@ namespace SixLabors.ImageSharp
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception> /// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>> /// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, IImageDecoder decoder) public static async Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
=> WithSeekableStreamAsync(Configuration.Default, stream, s => decoder.DecodeAsync<TPixel>(Configuration.Default, s)); => await WithSeekableStreamAsync(
Configuration.Default,
stream,
async s => await decoder.DecodeAsync<TPixel>(Configuration.Default, s).ConfigureAwait(false))
.ConfigureAwait(false);
/// <summary> /// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream. /// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@ -451,9 +463,13 @@ namespace SixLabors.ImageSharp
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception> /// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>> /// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder) public static async Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
=> WithSeekableStreamAsync(configuration, stream, s => decoder.DecodeAsync<TPixel>(configuration, s)); => await WithSeekableStreamAsync(
configuration,
stream,
async s => await decoder.DecodeAsync<TPixel>(configuration, s).ConfigureAwait(false))
.ConfigureAwait(false);
/// <summary> /// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream. /// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@ -520,7 +536,11 @@ namespace SixLabors.ImageSharp
/// <returns>A new <see cref="Image{TPixel}"/>.</returns> /// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static async Task<FormattedImage> LoadWithFormatAsync(Configuration configuration, Stream stream) public static async Task<FormattedImage> 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) if (data.img != null)
{ {
@ -553,7 +573,12 @@ namespace SixLabors.ImageSharp
public static async Task<FormattedImage<TPixel>> LoadWithFormatAsync<TPixel>(Configuration configuration, Stream stream) public static async Task<FormattedImage<TPixel>> LoadWithFormatAsync<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
(Image<TPixel> img, IImageFormat format) data = await WithSeekableStreamAsync(configuration, stream, s => DecodeAsync<TPixel>(s, configuration)); (Image<TPixel> img, IImageFormat format) data =
await WithSeekableStreamAsync(
configuration,
stream,
async s => await DecodeAsync<TPixel>(s, configuration).ConfigureAwait(false))
.ConfigureAwait(false);
if (data.img != null) 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 // 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()) using (var memoryStream = new MemoryStream())
{ {
stream.CopyTo(memoryStream); stream.CopyTo(memoryStream);
@ -655,7 +683,10 @@ namespace SixLabors.ImageSharp
} }
} }
private static async Task<T> WithSeekableStreamAsync<T>(Configuration configuration, Stream stream, Func<Stream, Task<T>> action) private static async Task<T> WithSeekableStreamAsync<T>(
Configuration configuration,
Stream stream,
Func<Stream, Task<T>> action)
{ {
Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
@ -665,8 +696,9 @@ namespace SixLabors.ImageSharp
throw new NotSupportedException("Cannot read from the stream."); 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 // To make sure we don't trigger anything with aspnetcore then we just need to make sure we are
// 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 // 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 // having to further wrap
if (stream.CanSeek) if (stream.CanSeek)
{ {
@ -678,7 +710,8 @@ namespace SixLabors.ImageSharp
return await action(stream).ConfigureAwait(false); 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); await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
memoryStream.Position = 0; memoryStream.Position = 0;

15
src/ImageSharp/Image.cs

@ -105,13 +105,13 @@ namespace SixLabors.ImageSharp
/// <param name="encoder">The encoder to save the image with.</param> /// <param name="encoder">The encoder to save the image with.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream or encoder is null.</exception> /// <exception cref="System.ArgumentNullException">Thrown if the stream or encoder is null.</exception>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public Task SaveAsync(Stream stream, IImageEncoder encoder) public async Task SaveAsync(Stream stream, IImageEncoder encoder)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder)); Guard.NotNull(encoder, nameof(encoder));
this.EnsureNotDisposed(); this.EnsureNotDisposed();
return this.AcceptVisitorAsync(new EncodeVisitor(encoder, stream)); await this.AcceptVisitorAsync(new EncodeVisitor(encoder, stream)).ConfigureAwait(false);
} }
/// <summary> /// <summary>
@ -177,16 +177,11 @@ namespace SixLabors.ImageSharp
} }
public void Visit<TPixel>(Image<TPixel> image) public void Visit<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel> => this.encoder.Encode(image, this.stream);
{
this.encoder.Encode(image, this.stream);
}
public Task VisitAsync<TPixel>(Image<TPixel> image) public async Task VisitAsync<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ => await this.encoder.EncodeAsync(image, this.stream).ConfigureAwait(false);
return this.encoder.EncodeAsync(image, this.stream).ConfigureAwait(false);
}
} }
} }
} }

Loading…
Cancel
Save