@@ -38,7 +38,7 @@ public static IImageFormat DetectFormat(Stream stream)
3838 /// <exception cref="NotSupportedException">The stream is not readable.</exception>
3939 /// <returns>The format type or null if none found.</returns>
4040 public static IImageFormat DetectFormat ( Configuration configuration , Stream stream )
41- => WithSeekableStream ( configuration , stream , false , s => InternalDetectFormat ( s , configuration ) ) ;
41+ => WithSeekableStream ( configuration , stream , s => InternalDetectFormat ( s , configuration ) , false ) ;
4242
4343 /// <summary>
4444 /// By reading the header on the provided stream this calculates the images format type.
@@ -63,7 +63,8 @@ public static Task<IImageFormat> DetectFormatAsync(Configuration configuration,
6363 => WithSeekableStreamAsync (
6464 configuration ,
6565 stream ,
66- s => InternalDetectFormatAsync ( s , configuration ) ) ;
66+ s => InternalDetectFormatAsync ( s , configuration ) ,
67+ false ) ;
6768
6869 /// <summary>
6970 /// Reads the raw image information from the specified stream without fully decoding it.
@@ -155,7 +156,7 @@ public static async Task<IImageInfo> IdentifyAsync(Configuration configuration,
155156 /// </returns>
156157 public static IImageInfo Identify ( Configuration configuration , Stream stream , out IImageFormat format )
157158 {
158- ( IImageInfo ImageInfo , IImageFormat format ) data = WithSeekableStream ( configuration , stream , false , s => InternalIdentity ( s , configuration ?? Configuration . Default ) ) ;
159+ ( IImageInfo ImageInfo , IImageFormat Format ) data = WithSeekableStream ( configuration , stream , s => InternalIdentity ( s , configuration ?? Configuration . Default ) ) ;
159160
160161 format = data . Format ;
161162 return data . ImageInfo ;
@@ -291,7 +292,7 @@ public static Task<Image> LoadAsync(Stream stream, IImageDecoder decoder)
291292 /// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
292293 /// <returns>A new <see cref="Image"/>.</returns>
293294 public static Image Load ( Configuration configuration , Stream stream , IImageDecoder decoder )
294- => WithSeekableStream ( configuration , stream , true , s => decoder . Decode ( configuration , s ) ) ;
295+ => WithSeekableStream ( configuration , stream , s => decoder . Decode ( configuration , s ) ) ;
295296
296297 /// <summary>
297298 /// Decode a new instance of the <see cref="Image"/> class from the given stream.
@@ -416,7 +417,7 @@ public static Image<TPixel> Load<TPixel>(Stream stream, out IImageFormat format)
416417 /// <returns>A new <see cref="Image{TPixel}"/>.</returns>
417418 public static Image < TPixel > Load < TPixel > ( Stream stream , IImageDecoder decoder )
418419 where TPixel : unmanaged, IPixel < TPixel >
419- => WithSeekableStream ( Configuration . Default , stream , true , s => decoder . Decode < TPixel > ( Configuration . Default , s ) ) ;
420+ => WithSeekableStream ( Configuration . Default , stream , s => decoder . Decode < TPixel > ( Configuration . Default , s ) ) ;
420421
421422 /// <summary>
422423 /// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@@ -451,7 +452,7 @@ public static Task<Image<TPixel>> LoadAsync<TPixel>(Stream stream, IImageDecoder
451452 /// <returns>A new <see cref="Image{TPixel}"/>.</returns>
452453 public static Image < TPixel > Load < TPixel > ( Configuration configuration , Stream stream , IImageDecoder decoder )
453454 where TPixel : unmanaged, IPixel < TPixel >
454- => WithSeekableStream ( configuration , stream , true , s => decoder . Decode < TPixel > ( configuration , s ) ) ;
455+ => WithSeekableStream ( configuration , stream , s => decoder . Decode < TPixel > ( configuration , s ) ) ;
455456
456457 /// <summary>
457458 /// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@@ -505,7 +506,7 @@ public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream str
505506 public static Image < TPixel > Load < TPixel > ( Configuration configuration , Stream stream , out IImageFormat format )
506507 where TPixel : unmanaged, IPixel < TPixel >
507508 {
508- ( Image < TPixel > Image , IImageFormat Format ) data = WithSeekableStream ( configuration , stream , true , s => Decode < TPixel > ( s , configuration ) ) ;
509+ ( Image < TPixel > Image , IImageFormat Format ) data = WithSeekableStream ( configuration , stream , s => Decode < TPixel > ( s , configuration ) ) ;
509510
510511 format = data . Format ;
511512
@@ -632,7 +633,7 @@ public static async Task<Image<TPixel>> LoadAsync<TPixel>(Configuration configur
632633 /// <returns>A new <see cref="Image{TPixel}"/>.</returns>
633634 public static Image Load ( Configuration configuration , Stream stream , out IImageFormat format )
634635 {
635- ( Image img , IImageFormat format ) data = WithSeekableStream ( configuration , stream , true , s => Decode ( s , configuration ) ) ;
636+ ( Image img , IImageFormat format ) data = WithSeekableStream ( configuration , stream , s => Decode ( s , configuration ) ) ;
636637
637638 format = data . format ;
638639
@@ -652,7 +653,24 @@ public static Image Load(Configuration configuration, Stream stream, out IImageF
652653 throw new UnknownImageFormatException ( sb . ToString ( ) ) ;
653654 }
654655
655- private static T WithSeekableStream < T > ( Configuration configuration , Stream stream , bool buffer , Func < Stream , T > action )
656+ /// <summary>
657+ /// Performs the given action against the stream ensuring that it is seekable.
658+ /// </summary>
659+ /// <typeparam name="T">The type of object returned from the action.</typeparam>
660+ /// <param name="configuration">The configuration.</param>
661+ /// <param name="stream">The input stream.</param>
662+ /// <param name="action">The action to perform.</param>
663+ /// <param name="buffer">
664+ /// Whether to buffer the input stream.
665+ /// Short intial reads like <see cref="DetectFormat(Configuration, Stream)"/> do not require
666+ /// the overhead of reading the stream to the buffer. Defaults to <see langword="true"/>.
667+ /// </param>
668+ /// <returns>The <typeparamref name="T"/>.</returns>
669+ private static T WithSeekableStream < T > (
670+ Configuration configuration ,
671+ Stream stream ,
672+ Func < Stream , T > action ,
673+ bool buffer = true )
656674 {
657675 Guard . NotNull ( configuration , nameof ( configuration ) ) ;
658676 Guard . NotNull ( stream , nameof ( stream ) ) ;
@@ -684,14 +702,34 @@ private static T WithSeekableStream<T>(Configuration configuration, Stream strea
684702 stream . CopyTo ( memoryStream ) ;
685703 memoryStream . Position = 0 ;
686704
705+ if ( buffer )
706+ {
707+ using var bufferedStream = new BufferedReadStream ( memoryStream ) ;
708+ return action ( bufferedStream ) ;
709+ }
710+
687711 return action ( memoryStream ) ;
688712 }
689713 }
690714
715+ /// <summary>
716+ /// Performs the given action asynchronously against the stream ensuring that it is seekable.
717+ /// </summary>
718+ /// <typeparam name="T">The type of object returned from the action.</typeparam>
719+ /// <param name="configuration">The configuration.</param>
720+ /// <param name="stream">The input stream.</param>
721+ /// <param name="action">The action to perform.</param>
722+ /// <param name="buffer">
723+ /// Whether to buffer the input stream.
724+ /// Short intial reads like <see cref="DetectFormat(Configuration, Stream)"/> do not require
725+ /// the overhead of reading the stream to the buffer. Defaults to <see langword="true"/>.
726+ /// </param>
727+ /// <returns>The <see cref="Task{T}"/>.</returns>
691728 private static async Task < T > WithSeekableStreamAsync < T > (
692729 Configuration configuration ,
693730 Stream stream ,
694- Func < Stream , Task < T > > action )
731+ Func < Stream , Task < T > > action ,
732+ bool buffer = true )
695733 {
696734 Guard . NotNull ( configuration , nameof ( configuration ) ) ;
697735 Guard . NotNull ( stream , nameof ( stream ) ) ;
@@ -712,6 +750,12 @@ private static async Task<T> WithSeekableStreamAsync<T>(
712750 stream . Position = 0 ;
713751 }
714752
753+ if ( buffer )
754+ {
755+ using var bufferedStream = new BufferedReadStream ( stream ) ;
756+ return await action ( bufferedStream ) . ConfigureAwait ( false ) ;
757+ }
758+
715759 return await action ( stream ) . ConfigureAwait ( false ) ;
716760 }
717761
@@ -720,6 +764,12 @@ private static async Task<T> WithSeekableStreamAsync<T>(
720764 await stream . CopyToAsync ( memoryStream ) . ConfigureAwait ( false ) ;
721765 memoryStream . Position = 0 ;
722766
767+ if ( buffer )
768+ {
769+ using var bufferedStream = new BufferedReadStream ( memoryStream ) ;
770+ return await action ( bufferedStream ) . ConfigureAwait ( false ) ;
771+ }
772+
723773 return await action ( memoryStream ) . ConfigureAwait ( false ) ;
724774 }
725775 }
0 commit comments