Browse Source

Use named tuple

pull/1196/head
James Jackson-South 6 years ago
parent
commit
73cc7964e8
  1. 95
      src/ImageSharp/FormattedImage.cs
  2. 93
      src/ImageSharp/FormattedImageInfo.cs
  3. 98
      src/ImageSharp/FormattedImage{TPixel}.cs
  4. 35
      src/ImageSharp/Image.Decode.cs
  5. 98
      src/ImageSharp/Image.FromStream.cs
  6. 6
      tests/ImageSharp.Tests/Image/ImageTests.Identify.cs
  7. 7
      tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
  8. 6
      tests/ImageSharp.Tests/TestUtilities/AsyncStreamWrapper.cs

95
src/ImageSharp/FormattedImage.cs

@ -1,95 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the GNU Affero General Public License, Version 3.
using System;
using System.Collections.Generic;
using SixLabors.ImageSharp.Formats;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Struct to curry <see cref="Image"/> and <see cref="IImageFormat"/> for return from async overloads.
/// </summary>
public readonly struct FormattedImage : IEquatable<FormattedImage>
{
/// <summary>
/// Initializes a new instance of the <see cref="FormattedImage"/> struct.
/// </summary>
/// <param name="image">The <see cref="Image"/>.</param>
/// <param name="format">The <see cref="IImageFormat"/>.</param>
public FormattedImage(Image image, IImageFormat format)
{
this.Image = image;
this.Format = format;
}
/// <summary>
/// Gets the Image.
/// </summary>
public readonly Image Image { get; }
/// <summary>
/// Gets the Format.
/// </summary>
public readonly IImageFormat Format { get; }
/// <summary>
/// Converts <see cref="FormattedImage"/> to <see cref="ValueTuple"/>.
/// </summary>
/// <param name="value">The <see cref="FormattedImage"/> to convert.</param>
public static implicit operator (Image image, IImageFormat format)(FormattedImage value)
=> (value.Image, value.Format);
/// <summary>
/// Converts <see cref="ValueTuple"/> to <see cref="FormattedImage"/>
/// </summary>
/// <param name="value">The <see cref="ValueTuple"/> to convert.</param>
public static implicit operator FormattedImage((Image image, IImageFormat format) value)
=> new FormattedImage(value.image, value.format);
/// <summary>
/// Compares two <see cref="FormattedImage"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="FormattedImage"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="FormattedImage"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator ==(FormattedImage left, FormattedImage right)
=> left.Equals(right);
/// <summary>
/// Compares two <see cref="FormattedImage"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="FormattedImage"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="FormattedImage"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator !=(FormattedImage left, FormattedImage right)
=> !(left == right);
/// <inheritdoc/>
public override bool Equals(object obj)
=> obj is FormattedImage image && this.Equals(image);
/// <inheritdoc/>
public bool Equals(FormattedImage other)
=> EqualityComparer<Image>.Default.Equals(this.Image, other.Image)
&& EqualityComparer<IImageFormat>.Default.Equals(this.Format, other.Format);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.Image, this.Format);
/// <summary>
/// Deconstructs <see cref="FormattedImage"/> into component parts.
/// </summary>
/// <param name="image">The <see cref="Image"/>.</param>
/// <param name="format">The <see cref="IImageFormat"/>.</param>
public void Deconstruct(out Image image, out IImageFormat format)
{
image = this.Image;
format = this.Format;
}
}
}

93
src/ImageSharp/FormattedImageInfo.cs

