diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index c845cfc4f0..e3a5938e24 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -75,6 +75,7 @@ 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); diff --git a/src/ImageSharp/Advanced/IImageVisitor.cs b/src/ImageSharp/Advanced/IImageVisitor.cs index fa7b8e2f1a..5c736c43fd 100644 --- a/src/ImageSharp/Advanced/IImageVisitor.cs +++ b/src/ImageSharp/Advanced/IImageVisitor.cs @@ -32,6 +32,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// The image. /// The pixel type. + /// A representing the asynchronous operation. Task VisitAsync(Image image) where TPixel : unmanaged, IPixel; } diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index e5de1c028d..4adfcb2256 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -76,7 +76,6 @@ namespace SixLabors.ImageSharp.Formats.Gif return decoder.Identify(stream); } - /// public async Task IdentifyAsync(Configuration configuration, Stream stream) { diff --git a/src/ImageSharp/Formats/IImageEncoder.cs b/src/ImageSharp/Formats/IImageEncoder.cs index f4d9b27937..8588385f82 100644 --- a/src/ImageSharp/Formats/IImageEncoder.cs +++ b/src/ImageSharp/Formats/IImageEncoder.cs @@ -27,6 +27,7 @@ namespace SixLabors.ImageSharp.Formats /// The pixel format. /// The to encode from. /// The to encode the image data to. + /// A representing the asynchronous operation. Task EncodeAsync(Image image, Stream stream) where TPixel : unmanaged, IPixel; } diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs index 1838b8d6d6..488d7d5f09 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs @@ -43,6 +43,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The pixel format. /// The to encode from. /// The to encode the image data to. + /// A representing the asynchronous operation. public async Task EncodeAsync(Image image, Stream stream) where TPixel : unmanaged, IPixel { diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs index a2c2ca1009..4209bef610 100644 --- a/src/ImageSharp/Formats/Png/PngEncoder.cs +++ b/src/ImageSharp/Formats/Png/PngEncoder.cs @@ -64,6 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The to encode from. /// The to encode the image data to. + /// A representing the asynchronous operation. public async Task EncodeAsync(Image image, Stream stream) where TPixel : unmanaged, IPixel { diff --git a/src/ImageSharp/FormattedImage.cs b/src/ImageSharp/FormattedImage.cs new file mode 100644 index 0000000000..5617be3515 --- /dev/null +++ b/src/ImageSharp/FormattedImage.cs @@ -0,0 +1,79 @@ +// 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 +{ + /// + /// Struct to curry and for return from async overloads. + /// + public readonly struct FormattedImage + { + /// + /// Initializes a new instance of the struct. + /// + /// The . + /// The . + public FormattedImage(Image image, IImageFormat format) + { + this.Image = image; + this.Format = format; + } + + /// + /// Gets the Image. + /// + public readonly Image Image { get; } + + /// + /// Gets the Format. + /// + public readonly IImageFormat Format { get; } + + /// + /// Converts to + /// + /// The to convert. + public static implicit operator (Image image, IImageFormat format)(FormattedImage value) + { + return (value.Image, value.Format); + } + + /// + /// Converts to + /// + /// The to convert. + public static implicit operator FormattedImage((Image image, IImageFormat format) value) + { + return new FormattedImage(value.image, value.format); + } + + /// + public override bool Equals(object obj) + { + return obj is FormattedImage other && + EqualityComparer.Default.Equals(this.Image, other.Image) && + EqualityComparer.Default.Equals(this.Format, other.Format); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(this.Image, this.Format); + } + + /// + /// Deconstructs into component parts. + /// + /// The . + /// The . + public void Deconstruct(out Image image, out IImageFormat format) + { + image = this.Image; + format = this.Format; + } + } +} diff --git a/src/ImageSharp/FormattedImageInfo.cs b/src/ImageSharp/FormattedImageInfo.cs new file mode 100644 index 0000000000..b3f854fc47 --- /dev/null +++ b/src/ImageSharp/FormattedImageInfo.cs @@ -0,0 +1,79 @@ +// 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 +{ + /// + /// Struct to curry and for return from async overloads. + /// + public readonly struct FormattedImageInfo + { + /// + /// Initializes a new instance of the struct. + /// + /// The . + /// The . + public FormattedImageInfo(IImageInfo imageInfo, IImageFormat format) + { + this.ImageInfo = imageInfo; + this.Format = format; + } + + /// + /// Gets the Image Info. + /// + public readonly IImageInfo ImageInfo { get; } + + /// + /// Gets the Format. + /// + public readonly IImageFormat Format { get; } + + /// + /// Converts to a + /// + /// The to convert. + public static implicit operator (IImageInfo imageInfo, IImageFormat format)(FormattedImageInfo value) + { + return (value.ImageInfo, value.Format); + } + + /// + /// Converts to + /// + /// The to convert. + public static implicit operator FormattedImageInfo((IImageInfo imageInfo, IImageFormat format) value) + { + return new FormattedImageInfo(value.imageInfo, value.format); + } + + /// + public override bool Equals(object obj) + { + return obj is FormattedImageInfo other && + EqualityComparer.Default.Equals(this.ImageInfo, other.ImageInfo) && + EqualityComparer.Default.Equals(this.Format, other.Format); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(this.ImageInfo, this.Format); + } + + /// + /// Deconstructs into component parts. + /// + /// The . + /// The . + public void Deconstruct(out IImageInfo imageInfo, out IImageFormat format) + { + imageInfo = this.ImageInfo; + format = this.Format; + } + } +} diff --git a/src/ImageSharp/FormattedImage{TPixel}.cs b/src/ImageSharp/FormattedImage{TPixel}.cs new file mode 100644 index 0000000000..dc4609b7e4 --- /dev/null +++ b/src/ImageSharp/FormattedImage{TPixel}.cs @@ -0,0 +1,82 @@ +// 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 +{ + /// + /// Struct to curry and for return from async overloads. + /// + /// The pixel format. + public readonly struct FormattedImage + where TPixel : unmanaged, IPixel + { + /// + /// Initializes a new instance of the struct. + /// + /// The . + /// The . + public FormattedImage(Image image, IImageFormat format) + { + this.Image = image; + this.Format = format; + } + + /// + /// Gets the Image. + /// + public readonly Image Image { get; } + + /// + /// Gets the Format. + /// + public readonly IImageFormat Format { get; } + + /// + /// Converts to . + /// + /// The to convert. + public static implicit operator (Image image, IImageFormat format)(FormattedImage value) + { + return (value.Image, value.Format); + } + + /// + /// Converts to + /// + /// The to convert. + public static implicit operator FormattedImage((Image image, IImageFormat format) value) + { + return new FormattedImage(value.image, value.format); + } + + /// + public override bool Equals(object obj) + { + return obj is FormattedImage other && + EqualityComparer>.Default.Equals(this.Image, other.Image) && + EqualityComparer.Default.Equals(this.Format, other.Format); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(this.Image, this.Format); + } + + /// + /// Deconstructs into component parts. + /// + /// The . + /// The . + public void Deconstruct(out Image image, out IImageFormat format) + { + image = this.Image; + format = this.Format; + } + } +} diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index c6f9b82241..c1cf5cc14a 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -71,6 +71,20 @@ namespace SixLabors.ImageSharp } } + /// + /// By reading the header on the provided stream this calculates the images format. + /// + /// The image stream to read the header from. + /// The configuration. + /// 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 + // 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)); + } + /// /// By reading the header on the provided stream this calculates the images format. /// @@ -163,14 +177,34 @@ namespace SixLabors.ImageSharp /// /// The or null if suitable info detector not found. /// - private static (IImageInfo info, IImageFormat format) InternalIdentity(Stream stream, Configuration config) + private static FormattedImageInfo InternalIdentity(Stream stream, Configuration config) + { + if (!(DiscoverDecoder(stream, config, out IImageFormat format) is IImageInfoDetector detector)) + { + return (null, null); + } + + var info = detector?.Identify(config, stream); + return new FormattedImageInfo(info, format); + } + + /// + /// Reads the raw image information from the specified stream. + /// + /// The stream. + /// the configuration. + /// + /// The or null if suitable info detector not found. + /// + private static async Task InternalIdentityAsync(Stream stream, Configuration config) { if (!(DiscoverDecoder(stream, config, out IImageFormat format) is IImageInfoDetector detector)) { return (null, null); } - return (detector?.Identify(config, stream), format); + var info = await detector?.IdentifyAsync(config, stream); + return new FormattedImageInfo(info, format); } } } diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index fa4b30d65a..713270525b 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -38,6 +38,28 @@ namespace SixLabors.ImageSharp public static IImageFormat DetectFormat(Configuration configuration, Stream stream) => WithSeekableStream(configuration, stream, s => InternalDetectFormat(s, configuration)); + /// + /// By reading the header on the provided stream this calculates the images format type. + /// + /// The image stream to read the header from. + /// The stream is null. + /// The stream is not readable. + /// The format type or null if none found. + public static Task DetectFormatAsync(Stream stream) + => DetectFormatAsync(Configuration.Default, stream); + + /// + /// By reading the header on the provided stream this calculates the images format type. + /// + /// The configuration. + /// The image stream to read the header from. + /// The configuration is null. + /// 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)); + /// /// Reads the raw image information from the specified stream without fully decoding it. /// @@ -51,6 +73,19 @@ namespace SixLabors.ImageSharp public static IImageInfo Identify(Stream stream) => Identify(stream, out IImageFormat _); + /// + /// Reads the raw image information from the specified stream without fully decoding it. + /// + /// The image stream to read the header from. + /// The stream is null. + /// The stream is not readable. + /// Image contains invalid content. + /// + /// The or null if suitable info detector not found. + /// + public static Task IdentifyAsync(Stream stream) + => IdentifyAsync(Configuration.Default, stream); + /// /// Reads the raw image information from the specified stream without fully decoding it. /// @@ -65,6 +100,39 @@ namespace SixLabors.ImageSharp public static IImageInfo Identify(Stream stream, out IImageFormat format) => Identify(Configuration.Default, stream, out format); + /// + /// Reads the raw image information from the specified stream without fully decoding it. + /// + /// The configuration. + /// The image stream to read the information from. + /// The configuration is null. + /// The stream is null. + /// The stream is not readable. + /// Image contains invalid content. + /// + /// The or null if suitable info detector is not found. + /// + public static IImageInfo Identify(Configuration configuration, Stream stream) + => Identify(configuration, stream, out _); + + /// + /// Reads the raw image information from the specified stream without fully decoding it. + /// + /// The configuration. + /// The image stream to read the information from. + /// The configuration is null. + /// The stream is null. + /// The stream is not readable. + /// Image contains invalid content. + /// + /// The or null if suitable info detector is not found. + /// + public static async Task IdentifyAsync(Configuration configuration, Stream stream) + { + FormattedImageInfo res = await IdentifyWithFormatAsync(configuration, stream); + return res.ImageInfo; + } + /// /// Reads the raw image information from the specified stream without fully decoding it. /// @@ -80,12 +148,41 @@ namespace SixLabors.ImageSharp /// public static IImageInfo Identify(Configuration configuration, Stream stream, out IImageFormat format) { - (IImageInfo info, IImageFormat format) data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default)); + FormattedImageInfo data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default)); - format = data.format; - return data.info; + format = data.Format; + return data.ImageInfo; } + /// + /// Reads the raw image information from the specified stream without fully decoding it. + /// + /// The image stream to read the information from. + /// The configuration is null. + /// The stream is null. + /// The stream is not readable. + /// Image contains invalid content. + /// + /// The with set to null if suitable info detector is not found. + /// + public static Task IdentifyWithFormatAsync(Stream stream) + => IdentifyWithFormatAsync(Configuration.Default, stream); + + /// + /// Reads the raw image information from the specified stream without fully decoding it. + /// + /// The configuration. + /// The image stream to read the information from. + /// The configuration is null. + /// The stream is null. + /// The stream is not readable. + /// Image contains invalid content. + /// + /// 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)); + /// /// Decode a new instance of the class from the given stream. /// The pixel format is selected by the decoder. @@ -100,18 +197,16 @@ namespace SixLabors.ImageSharp public static Image Load(Stream stream, out IImageFormat format) => Load(Configuration.Default, stream, out format); - /// /// Decode a new instance of the class from the given stream. /// The pixel format is selected by the decoder. /// /// The stream containing image information. - /// The format type of the decoded image. /// The stream is null. /// The stream is not readable. /// Image format not recognised. /// Image contains invalid content. - /// The . + /// A representing the asynchronous operation. public static Task LoadWithFormatAsync(Stream stream) => LoadWithFormatAsync(Configuration.Default, stream); @@ -282,18 +377,16 @@ namespace SixLabors.ImageSharp where TPixel : unmanaged, IPixel => Load(Configuration.Default, stream, out format); - /// /// Create a new instance of the class from the given stream. /// /// The stream containing image information. - /// The format type of the decoded image. /// The stream is null. /// The stream is not readable. /// Image format not recognised. /// Image contains invalid content. /// The pixel format. - /// A new .> + /// A representing the asynchronous operation. public static Task> LoadWithFormatAsync(Stream stream) where TPixel : unmanaged, IPixel => LoadWithFormatAsync(Configuration.Default, stream); @@ -594,88 +687,4 @@ namespace SixLabors.ImageSharp } } } - - public readonly struct FormattedImage where TPixel : unmanaged, IPixel - { - public FormattedImage(Image image, IImageFormat format) - { - this.Image = image; - this.Format = format; - } - - public readonly Image Image { get; } - - public readonly IImageFormat Format { get; } - - - public static implicit operator (Image image, IImageFormat format)(FormattedImage value) - { - return (value.Image, value.Format); - } - - public static implicit operator FormattedImage((Image image, IImageFormat format) value) - { - return new FormattedImage(value.image, value.format); - } - - public override bool Equals(object obj) - { - return obj is FormattedImage other && - EqualityComparer>.Default.Equals(this.Image, other.Image) && - EqualityComparer.Default.Equals(this.Format, other.Format); - } - - public override int GetHashCode() - { - return HashCode.Combine(this.Image, this.Format); - } - - public void Deconstruct(out Image image, out IImageFormat format) - { - image = this.Image; - format = this.Format; - } - } - - public readonly struct FormattedImage - { - public FormattedImage(Image image, IImageFormat format) - { - this.Image = image; - this.Format = format; - } - - public readonly Image Image { get; } - - public readonly IImageFormat Format { get; } - - - public static implicit operator (Image image, IImageFormat format)(FormattedImage value) - { - return (value.Image, value.Format); - } - - public static implicit operator FormattedImage((Image image, IImageFormat format) value) - { - return new FormattedImage(value.image, value.format); - } - - public override bool Equals(object obj) - { - return obj is FormattedImage other && - EqualityComparer.Default.Equals(this.Image, other.Image) && - EqualityComparer.Default.Equals(this.Format, other.Format); - } - - public override int GetHashCode() - { - return HashCode.Combine(this.Image, this.Format); - } - - public void Deconstruct(out Image image, out IImageFormat format) - { - image = this.Image; - format = this.Format; - } - } } diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 5de580283e..8a691a4b33 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -104,6 +104,7 @@ namespace SixLabors.ImageSharp /// The stream to save the image to. /// 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) { Guard.NotNull(stream, nameof(stream)); diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs index a71cc40644..df2c121065 100644 --- a/src/ImageSharp/ImageExtensions.cs +++ b/src/ImageSharp/ImageExtensions.cs @@ -31,6 +31,7 @@ namespace SixLabors.ImageSharp /// The source image. /// The file path to save the image to. /// The path is null. + /// A representing the asynchronous operation. public static Task SaveAsync(this Image source, string path) => source.SaveAsync(path, source.FindEncoded(path)); @@ -52,7 +53,6 @@ namespace SixLabors.ImageSharp } } - /// /// Writes the image to the given stream using the currently loaded image format. /// @@ -61,6 +61,7 @@ namespace SixLabors.ImageSharp /// The encoder to save the image with. /// The path is null. /// The encoder is null. + /// A representing the asynchronous operation. public static async Task SaveAsync(this Image source, string path, IImageEncoder encoder) { Guard.NotNull(path, nameof(path)); diff --git a/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs b/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs index f923832abe..b1acea9671 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs @@ -3,8 +3,9 @@ using System; using System.IO; +using System.Threading.Tasks; using SixLabors.ImageSharp.Formats; - +using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; // ReSharper disable InconsistentNaming @@ -91,6 +92,30 @@ namespace SixLabors.ImageSharp.Tests IImageFormat type = Image.DetectFormat(new Configuration(), this.DataStream); Assert.Null(type); } + + [Fact] + public async Task FromStreamAsync_GlobalConfiguration() + { + using (var stream = new MemoryStream(this.ActualImageBytes)) + { + IImageFormat type = await Image.DetectFormatAsync(new AsyncStreamWrapper(stream, () => false)); + Assert.Equal(ExpectedGlobalFormat, type); + } + } + + [Fact] + public async Task FromStreamAsync_CustomConfiguration() + { + IImageFormat type = await Image.DetectFormatAsync(this.LocalConfiguration, new AsyncStreamWrapper(this.DataStream, () => false)); + Assert.Equal(this.LocalImageFormat, type); + } + + [Fact] + public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull() + { + IImageFormat type = await Image.DetectFormatAsync(new Configuration(), new AsyncStreamWrapper(this.DataStream, () => false)); + Assert.Null(type); + } } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs b/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs index c7dbbc2d8f..8493db073f 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs @@ -2,8 +2,9 @@ // Licensed under the GNU Affero General Public License, Version 3. using System.IO; +using System.Threading.Tasks; using SixLabors.ImageSharp.Formats; - +using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; // ReSharper disable InconsistentNaming @@ -77,6 +78,17 @@ namespace SixLabors.ImageSharp.Tests } } + [Fact] + public void FromStream_GlobalConfiguration_NoFormat() + { + using (var stream = new MemoryStream(this.ActualImageBytes)) + { + IImageInfo info = Image.Identify(stream); + + Assert.NotNull(info); + } + } + [Fact] public void FromStream_CustomConfiguration() { @@ -86,6 +98,14 @@ namespace SixLabors.ImageSharp.Tests Assert.Equal(this.LocalImageFormat, type); } + [Fact] + public void FromStream_CustomConfiguration_NoFormat() + { + IImageInfo info = Image.Identify(this.LocalConfiguration, this.DataStream); + + Assert.Equal(this.LocalImageInfo, info); + } + [Fact] public void WhenNoMatchingFormatFound_ReturnsNull() { @@ -94,6 +114,50 @@ namespace SixLabors.ImageSharp.Tests Assert.Null(info); Assert.Null(type); } + + [Fact] + public async Task FromStreamAsync_GlobalConfiguration_NoFormat() + { + using (var stream = new MemoryStream(this.ActualImageBytes)) + { + var asyncStream = new AsyncStreamWrapper(stream, () => false); + IImageInfo info = await Image.IdentifyAsync(asyncStream); + + Assert.NotNull(info); + } + } + + [Fact] + public async Task FromStreamAsync_GlobalConfiguration() + { + using (var stream = new MemoryStream(this.ActualImageBytes)) + { + var asyncStream = new AsyncStreamWrapper(stream, () => false); + FormattedImageInfo info = await Image.IdentifyWithFormatAsync(asyncStream); + + Assert.NotNull(info.ImageInfo); + Assert.Equal(ExpectedGlobalFormat, info.Format); + } + } + + [Fact] + public async Task FromStreamAsync_CustomConfiguration() + { + var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false); + FormattedImageInfo info = await Image.IdentifyWithFormatAsync(this.LocalConfiguration, asyncStream); + + Assert.Equal(this.LocalImageInfo, info.ImageInfo); + Assert.Equal(this.LocalImageFormat, info.Format); + } + + [Fact] + public async Task WhenNoMatchingFormatFoundAsync_ReturnsNull() + { + var asyncStream = new AsyncStreamWrapper(this.DataStream, () => false); + FormattedImageInfo info = await Image.IdentifyWithFormatAsync(new Configuration(), asyncStream); + + Assert.Null(info.ImageInfo); + } } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs index 5941854c14..6085fff2ea 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs @@ -60,6 +60,7 @@ namespace SixLabors.ImageSharp.Tests var detector = new Mock(); detector.Setup(x => x.Identify(It.IsAny(), It.IsAny())).Returns(this.localImageInfoMock.Object); + detector.Setup(x => x.IdentifyAsync(It.IsAny(), It.IsAny())).ReturnsAsync(this.localImageInfoMock.Object); this.localDecoder = detector.As(); this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object); diff --git a/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs b/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs index 0f87df7b2a..a327861ca0 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs @@ -23,7 +23,6 @@ namespace SixLabors.ImageSharp.Tests { public class SaveAsync { - [Fact] public async Task DetectedEncoding() { diff --git a/tests/ImageSharp.Tests/TestUtilities/AsyncStreamWrapper.cs b/tests/ImageSharp.Tests/TestUtilities/AsyncStreamWrapper.cs index dc4133fbf2..3d23a3c3b1 100644 --- a/tests/ImageSharp.Tests/TestUtilities/AsyncStreamWrapper.cs +++ b/tests/ImageSharp.Tests/TestUtilities/AsyncStreamWrapper.cs @@ -1,3 +1,6 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the GNU Affero General Public License, Version 3. + using System; using System.Collections.Generic; using System.IO;