Skip to content

Commit be88f8a

Browse files
committed
Added ReadAsync to MagickImageCollection.
1 parent db15872 commit be88f8a

File tree

4 files changed

+237
-0
lines changed

4 files changed

+237
-0
lines changed

src/Magick.NET.Core/IMagickImageCollection.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
using System;
1414
using System.IO;
15+
#if NETSTANDARD
16+
using System.Threading.Tasks;
17+
#endif
1518

1619
namespace ImageMagick
1720
{
@@ -242,6 +245,25 @@ public interface IMagickImageCollection : IDisposable
242245
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
243246
void Read(string fileName, MagickFormat format);
244247

248+
#if NETSTANDARD
249+
/// <summary>
250+
/// Read all image frames.
251+
/// </summary>
252+
/// <param name="stream">The stream to read the image data from.</param>
253+
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
254+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
255+
Task ReadAsync(Stream stream);
256+
257+
/// <summary>
258+
/// Read all image frames.
259+
/// </summary>
260+
/// <param name="stream">The stream to read the image data from.</param>
261+
/// <param name="format">The format to use.</param>
262+
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
263+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
264+
Task ReadAsync(Stream stream, MagickFormat format);
265+
#endif
266+
245267
/// <summary>
246268
/// Resets the page property of every image in the collection.
247269
/// </summary>

src/Magick.NET.Core/IMagickImageCollection{TQuantumType}.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
using System.Collections.Generic;
1414
using System.IO;
15+
#if NETSTANDARD
16+
using System.Threading.Tasks;
17+
#endif
1518

1619
namespace ImageMagick
1720
{
@@ -249,6 +252,17 @@ public interface IMagickImageCollection<TQuantumType> : IMagickImageCollection,
249252
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
250253
void Read(string fileName, IMagickReadSettings<TQuantumType> readSettings);
251254

255+
#if NETSTANDARD
256+
/// <summary>
257+
/// Read all image frames.
258+
/// </summary>
259+
/// <param name="stream">The stream to read the image data from.</param>
260+
/// <param name="readSettings">The settings to use when reading the image.</param>
261+
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
262+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
263+
Task ReadAsync(Stream stream, IMagickReadSettings<TQuantumType> readSettings);
264+
#endif
265+
252266
/// <summary>
253267
/// Smush images from list into single image in horizontal direction.
254268
/// </summary>

src/Magick.NET/MagickImageCollection.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
using System.Collections.Generic;
1616
using System.Diagnostics.CodeAnalysis;
1717
using System.IO;
18+
#if NETSTANDARD
19+
using System.Threading.Tasks;
20+
#endif
1821

1922
#if Q8
2023
using QuantumType = System.Byte;
@@ -1184,6 +1187,48 @@ public void Read(string fileName, IMagickReadSettings<QuantumType> readSettings)
11841187
AddImages(fileName, readSettings, false);
11851188
}
11861189

1190+
#if NETSTANDARD
1191+
/// <summary>
1192+
/// Read all image frames.
1193+
/// </summary>
1194+
/// <param name="stream">The stream to read the image data from.</param>
1195+
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
1196+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
1197+
public Task ReadAsync(Stream stream)
1198+
=> ReadAsync(stream, null);
1199+
1200+
/// <summary>
1201+
/// Read all image frames.
1202+
/// </summary>
1203+
/// <param name="stream">The stream to read the image data from.</param>
1204+
/// <param name="format">The format to use.</param>
1205+
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
1206+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
1207+
public Task ReadAsync(Stream stream, MagickFormat format)
1208+
=> ReadAsync(stream, new MagickReadSettings { Format = format });
1209+
1210+
/// <summary>
1211+
/// Read all image frames.
1212+
/// </summary>
1213+
/// <param name="stream">The stream to read the image data from.</param>
1214+
/// <param name="readSettings">The settings to use when reading the image.</param>
1215+
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
1216+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
1217+
public async Task ReadAsync(Stream stream, IMagickReadSettings<QuantumType> readSettings)
1218+
{
1219+
Throw.IfNull(nameof(stream), stream);
1220+
1221+
using (var memStream = new MemoryStream())
1222+
{
1223+
await stream.CopyToAsync(memStream).ConfigureAwait(false);
1224+
1225+
memStream.Position = 0;
1226+
Clear();
1227+
AddImages(memStream, readSettings, false);
1228+
}
1229+
}
1230+
#endif
1231+
11871232
/// <summary>
11881233
/// Removes the first occurrence of the specified image from the collection.
11891234
/// </summary>
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Copyright 2013-2020 Dirk Lemstra <https://github.com/dlemstra/Magick.NET/>
2+
//
3+
// Licensed under the ImageMagick License (the "License"); you may not use this file except in
4+
// compliance with the License. You may obtain a copy of the License at
5+
//
6+
// https://www.imagemagick.org/script/license.php
7+
//
8+
// Unless required by applicable law or agreed to in writing, software distributed under the
9+
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
10+
// either express or implied. See the License for the specific language governing permissions
11+
// and limitations under the License.
12+
13+
#if NETCOREAPP
14+
using System;
15+
using System.IO;
16+
using System.Text;
17+
using System.Threading.Tasks;
18+
using ImageMagick;
19+
using Xunit;
20+
21+
namespace Magick.NET.Tests
22+
{
23+
public partial class MagickImageCollectionTests
24+
{
25+
public class TheReadAsyncMethod
26+
{
27+
public class WithStream
28+
{
29+
[Fact]
30+
public async Task ShouldThrowExceptionWhenStreamIsNull()
31+
{
32+
using (var images = new MagickImageCollection())
33+
{
34+
await Assert.ThrowsAsync<ArgumentNullException>("stream", () => images.ReadAsync(null));
35+
}
36+
}
37+
38+
[Fact]
39+
public async Task ShouldResetTheFormatAfterReading()
40+
{
41+
var readSettings = new MagickReadSettings
42+
{
43+
Format = MagickFormat.Png,
44+
};
45+
46+
using (var stream = File.OpenRead(Files.CirclePNG))
47+
{
48+
using (var input = new MagickImageCollection())
49+
{
50+
await input.ReadAsync(stream, readSettings);
51+
52+
Assert.Equal(MagickFormat.Unknown, input[0].Settings.Format);
53+
}
54+
}
55+
}
56+
}
57+
58+
public class WithStreamAndMagickFormat
59+
{
60+
[Fact]
61+
public async Task ShouldThrowExceptionWhenStreamIsNull()
62+
{
63+
using (var images = new MagickImageCollection())
64+
{
65+
await Assert.ThrowsAsync<ArgumentNullException>("stream", () => images.ReadAsync((Stream)null, MagickFormat.Png));
66+
}
67+
}
68+
69+
[Fact]
70+
public async Task ShouldThrowExceptionWhenStreamIsEmpty()
71+
{
72+
using (var images = new MagickImageCollection())
73+
{
74+
await Assert.ThrowsAsync<ArgumentException>("stream", () => images.ReadAsync(new MemoryStream(), MagickFormat.Png));
75+
}
76+
}
77+
78+
[Fact]
79+
public async Task ShouldUseTheCorrectReaderWhenFormatIsSet()
80+
{
81+
var bytes = Encoding.ASCII.GetBytes("%PDF-");
82+
83+
using (MemoryStream stream = new MemoryStream(bytes))
84+
{
85+
using (var images = new MagickImageCollection())
86+
{
87+
var exception = await Assert.ThrowsAsync<MagickCorruptImageErrorException>(() => images.ReadAsync(stream, MagickFormat.Png));
88+
89+
Assert.Contains("ReadPNGImage", exception.Message);
90+
}
91+
}
92+
}
93+
}
94+
95+
public class WithStreamAndMagickReadSettings
96+
{
97+
[Fact]
98+
public async Task ShouldThrowExceptionWhenStreamIsNull()
99+
{
100+
var settings = new MagickReadSettings();
101+
102+
using (var images = new MagickImageCollection())
103+
{
104+
await Assert.ThrowsAsync<ArgumentNullException>("stream", () => images.ReadAsync(null, settings));
105+
}
106+
}
107+
108+
[Fact]
109+
public async Task ShouldThrowExceptionWhenStreamIsEmpty()
110+
{
111+
var settings = new MagickReadSettings();
112+
113+
using (var images = new MagickImageCollection())
114+
{
115+
await Assert.ThrowsAsync<ArgumentException>("stream", () => images.ReadAsync(new MemoryStream(), settings));
116+
}
117+
}
118+
119+
[Fact]
120+
public async Task ShouldNotThrowExceptionWhenSettingsIsNull()
121+
{
122+
using (var fileStream = File.OpenRead(Files.CirclePNG))
123+
{
124+
using (var images = new MagickImageCollection())
125+
{
126+
await images.ReadAsync(fileStream, null);
127+
128+
Assert.Single(images);
129+
}
130+
}
131+
}
132+
133+
[Fact]
134+
public async Task ShouldUseTheCorrectReaderWhenFormatIsSet()
135+
{
136+
var bytes = Encoding.ASCII.GetBytes("%PDF-");
137+
var settings = new MagickReadSettings
138+
{
139+
Format = MagickFormat.Png,
140+
};
141+
142+
using (var stream = new MemoryStream(bytes))
143+
{
144+
using (var images = new MagickImageCollection())
145+
{
146+
var exception = await Assert.ThrowsAsync<MagickCorruptImageErrorException>(() => images.ReadAsync(stream, settings));
147+
148+
Assert.Contains("ReadPNGImage", exception.Message);
149+
}
150+
}
151+
}
152+
}
153+
}
154+
}
155+
}
156+
#endif

0 commit comments

Comments
 (0)