Browse Source

Streams are now better handled

Non-seekable streams are now copied rather than throwing exception.
Output stream position is set to 0 on save.


Former-commit-id: 78b65a6c5fc22922b238b813c7625b053ca605a3
Former-commit-id: 496b6a8cd2e972767a370bf5a5a04d99cdd8d4b2
Former-commit-id: 68c5dc773389a413282c6ebac2542784c6d26867
af/merge-core
James Jackson-South 10 years ago
parent
commit
4285f27786
  1. 75
      src/ImageProcessorCore/Image/Image.cs
  2. 31
      src/ImageProcessorCore/Image/ImageIOExtensions.cs

75
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;
/// <summary>
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes.
@ -218,10 +217,20 @@ namespace ImageProcessorCore
/// <param name="stream">The stream to save the image to.</param>
/// <param name="encoder">The encoder to save the image with.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
/// <returns>
/// The <see cref="Image{TColor,TPacked}"/>.
/// </returns>
public Image<TColor, TPacked> 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
/// </exception>
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());
}
/// <summary>
/// Decodes the image stream to the current image.
/// </summary>
/// <param name="stream">The stream.</param>
/// <returns>
/// The <see cref="bool"/>.
/// </returns>
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;
}
}
}

31
src/ImageProcessorCore/Image/ImageIOExtensions.cs

@ -22,10 +22,13 @@ namespace ImageProcessorCore
/// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsBmp<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream)
/// <returns>
/// The <see cref="Image{TColor,TPacked}"/>.
/// </returns>
public static Image<TColor, TPacked> SaveAsBmp<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream)
where TColor : IPackedVector<TPacked>
where TPacked : struct
=> new BmpEncoder().Encode(source, stream);
=> source.Save(stream, new BmpEncoder());
/// <summary>
/// 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.
/// </param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsPng<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream, int quality = int.MaxValue)
where TColor : IPackedVector<TPacked>
where TPacked : struct
=> new PngEncoder { Quality = quality }.Encode(source, stream);
/// <returns>
/// The <see cref="Image{TColor,TPacked}"/>.
/// </returns>
public static Image<TColor, TPacked> SaveAsPng<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream, int quality = int.MaxValue)
where TColor : IPackedVector<TPacked> where TPacked : struct
=> source.Save(stream, new PngEncoder { Quality = quality });
/// <summary>
/// Saves the image to the given stream with the jpeg format.
@ -52,10 +57,13 @@ namespace ImageProcessorCore
/// <param name="stream">The stream to save the image to.</param>
/// <param name="quality">The quality to save the image to. Between 1 and 100.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsJpeg<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream, int quality = 75)
/// <returns>
/// The <see cref="Image{TColor,TPacked}"/>.
/// </returns>
public static Image<TColor, TPacked> SaveAsJpeg<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream, int quality = 75)
where TColor : IPackedVector<TPacked>
where TPacked : struct
=> new JpegEncoder { Quality = quality }.Encode(source, stream);
=> source.Save(stream, new JpegEncoder { Quality = quality });
/// <summary>
/// Saves the image to the given stream with the gif format.
@ -66,9 +74,12 @@ namespace ImageProcessorCore
/// <param name="stream">The stream to save the image to.</param>
/// <param name="quality">The quality to save the image to representing the number of colors. Between 1 and 256.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
internal static void SaveAsGif<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream, int quality = 256)
/// <returns>
/// The <see cref="Image{TColor,TPacked}"/>.
/// </returns>
public static Image<TColor, TPacked> SaveAsGif<TColor, TPacked>(this Image<TColor, TPacked> source, Stream stream, int quality = 256)
where TColor : IPackedVector<TPacked>
where TPacked : struct
=> new GifEncoder { Quality = quality }.Encode(source, stream);
=> source.Save(stream, new GifEncoder { Quality = quality });
}
}

Loading…
Cancel
Save