@@ -18,27 +18,29 @@ namespace SixLabors.ImageSharp
1818 public static partial class ImageExtensions
1919 {
2020 /// <summary>
21- /// Writes the image to the given stream using the currently loaded image format .
21+ /// Writes the image to the given file path using an encoder detected from the path .
2222 /// </summary>
2323 /// <param name="source">The source image.</param>
2424 /// <param name="path">The file path to save the image to.</param>
2525 /// <exception cref="ArgumentNullException">The path is null.</exception>
26+ /// <exception cref="NotSupportedException">No encoder available for provided path.</exception>
2627 public static void Save ( this Image source , string path )
2728 => source . Save ( path , source . DetectEncoder ( path ) ) ;
2829
2930 /// <summary>
30- /// Writes the image to the given stream using the currently loaded image format .
31+ /// Writes the image to the given file path using an encoder detected from the path .
3132 /// </summary>
3233 /// <param name="source">The source image.</param>
3334 /// <param name="path">The file path to save the image to.</param>
3435 /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
3536 /// <exception cref="ArgumentNullException">The path is null.</exception>
37+ /// <exception cref="NotSupportedException">No encoder available for provided path.</exception>
3638 /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
3739 public static Task SaveAsync ( this Image source , string path , CancellationToken cancellationToken = default )
3840 => source . SaveAsync ( path , source . DetectEncoder ( path ) , cancellationToken ) ;
3941
4042 /// <summary>
41- /// Writes the image to the given stream using the currently loaded image format .
43+ /// Writes the image to the given file path using the given image encoder .
4244 /// </summary>
4345 /// <param name="source">The source image.</param>
4446 /// <param name="path">The file path to save the image to.</param>
@@ -56,7 +58,7 @@ public static void Save(this Image source, string path, IImageEncoder encoder)
5658 }
5759
5860 /// <summary>
59- /// Writes the image to the given stream using the currently loaded image format .
61+ /// Writes the image to the given file path using the given image encoder .
6062 /// </summary>
6163 /// <param name="source">The source image.</param>
6264 /// <param name="path">The file path to save the image to.</param>
@@ -73,12 +75,15 @@ public static async Task SaveAsync(
7375 {
7476 Guard . NotNull ( path , nameof ( path ) ) ;
7577 Guard . NotNull ( encoder , nameof ( encoder ) ) ;
76- using Stream fs = source . GetConfiguration ( ) . FileSystem . Create ( path ) ;
77- await source . SaveAsync ( fs , encoder , cancellationToken ) . ConfigureAwait ( false ) ;
78+
79+ using ( Stream fs = source . GetConfiguration ( ) . FileSystem . Create ( path ) )
80+ {
81+ await source . SaveAsync ( fs , encoder , cancellationToken ) . ConfigureAwait ( false ) ;
82+ }
7883 }
7984
8085 /// <summary>
81- /// Writes the image to the given stream using the currently loaded image format.
86+ /// Writes the image to the given stream using the given image format.
8287 /// </summary>
8388 /// <param name="source">The source image.</param>
8489 /// <param name="stream">The stream to save the image to.</param>
@@ -115,6 +120,50 @@ public static void Save(this Image source, Stream stream, IImageFormat format)
115120 source . Save ( stream , encoder ) ;
116121 }
117122
123+ /// <summary>
124+ /// Writes the image to the given stream using the given image format.
125+ /// </summary>
126+ /// <param name="source">The source image.</param>
127+ /// <param name="stream">The stream to save the image to.</param>
128+ /// <param name="format">The format to save the image in.</param>
129+ /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
130+ /// <exception cref="ArgumentNullException">The stream is null.</exception>
131+ /// <exception cref="ArgumentNullException">The format is null.</exception>
132+ /// <exception cref="NotSupportedException">The stream is not writable.</exception>
133+ /// <exception cref="NotSupportedException">No encoder available for provided format.</exception>
134+ /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
135+ public static Task SaveAsync (
136+ this Image source ,
137+ Stream stream ,
138+ IImageFormat format ,
139+ CancellationToken cancellationToken = default )
140+ {
141+ Guard . NotNull ( stream , nameof ( stream ) ) ;
142+ Guard . NotNull ( format , nameof ( format ) ) ;
143+
144+ if ( ! stream . CanWrite )
145+ {
146+ throw new NotSupportedException ( "Cannot write to the stream." ) ;
147+ }
148+
149+ IImageEncoder encoder = source . GetConfiguration ( ) . ImageFormatsManager . FindEncoder ( format ) ;
150+
151+ if ( encoder is null )
152+ {
153+ var sb = new StringBuilder ( ) ;
154+ sb . AppendLine ( "No encoder was found for the provided mime type. Registered encoders include:" ) ;
155+
156+ foreach ( KeyValuePair < IImageFormat , IImageEncoder > val in source . GetConfiguration ( ) . ImageFormatsManager . ImageEncoders )
157+ {
158+ sb . AppendFormat ( " - {0} : {1}{2}" , val . Key . Name , val . Value . GetType ( ) . Name , Environment . NewLine ) ;
159+ }
160+
161+ throw new NotSupportedException ( sb . ToString ( ) ) ;
162+ }
163+
164+ return source . SaveAsync ( stream , encoder , cancellationToken ) ;
165+ }
166+
118167 /// <summary>
119168 /// Returns a Base64 encoded string from the given image.
120169 /// The result is prepended with a Data URI <see href="https://en.wikipedia.org/wiki/Data_URI_scheme"/>
0 commit comments