@ -1,93 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the GNU Affero General Public License, Version 3.
using System;
using System.Collections.Generic;
using SixLabors.ImageSharp.Formats;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Struct to curry <see cref="IImageInfo"/> and <see cref="IImageFormat"/> for return from async overloads.
/// </summary>
public readonly struct FormattedImageInfo : IEquatable<FormattedImageInfo>
{
/// <summary>
/// Initializes a new instance of the <see cref="FormattedImageInfo"/> struct.
/// </summary>
/// <param name="imageInfo">The <see cref="FormattedImageInfo"/>.</param>
/// <param name="format">The <see cref="IImageFormat"/>.</param>
public FormattedImageInfo(IImageInfo imageInfo, IImageFormat format)
{
this.ImageInfo = imageInfo;
this.Format = format;
}
/// <summary>
/// Gets the Image Info.
/// </summary>
public readonly IImageInfo ImageInfo { get; }
/// <summary>
/// Gets the Format.
/// </summary>
public readonly IImageFormat Format { get; }
/// <summary>
/// Converts <see cref="FormattedImageInfo"/> to a <see cref="ValueTuple"/>
/// </summary>
/// <param name="value">The <see cref="FormattedImageInfo"/> to convert.</param>
public static implicit operator (IImageInfo imageInfo, IImageFormat format)(FormattedImageInfo value)
=> (value.ImageInfo, value.Format);
/// <summary>
/// Converts <see cref="ValueTuple"/> to <see cref="FormattedImageInfo"/>
/// </summary>
/// <param name="value">The <see cref="ValueTuple"/> to convert.</param>
public static implicit operator FormattedImageInfo((IImageInfo imageInfo, IImageFormat format) value)
=> new FormattedImageInfo(value.imageInfo, value.format);
/// <summary>
/// Compares two <see cref="FormattedImageInfo"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="FormattedImageInfo"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="FormattedImageInfo"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator ==(FormattedImageInfo left, FormattedImageInfo right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="FormattedImageInfo"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="FormattedImageInfo"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="FormattedImageInfo"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator !=(FormattedImageInfo left, FormattedImageInfo right) => !(left == right);
/// <inheritdoc/>
public override bool Equals(object obj)
=> obj is FormattedImageInfo info && this.Equals(info);
/// <inheritdoc/>
public bool Equals(FormattedImageInfo other)
=> EqualityComparer<IImageInfo>.Default.Equals(this.ImageInfo, other.ImageInfo)
&& EqualityComparer<IImageFormat>.Default.Equals(this.Format, other.Format);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.ImageInfo, this.Format);
/// <summary>
/// Deconstructs <see cref="FormattedImageInfo"/> into component parts.
/// </summary>
/// <param name="imageInfo">The <see cref="FormattedImageInfo"/>.</param>
/// <param name="format">The <see cref="IImageFormat"/>.</param>
public void Deconstruct(out IImageInfo imageInfo, out IImageFormat format)
{
imageInfo = this.ImageInfo;
format = this.Format;
}
}
}

98
src/ImageSharp/FormattedImage{TPixel}.cs

@ -1,98 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the GNU Affero General Public License, Version 3.
using System;
using System.Collections.Generic;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Struct to curry <see cref="Image{TPixel}"/> and <see cref="IImageFormat"/> for return from async overloads.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public readonly struct FormattedImage<TPixel> : IEquatable<FormattedImage<TPixel>>
where TPixel : unmanaged, IPixel<TPixel>
{
/// <summary>
/// Initializes a new instance of the <see cref="FormattedImage{TPixel}"/> struct.
/// </summary>
/// <param name="image">The <see cref="Image{TPixel}"/>.</param>
/// <param name="format">The <see cref="IImageFormat"/>.</param>
public FormattedImage(Image<TPixel> image, IImageFormat format)
{
this.Image = image;
this.Format = format;
}
/// <summary>
/// Gets the Image.
/// </summary>
public readonly Image<TPixel> Image { get; }
/// <summary>
/// Gets the Format.
/// </summary>
public readonly IImageFormat Format { get; }
/// <summary>
/// Converts <see cref="FormattedImage{TPixel}"/> to <see cref="ValueTuple"/>.
/// </summary>
/// <param name="value">The <see cref="FormattedImage{TPixel}"/> to convert.</param>
public static implicit operator (Image<TPixel> image, IImageFormat format)(FormattedImage<TPixel> value)
=> (value.Image, value.Format);
/// <summary>
/// Converts <see cref="ValueTuple"/> to <see cref="FormattedImage{TPixel}"/>
/// </summary>
/// <param name="value">The <see cref="ValueTuple"/> to convert.</param>
public static implicit operator FormattedImage<TPixel>((Image<TPixel> image, IImageFormat format) value)
=> new FormattedImage<TPixel>(value.image, value.format);
/// <summary>
/// Compares two <see cref="FormattedImage{TPixel}"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="FormattedImage{TPixel}"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="FormattedImage{TPixel}"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator ==(FormattedImage<TPixel> left, FormattedImage<TPixel> right)
=> left.Equals(right);
/// <summary>
/// Compares two <see cref="FormattedImage{TPixel}"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="FormattedImage{TPixel}"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="FormattedImage{TPixel}"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator !=(FormattedImage<TPixel> left, FormattedImage<TPixel> right)
=> !(left == right);
/// <inheritdoc/>
public override bool Equals(object obj)
=> obj is FormattedImage<TPixel> image && this.Equals(image);
/// <inheritdoc/>
public bool Equals(FormattedImage<TPixel> other)
=> EqualityComparer<Image<TPixel>>.Default.Equals(this.Image, other.Image)
&& EqualityComparer<IImageFormat>.Default.Equals(this.Format, other.Format);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.Image, this.Format);
/// <summary>
/// Deconstructs <see cref="FormattedImage"/> into component parts.
/// </summary>
/// <param name="image">The <see cref="Image{TPixel}"/>.</param>
/// <param name="format">The <see cref="IImageFormat"/>.</param>
public void Deconstruct(out Image<TPixel> image, out IImageFormat format)
{
image = this.Image;
format = this.Format;
}
}
}

