diff --git a/src/ImageProcessorCore/Image/Image.cs b/src/ImageProcessorCore/Image/Image.cs index 960e5e26c2..b36d9d707b 100644 --- a/src/ImageProcessorCore/Image/Image.cs +++ b/src/ImageProcessorCore/Image/Image.cs @@ -5,15 +5,14 @@ namespace ImageProcessorCore { - using System.IO; - using System.Text; - using System; using System.Collections.Generic; + using System.Diagnostics; + using System.IO; using System.Linq; + using System.Text; using Formats; - using System.Diagnostics; /// /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. @@ -218,10 +217,20 @@ namespace ImageProcessorCore /// The stream to save the image to. /// The encoder to save the image with. /// Thrown if the stream is null. + /// + /// The . + /// public Image Save(Stream stream, IImageEncoder encoder) { Guard.NotNull(stream, nameof(stream)); encoder.Encode(this, stream); + + // Reset to the start of the stream. + if (stream.CanSeek) + { + stream.Position = 0; + } + return this; } @@ -270,18 +279,58 @@ namespace ImageProcessorCore /// private void Load(Stream stream) { - if (!this.Formats.Any()) { return; } + if (!this.Formats.Any()) + { + return; + } if (!stream.CanRead) { throw new NotSupportedException("Cannot read from the stream."); } - if (!stream.CanSeek) + if (stream.CanSeek) + { + if (this.Decode(stream)) + { + return; + } + } + else + { + // We want to be able to load images from things like HttpContext.Request.Body + using (MemoryStream ms = new MemoryStream()) + { + stream.CopyTo(ms); + ms.Position = 0; + + if (this.Decode(stream)) + { + return; + } + } + } + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("Image cannot be loaded. Available formats:"); + + foreach (IImageFormat format in this.Formats) { - throw new NotSupportedException("The stream does not support seeking."); + stringBuilder.AppendLine("-" + format); } + throw new NotSupportedException(stringBuilder.ToString()); + } + + /// + /// Decodes the image stream to the current image. + /// + /// The stream. + /// + /// The . + /// + private bool Decode(Stream stream) + { int maxHeaderSize = this.Formats.Max(x => x.Decoder.HeaderSize); if (maxHeaderSize > 0) { @@ -296,19 +345,11 @@ namespace ImageProcessorCore { format.Decoder.Decode(this, stream); this.CurrentImageFormat = format; - return; + return true; } } - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine("Image cannot be loaded. Available formats:"); - - foreach (IImageFormat format in this.Formats) - { - stringBuilder.AppendLine("-" + format); - } - - throw new NotSupportedException(stringBuilder.ToString()); + return false; } } } diff --git a/src/ImageProcessorCore/Image/ImageIOExtensions.cs b/src/ImageProcessorCore/Image/ImageIOExtensions.cs index 9241a58edb..85d9fe3fe5 100644 --- a/src/ImageProcessorCore/Image/ImageIOExtensions.cs +++ b/src/ImageProcessorCore/Image/ImageIOExtensions.cs @@ -22,10 +22,13 @@ namespace ImageProcessorCore /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. - public static void SaveAsBmp(this Image source, Stream stream) + /// + /// The . + /// + public static Image SaveAsBmp(this Image source, Stream stream) where TColor : IPackedVector where TPacked : struct - => new BmpEncoder().Encode(source, stream); + => source.Save(stream, new BmpEncoder()); /// /// Saves the image to the given stream with the png format. @@ -38,10 +41,12 @@ namespace ImageProcessorCore /// Anything equal to 256 and below will cause the encoder to save the image in an indexed format. /// /// Thrown if the stream is null. - public static void SaveAsPng(this Image source, Stream stream, int quality = int.MaxValue) - where TColor : IPackedVector - where TPacked : struct - => new PngEncoder { Quality = quality }.Encode(source, stream); + /// + /// The . + /// + public static Image SaveAsPng(this Image source, Stream stream, int quality = int.MaxValue) + where TColor : IPackedVector where TPacked : struct + => source.Save(stream, new PngEncoder { Quality = quality }); /// /// Saves the image to the given stream with the jpeg format. @@ -52,10 +57,13 @@ namespace ImageProcessorCore /// The stream to save the image to. /// The quality to save the image to. Between 1 and 100. /// Thrown if the stream is null. - public static void SaveAsJpeg(this Image source, Stream stream, int quality = 75) + /// + /// The . + /// + public static Image SaveAsJpeg(this Image source, Stream stream, int quality = 75) where TColor : IPackedVector where TPacked : struct - => new JpegEncoder { Quality = quality }.Encode(source, stream); + => source.Save(stream, new JpegEncoder { Quality = quality }); /// /// Saves the image to the given stream with the gif format. @@ -66,9 +74,12 @@ namespace ImageProcessorCore /// The stream to save the image to. /// The quality to save the image to representing the number of colors. Between 1 and 256. /// Thrown if the stream is null. - internal static void SaveAsGif(this Image source, Stream stream, int quality = 256) + /// + /// The . + /// + public static Image SaveAsGif(this Image source, Stream stream, int quality = 256) where TColor : IPackedVector where TPacked : struct - => new GifEncoder { Quality = quality }.Encode(source, stream); + => source.Save(stream, new GifEncoder { Quality = quality }); } }