|
|
|
@ -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; |
|
|
|
@ -62,7 +63,8 @@ namespace SixLabors.ImageSharp |
|
|
|
=> WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
s => InternalDetectFormatAsync(s, configuration)); |
|
|
|
(s, _) => InternalDetectFormatAsync(s, configuration), |
|
|
|
default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Reads the raw image information from the specified stream without fully decoding it.
|
|
|
|
@ -192,7 +194,29 @@ namespace SixLabors.ImageSharp |
|
|
|
=> WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
s => InternalIdentityAsync(s, configuration ?? Configuration.Default)); |
|
|
|
(s, ct) => InternalIdentityAsync(s, configuration ?? Configuration.Default, ct), |
|
|
|
default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Reads the raw image information from the specified stream without fully decoding it.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The configuration.</param>
|
|
|
|
/// <param name="stream">The image stream to read the information from.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <returns>
|
|
|
|
/// The <see cref="Task{ValueTuple}"/> representing the asyncronous operation with the parameter type
|
|
|
|
/// <see cref="IImageInfo"/> property set to null if suitable info detector is not found.
|
|
|
|
/// </returns>
|
|
|
|
public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
=> WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
(s, ct) => InternalIdentityAsync(s, configuration ?? Configuration.Default, ct), |
|
|
|
cancellationToken); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
|
|
|
|
@ -310,12 +334,31 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static Task<Image> LoadAsync(Configuration configuration, Stream stream, IImageDecoder decoder) |
|
|
|
=> LoadAsync(configuration, stream, decoder, default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
|
|
|
|
/// The pixel format is selected by the decoder.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The configuration for the decoder.</param>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="decoder">The decoder.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static Task<Image> LoadAsync(Configuration configuration, Stream stream, IImageDecoder decoder, CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
Guard.NotNull(decoder, nameof(decoder)); |
|
|
|
return WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
s => decoder.DecodeAsync(configuration, s)); |
|
|
|
(s, ct) => decoder.DecodeAsync(configuration, s), |
|
|
|
cancellationToken); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -348,6 +391,25 @@ namespace SixLabors.ImageSharp |
|
|
|
return fmt.Image; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The configuration for the decoder.</param>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<Image> LoadAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
(Image Image, IImageFormat Format) fmt = await LoadWithFormatAsync(configuration, stream, cancellationToken) |
|
|
|
.ConfigureAwait(false); |
|
|
|
return fmt.Image; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
@ -432,11 +494,28 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, IImageDecoder decoder) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
=> LoadAsync<TPixel>(stream, decoder, default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="decoder">The decoder.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, IImageDecoder decoder, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
=> WithSeekableStreamAsync( |
|
|
|
Configuration.Default, |
|
|
|
stream, |
|
|
|
s => decoder.DecodeAsync<TPixel>(Configuration.Default, s)); |
|
|
|
(s, ct) => decoder.DecodeAsync<TPixel>(Configuration.Default, s), |
|
|
|
cancellationToken); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
@ -468,12 +547,38 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
public static Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder) |
|
|
|
public static Task<Image<TPixel>> LoadAsync<TPixel>( |
|
|
|
Configuration configuration, |
|
|
|
Stream stream, |
|
|
|
IImageDecoder decoder) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
=> LoadAsync<TPixel>(configuration, stream, decoder, default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The Configuration.</param>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="decoder">The decoder.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
public static Task<Image<TPixel>> LoadAsync<TPixel>( |
|
|
|
Configuration configuration, |
|
|
|
Stream stream, |
|
|
|
IImageDecoder decoder, |
|
|
|
CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
=> WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
s => decoder.DecodeAsync<TPixel>(configuration, s)); |
|
|
|
(s, ct) => decoder.DecodeAsync<TPixel>(configuration, s), |
|
|
|
cancellationToken); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
@ -538,12 +643,30 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Configuration configuration, Stream stream) |
|
|
|
public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync( |
|
|
|
Configuration configuration, |
|
|
|
Stream stream) |
|
|
|
=> LoadWithFormatAsync(configuration, stream, default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The configuration options.</param>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
(Image Image, IImageFormat Format) data = await WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
async s => await DecodeAsync(s, configuration).ConfigureAwait(false)) |
|
|
|
async (s, ct) => await DecodeAsync(s, configuration, ct).ConfigureAwait(false), |
|
|
|
cancellationToken) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
if (data.Image != null) |
|
|
|
@ -574,14 +697,33 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<(Image<TPixel> Image, IImageFormat Format)> LoadWithFormatAsync<TPixel>(Configuration configuration, Stream stream) |
|
|
|
public static Task<(Image<TPixel> Image, IImageFormat Format)> LoadWithFormatAsync<TPixel>( |
|
|
|
Configuration configuration, Stream stream) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
=> LoadWithFormatAsync<TPixel>(configuration, stream, default); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The configuration options.</param>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<(Image<TPixel> Image, IImageFormat Format)> LoadWithFormatAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
(Image<TPixel> Image, IImageFormat Format) data = |
|
|
|
await WithSeekableStreamAsync( |
|
|
|
configuration, |
|
|
|
stream, |
|
|
|
s => DecodeAsync<TPixel>(s, configuration)) |
|
|
|
(s, ct) => DecodeAsync<TPixel>(s, configuration, ct), |
|
|
|
cancellationToken) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
if (data.Image != null) |
|
|
|
@ -612,10 +754,28 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream) |
|
|
|
public static Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
=> LoadAsync<TPixel>(configuration, stream, default(CancellationToken)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="configuration">The configuration options.</param>
|
|
|
|
/// <param name="stream">The stream containing image information.</param>
|
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|
|
|
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
|
|
|
|
/// <exception cref="ArgumentNullException">The stream is null.</exception>
|
|
|
|
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
|
|
|
|
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
|
|
|
|
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
public static async Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
(Image<TPixel> img, _) = await LoadWithFormatAsync<TPixel>(configuration, stream).ConfigureAwait(false); |
|
|
|
(Image<TPixel> img, _) = await LoadWithFormatAsync<TPixel>(configuration, stream, cancellationToken) |
|
|
|
.ConfigureAwait(false); |
|
|
|
return img; |
|
|
|
} |
|
|
|
|
|
|
|
@ -700,11 +860,13 @@ namespace SixLabors.ImageSharp |
|
|
|
/// <param name="configuration">The configuration.</param>
|
|
|
|
/// <param name="stream">The input stream.</param>
|
|
|
|
/// <param name="action">The action to perform.</param>
|
|
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
|
|
/// <returns>The <see cref="Task{T}"/>.</returns>
|
|
|
|
private static async Task<T> WithSeekableStreamAsync<T>( |
|
|
|
Configuration configuration, |
|
|
|
Stream stream, |
|
|
|
Func<Stream, Task<T>> action) |
|
|
|
Func<Stream, CancellationToken, Task<T>> action, |
|
|
|
CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
Guard.NotNull(configuration, nameof(configuration)); |
|
|
|
Guard.NotNull(stream, nameof(stream)); |
|
|
|
@ -725,14 +887,14 @@ namespace SixLabors.ImageSharp |
|
|
|
stream.Position = 0; |
|
|
|
} |
|
|
|
|
|
|
|
return await action(stream).ConfigureAwait(false); |
|
|
|
return await action(stream, cancellationToken).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
using MemoryStream memoryStream = configuration.MemoryAllocator.AllocateFixedCapacityMemoryStream(stream.Length); |
|
|
|
await stream.CopyToAsync(memoryStream).ConfigureAwait(false); |
|
|
|
await stream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false); |
|
|
|
memoryStream.Position = 0; |
|
|
|
|
|
|
|
return await action(memoryStream).ConfigureAwait(false); |
|
|
|
return await action(memoryStream, cancellationToken).ConfigureAwait(false); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|