35
src/ImageSharp/Image.Decode.cs

@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp
/// <returns>
/// A new <see cref="Image{TPixel}"/>.
/// </returns>
private static FormattedImage<TPixel> Decode<TPixel>(Stream stream, Configuration config)
private static (Image<TPixel> Image, IImageFormat Format) Decode<TPixel>(Stream stream, Configuration config)
where TPixel : unmanaged, IPixel<TPixel>
{
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp
}
Image<TPixel> img = decoder.Decode<TPixel>(config, stream);
return new FormattedImage<TPixel>(img, format);
return (img, format);
}
/// <summary>
@ -129,10 +129,8 @@ namespace SixLabors.ImageSharp
/// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>
/// A new <see cref="Image{TPixel}"/>.
/// </returns>
private static async Task<FormattedImage<TPixel>> DecodeAsync<TPixel>(Stream stream, Configuration config)
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
private static async Task<(Image<TPixel> Image, IImageFormat Format)> DecodeAsync<TPixel>(Stream stream, Configuration config)
where TPixel : unmanaged, IPixel<TPixel>
{
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
@ -142,10 +140,10 @@ namespace SixLabors.ImageSharp
}
Image<TPixel> img = await decoder.DecodeAsync<TPixel>(config, stream).ConfigureAwait(false);
return new FormattedImage<TPixel>(img, format);
return (img, format);
}
private static FormattedImage Decode(Stream stream, Configuration config)
private static (Image Image, IImageFormat Format) Decode(Stream stream, Configuration config)
{
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
if (decoder is null)
@ -154,10 +152,10 @@ namespace SixLabors.ImageSharp
}
Image img = decoder.Decode(config, stream);
return new FormattedImage(img, format);
return (img, format);
}
private static async Task<FormattedImage> DecodeAsync(Stream stream, Configuration config)
private static async Task<(Image Image, IImageFormat Format)> DecodeAsync(Stream stream, Configuration config)
{
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
if (decoder is null)
@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp
}
Image img = await decoder.DecodeAsync(config, stream).ConfigureAwait(false);
return new FormattedImage(img, format);
return (img, format);
}
/// <summary>
@ -175,9 +173,9 @@ namespace SixLabors.ImageSharp
/// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// The <see cref="IImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
private static FormattedImageInfo InternalIdentity(Stream stream, Configuration config)
private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(Stream stream, Configuration config)
{
if (!(DiscoverDecoder(stream, config, out IImageFormat format) is IImageInfoDetector detector))
{
@ -185,7 +183,7 @@ namespace SixLabors.ImageSharp
}
IImageInfo info = detector?.Identify(config, stream);
return new FormattedImageInfo(info, format);
return (info, format);
}
/// <summary>
@ -194,9 +192,10 @@ namespace SixLabors.ImageSharp
/// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
private static async Task<FormattedImageInfo> InternalIdentityAsync(Stream stream, Configuration config)
/// A <see cref="Task{ValueTuple}"/> representing the asynchronous operation with the
/// <see cref="IImageInfo"/> property of the returned type set to null if a suitable detector
/// is not found.</returns>
private static async Task<(IImageInfo ImageInfo, IImageFormat Format)> InternalIdentityAsync(Stream stream, Configuration config)
{
if (!(DiscoverDecoder(stream, config, out IImageFormat format) is IImageInfoDetector detector))
{
@ -209,7 +208,7 @@ namespace SixLabors.ImageSharp
}
IImageInfo info = await detector.IdentifyAsync(config, stream).ConfigureAwait(false);
return new FormattedImageInfo(info, format);
return (info, format);
}
}
}

98
src/ImageSharp/Image.FromStream.cs

