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 namespace ImageProcessorCore
{ {
using System.IO;
using System.Text;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using Formats; using Formats;
using System.Diagnostics;
/// <summary> /// <summary>
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. /// 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="stream">The stream to save the image to.</param>
/// <param name="encoder">The encoder to save the image with.</param> /// <param name="encoder">The encoder to save the image with.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception> /// <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) public Image<TColor, TPacked> Save(Stream stream, IImageEncoder encoder)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
encoder.Encode(this, stream); encoder.Encode(this, stream);
// Reset to the start of the stream.
if (stream.CanSeek)
{
stream.Position = 0;
}
return this; return this;
} }
@ -270,18 +279,58 @@ namespace ImageProcessorCore
/// </exception> /// </exception>
private void Load(Stream stream) private void Load(Stream stream)
{ {
if (!this.Formats.Any()) { return; } if (!this.Formats.Any())
{
return;
}
if (!stream.CanRead) if (!stream.CanRead)
{ {
throw new NotSupportedException("Cannot read from the stream."); 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); int maxHeaderSize = this.Formats.Max(x => x.Decoder.HeaderSize);
if (maxHeaderSize > 0) if (maxHeaderSize > 0)
{ {
@ -296,19 +345,11 @@ namespace ImageProcessorCore
{ {
format.Decoder.Decode(this, stream); format.Decoder.Decode(this, stream);
this.CurrentImageFormat = format; this.CurrentImageFormat = format;
return; return true;
} }
} }
StringBuilder stringBuilder = new StringBuilder(); return false;
stringBuilder.AppendLine("Image cannot be loaded. Available formats:");
foreach (IImageFormat format in this.Formats)
{
stringBuilder.AppendLine("-" + format);
}
throw new NotSupportedException(stringBuilder.ToString());
} }
} }
} }

31
src/ImageProcessorCore/Image/ImageIOExtensions.cs

@ -22,10 +22,13 @@ namespace ImageProcessorCore
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param> /// <param name="stream">The stream to save the image to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception> /// <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 TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
=> new BmpEncoder().Encode(source, stream); => source.Save(stream, new BmpEncoder());
/// <summary> /// <summary>
/// Saves the image to the given stream with the png format. /// 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. /// Anything equal to 256 and below will cause the encoder to save the image in an indexed format.
/// </param> /// </param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception> /// <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) /// <returns>
where TColor : IPackedVector<TPacked> /// The <see cref="Image{TColor,TPacked}"/>.
where TPacked : struct /// </returns>
=> new PngEncoder { Quality = quality }.Encode(source, stream); 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> /// <summary>
/// Saves the image to the given stream with the jpeg format. /// 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="stream">The stream to save the image to.</param>
/// <param name="quality">The quality to save the image to. Between 1 and 100.</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> /// <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 TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
=> new JpegEncoder { Quality = quality }.Encode(source, stream); => source.Save(stream, new JpegEncoder { Quality = quality });
/// <summary> /// <summary>
/// Saves the image to the given stream with the gif format. /// 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="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> /// <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> /// <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 TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
=> new GifEncoder { Quality = quality }.Encode(source, stream); => source.Save(stream, new GifEncoder { Quality = quality });
} }
} }

Loading…
Cancel
Save