@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <returns>The format type or null if none found.</returns>
/// <returns>A <see cref="Task{IImageFormat}"/> representing the asynchronous operation or null if none is found.</returns>
public static Task<IImageFormat> DetectFormatAsync(Stream stream)
=> DetectFormatAsync(Configuration.Default, stream);
@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp
/// <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>
/// <returns>The format type or null if none found.</returns>
/// <returns>A <see cref="Task{IImageFormat}"/> representing the asynchronous operation.</returns>
public static Task<IImageFormat> DetectFormatAsync(Configuration configuration, Stream stream)
=> WithSeekableStreamAsync(
configuration,
@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// The <see cref="IImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Stream stream)
=> Identify(stream, out IImageFormat _);
@ -84,7 +84,8 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// A <see cref="Task{IImageInfo}"/> representing the asynchronous operation or null if
/// a suitable detector is not found.
/// </returns>
public static Task<IImageInfo> IdentifyAsync(Stream stream)
=> IdentifyAsync(Configuration.Default, stream);
@ -98,7 +99,7 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// The <see cref="IImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Stream stream, out IImageFormat format)
=> Identify(Configuration.Default, stream, out format);
@ -113,7 +114,7 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// The <see cref="IImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration configuration, Stream stream)
=> Identify(configuration, stream, out _);
@ -128,11 +129,12 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// A <see cref="Task{IImageInfo}"/> representing the asynchronous operation or null if
/// a suitable detector is not found.
/// </returns>
public static async Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream)
{
FormattedImageInfo res = await IdentifyWithFormatAsync(configuration, stream).ConfigureAwait(false);
(IImageInfo ImageInfo, IImageFormat Format) res = await IdentifyWithFormatAsync(configuration, stream).ConfigureAwait(false);
return res.ImageInfo;
}
@ -147,11 +149,11 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// The <see cref="IImageInfo"/> or null if a suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration configuration, Stream stream, out IImageFormat format)
{
FormattedImageInfo data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default));
(IImageInfo ImageInfo, IImageFormat Format) data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default));
format = data.Format;
return data.ImageInfo;
@ -166,9 +168,10 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="FormattedImageInfo"/> with <see cref="FormattedImageInfo.ImageInfo"/> set to null if suitable info detector is not found.
/// A <see cref="Task"/> representing the asynchronous operation or null if
/// a suitable detector is not found.
/// </returns>
public static Task<FormattedImageInfo> IdentifyWithFormatAsync(Stream stream)
public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(Stream stream)
=> IdentifyWithFormatAsync(Configuration.Default, stream);
/// <summary>
@ -181,9 +184,10 @@ namespace SixLabors.ImageSharp
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="FormattedImageInfo"/> with <see cref="FormattedImageInfo.ImageInfo"/> set to null if suitable info detector is not found.
/// 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<FormattedImageInfo> IdentifyWithFormatAsync(Configuration configuration, Stream stream)
public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(Configuration configuration, Stream stream)
=> WithSeekableStreamAsync(
configuration,
stream,
@ -212,8 +216,8 @@ namespace SixLabors.ImageSharp
/// <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{FormattedImage}"/> representing the asynchronous operation.</returns>
public static Task<FormattedImage> LoadWithFormatAsync(Stream stream)
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Stream stream)
=> LoadWithFormatAsync(Configuration.Default, stream);
/// <summary>
@ -237,7 +241,7 @@ namespace SixLabors.ImageSharp
/// <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>The <see cref="Image"/>.</returns>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static Task<Image> LoadAsync(Stream stream) => LoadAsync(Configuration.Default, stream);
/// <summary>
@ -266,7 +270,7 @@ namespace SixLabors.ImageSharp
/// <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>The <see cref="Image"/>.</returns>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static Task<Image> LoadAsync(Stream stream, IImageDecoder decoder)
=> LoadAsync(Configuration.Default, stream, decoder);
@ -283,7 +287,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image"/>.</returns>>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder)
{
Guard.NotNull(decoder, nameof(decoder));
@ -303,7 +307,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image"/>.</returns>>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static Task<Image> LoadAsync(Configuration configuration, Stream stream, IImageDecoder decoder)
{
Guard.NotNull(decoder, nameof(decoder));
@ -323,7 +327,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image"/>.</returns>>
/// <returns>A new <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, Stream stream) => Load(configuration, stream, out _);
/// <summary>
@ -336,10 +340,10 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image"/>.</returns>>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static async Task<Image> LoadAsync(Configuration configuration, Stream stream)
{
FormattedImage fmt = await LoadWithFormatAsync(configuration, stream).ConfigureAwait(false);
(Image Image, IImageFormat Format) fmt = await LoadWithFormatAsync(configuration, stream).ConfigureAwait(false);
return fmt.Image;
}
@ -352,7 +356,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(Configuration.Default, stream);
@ -366,7 +370,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A <see cref="Task{Image}"/> representing the asynchronous operation.</returns>
public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> LoadAsync<TPixel>(Configuration.Default, stream);
@ -381,7 +385,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(Configuration.Default, stream, out format);
@ -395,8 +399,8 @@ namespace SixLabors.ImageSharp
/// <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<FormattedImage<TPixel>> LoadWithFormatAsync<TPixel>(Stream stream)
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static async Task<(Image<TPixel> Image, IImageFormat Format)> LoadWithFormatAsync<TPixel>(Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> await LoadWithFormatAsync<TPixel>(Configuration.Default, stream).ConfigureAwait(false);
@ -410,7 +414,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
=> WithSeekableStream(Configuration.Default, stream, s => decoder.Decode<TPixel>(Configuration.Default, s));
@ -425,7 +429,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <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>
=> WithSeekableStreamAsync(
@ -445,7 +449,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
=> WithSeekableStream(configuration, stream, s => decoder.Decode<TPixel>(configuration, s));
@ -462,7 +466,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
=> WithSeekableStreamAsync(
@ -481,7 +485,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(configuration, stream, out IImageFormat _);
@ -498,17 +502,17 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
(Image<TPixel> img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode<TPixel>(s, configuration));
(Image<TPixel> Image, IImageFormat Format) data = WithSeekableStream(configuration, stream, s => Decode<TPixel>(s, configuration));
format = data.format;
format = data.Format;
if (data.img != null)
if (data.Image != null)
{
return data.img;
return data.Image;
}
var sb = new StringBuilder();
@ -532,16 +536,16 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>
public static async Task<FormattedImage> LoadWithFormatAsync(Configuration configuration, Stream stream)
/// <returns>A <see cref="Task{ValueTuple}"/> representing the asynchronous operation.</returns>
public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Configuration configuration, Stream stream)
{
(Image img, IImageFormat format) data = await WithSeekableStreamAsync(
(Image Image, IImageFormat Format) data = await WithSeekableStreamAsync(
configuration,
stream,
async s => await DecodeAsync(s, configuration).ConfigureAwait(false))
.ConfigureAwait(false);
if (data.img != null)
if (data.Image != null)
{
return data;
}
@ -568,18 +572,18 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>
public static async Task<FormattedImage<TPixel>> LoadWithFormatAsync<TPixel>(Configuration configuration, Stream stream)
/// <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)
where TPixel : unmanaged, IPixel<TPixel>
{
(Image<TPixel> img, IImageFormat format) data =
(Image<TPixel> Image, IImageFormat Format) data =
await WithSeekableStreamAsync(
configuration,
stream,
s => DecodeAsync<TPixel>(s, configuration))
.ConfigureAwait(false);
if (data.img != null)
if (data.Image != null)
{
return data;
}
@ -606,7 +610,7 @@ namespace SixLabors.ImageSharp
/// <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 new <see cref="Image{TPixel}"/>.</returns>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static async Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{

6
tests/ImageSharp.Tests/Image/ImageTests.Identify.cs

@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Tests
using (var stream = new MemoryStream(this.ActualImageBytes))
{
var asyncStream = new AsyncStreamWrapper(stream, () => false);
FormattedImageInfo info = await Image.IdentifyWithFormatAsync(asyncStream);
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(asyncStream);
Assert.NotNull(info.ImageInfo);
Assert.Equal(ExpectedGlobalFormat, info.Format);
@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.Tests
public async Task FromStreamAsync_CustomConfiguration()
{
var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false);
FormattedImageInfo info = await Image.IdentifyWithFormatAsync(this.LocalConfiguration, asyncStream);
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(this.LocalConfiguration, asyncStream);
Assert.Equal(this.LocalImageInfo, info.ImageInfo);
Assert.Equal(this.LocalImageFormat, info.Format);
@ -154,7 +154,7 @@ namespace SixLabors.ImageSharp.Tests
public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull()
{
var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false);
FormattedImageInfo info = await Image.IdentifyWithFormatAsync(new Configuration(), asyncStream);
(IImageInfo ImageInfo, IImageFormat Format) info = await Image.IdentifyWithFormatAsync(new Configuration(), asyncStream);
Assert.Null(info.ImageInfo);
}

7
tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the GNU Affero General Public License, Version 3.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
@ -13,7 +13,6 @@ using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
{
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
@ -27,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests
public async Task DetectedEncoding()
{
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
string file = System.IO.Path.Combine(dir, "DetectedEncodingAsync.png");
string file = Path.Combine(dir, "DetectedEncodingAsync.png");
using (var image = new Image<Rgba32>(10, 10))
{

6
tests/ImageSharp.Tests/TestUtilities/AsyncStreamWrapper.cs

@ -1,10 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the GNU Affero General Public License, Version 3.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

Loading…
Cancel
Save