diff --git a/src/ImageProcessor.Playground/Program.cs b/src/ImageProcessor.Playground/Program.cs
index 80193905f..403acb323 100644
--- a/src/ImageProcessor.Playground/Program.cs
+++ b/src/ImageProcessor.Playground/Program.cs
@@ -79,17 +79,19 @@ namespace ImageProcessor.PlayGround
//.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer)
//.Constrain(size)
- //.Rotate(66)
+ //.Rotate(-64)
//.Mask(mask)
//.Format(new PngFormat())
//.BackgroundColor(Color.Cyan)
//.ReplaceColor(Color.FromArgb(255, 1, 107, 165), Color.FromArgb(255, 1, 165, 13), 80)
- .Resize(size)
- //.DetectEdges(new SobelEdgeFilter(), false)
+ //.Resize(size)
+ .DetectEdges(new SobelEdgeFilter(), true)
//.DetectEdges(new LaplacianOfGaussianEdgeFilter())
//.EntropyCrop()
//.Filter(MatrixFilters.Invert)
+ //.Contrast(50)
//.Filter(MatrixFilters.Comic)
+ //.Flip()
//.Filter(MatrixFilters.HiSatch)
//.Pixelate(8)
//.GaussianSharpen(10)
diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs
index 7b0acfdce..02d277bad 100644
--- a/src/ImageProcessor/ImageFactory.cs
+++ b/src/ImageProcessor/ImageFactory.cs
@@ -146,11 +146,20 @@ namespace ImageProcessor
throw new ImageFormatException("Input stream is not a supported format.");
}
+ MemoryStream memoryStream = new MemoryStream();
+
+ // Copy the stream. Disposal of the input stream is the responsibility
+ // of the user.
+ stream.CopyTo(memoryStream);
+
+ // Set the position to 0 afterwards.
+ stream.Position = memoryStream.Position = 0;
+
// Set our image as the memory stream value.
- this.Image = format.Load(stream);
+ this.Image = format.Load(memoryStream);
// Store the stream so we can dispose of it later.
- this.InputStream = stream;
+ this.InputStream = memoryStream;
// Set the other properties.
format.Quality = DefaultQuality;
@@ -242,6 +251,8 @@ namespace ImageProcessor
if (this.ShouldProcess)
{
// Set our new image as the memory stream value.
+ this.InputStream.Position = 0;
+
#if !__MonoCS__
Image newImage = Image.FromStream(this.InputStream, true);
#else
@@ -1027,7 +1038,7 @@ namespace ImageProcessor
if (this.ShouldProcess)
{
// Allow the same stream to be used as for input.
- stream.Seek(0, SeekOrigin.Begin);
+ stream.Position = 0;
this.Image = this.CurrentImageFormat.Save(stream, this.Image);
}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index d0f66a226..5112ef796 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -154,7 +154,7 @@
Code
-
+
diff --git a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs
index adf927d04..f344e400d 100644
--- a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs
+++ b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs
@@ -98,82 +98,6 @@ namespace ImageProcessor.Imaging.Formats
return ImageAnimator.CanAnimate(image);
}
- ///
- /// Returns information about the given .
- ///
- ///
- /// The image to extend.
- ///
- ///
- /// The image format.
- ///
- ///
- /// Whether to fetch the images frames.
- ///
- ///
- /// The .
- ///
- public static GifInfo GetGifInfo(Image image, ImageFormat format, bool fetchFrames = true)
- {
- if (image.RawFormat.Guid != ImageFormat.Gif.Guid && format.Guid != ImageFormat.Gif.Guid)
- {
- throw new ArgumentException("Image is not a gif.");
- }
-
- GifInfo info = new GifInfo
- {
- Height = image.Height,
- Width = image.Width
- };
-
- if (IsAnimated(image))
- {
- info.IsAnimated = true;
-
- if (fetchFrames)
- {
- int frameCount = image.GetFrameCount(FrameDimension.Time);
- int last = frameCount - 1;
- double length = 0;
-
- List gifFrames = new List();
-
- // Get the times stored in the gif.
- byte[] times = image.GetPropertyItem((int)ExifPropertyTag.FrameDelay).Value;
-
- for (int i = 0; i < frameCount; i++)
- {
- // Convert each 4-byte chunk into an integer.
- // GDI returns a single array with all delays, while Mono returns a different array for each frame.
- TimeSpan delay = TimeSpan.FromMilliseconds(BitConverter.ToInt32(times, (4 * i) % times.Length) * 10);
-
- // Find the frame
- image.SelectActiveFrame(FrameDimension.Time, i);
-
- // TODO: Get positions.
- gifFrames.Add(new GifFrame { Delay = delay, Image = new Bitmap(image) });
-
- // Reset the position.
- if (i == last)
- {
- image.SelectActiveFrame(FrameDimension.Time, 0);
- }
-
- length += delay.TotalMilliseconds;
- }
-
- info.GifFrames = gifFrames;
- info.AnimationLength = length;
-
- // Loop info is stored at byte 20737.
- info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem((int)ExifPropertyTag.LoopCount).Value, 0);
- info.IsLooped = info.LoopCount != 1;
- }
- }
-
- return info;
- }
-
///
/// Returns an instance of EncodingParameters for jpeg compression.
///
diff --git a/src/ImageProcessor/Imaging/Formats/GifDecoder.cs b/src/ImageProcessor/Imaging/Formats/GifDecoder.cs
new file mode 100644
index 000000000..a7008d162
--- /dev/null
+++ b/src/ImageProcessor/Imaging/Formats/GifDecoder.cs
@@ -0,0 +1,117 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// Decodes gifs to provides information.
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Imaging.Formats
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Drawing;
+ using System.Drawing.Imaging;
+
+ using ImageProcessor.Imaging.MetaData;
+
+ ///
+ /// Decodes gifs to provides information.
+ ///
+ public class GifDecoder
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The to decode.
+ ///
+ public GifDecoder(Image image)
+ {
+ this.Height = image.Height;
+ this.Width = image.Width;
+
+ if (FormatUtilities.IsAnimated(image))
+ {
+ this.IsAnimated = true;
+
+ if (this.IsAnimated)
+ {
+ int frameCount = image.GetFrameCount(FrameDimension.Time);
+ int last = frameCount - 1;
+ double length = 0;
+
+ List gifFrames = new List();
+
+ // Get the times stored in the gif.
+ byte[] times = image.GetPropertyItem((int)ExifPropertyTag.FrameDelay).Value;
+
+ for (int i = 0; i < frameCount; i++)
+ {
+ // Convert each 4-byte chunk into an integer.
+ // GDI returns a single array with all delays, while Mono returns a different array for each frame.
+ TimeSpan delay = TimeSpan.FromMilliseconds(BitConverter.ToInt32(times, (4 * i) % times.Length) * 10);
+
+ // Find the frame
+ image.SelectActiveFrame(FrameDimension.Time, i);
+
+ // TODO: Get positions.
+ gifFrames.Add(new GifFrame { Delay = delay, Image = new Bitmap(image) });
+
+ // Reset the position.
+ if (i == last)
+ {
+ image.SelectActiveFrame(FrameDimension.Time, 0);
+ }
+
+ length += delay.TotalMilliseconds;
+ }
+
+ this.GifFrames = gifFrames;
+ this.AnimationLength = length;
+
+ // Loop info is stored at byte 20737.
+ this.LoopCount = BitConverter.ToInt16(image.GetPropertyItem((int)ExifPropertyTag.LoopCount).Value, 0);
+ this.IsLooped = this.LoopCount != 1;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the image width.
+ ///
+ public int Width { get; set; }
+
+ ///
+ /// Gets or sets the image height.
+ ///
+ public int Height { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the image is animated.
+ ///
+ public bool IsAnimated { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the image is looped.
+ ///
+ public bool IsLooped { get; set; }
+
+ ///
+ /// Gets or sets the loop count.
+ ///
+ public int LoopCount { get; set; }
+
+ ///
+ /// Gets or sets the gif frames.
+ ///
+ public ICollection GifFrames { get; set; }
+
+ ///
+ /// Gets or sets the animation length in milliseconds.
+ ///
+ public double AnimationLength { get; set; }
+ }
+}
diff --git a/src/ImageProcessor/Imaging/Formats/GifFormat.cs b/src/ImageProcessor/Imaging/Formats/GifFormat.cs
index 8566e998b..a1819b3d8 100644
--- a/src/ImageProcessor/Imaging/Formats/GifFormat.cs
+++ b/src/ImageProcessor/Imaging/Formats/GifFormat.cs
@@ -74,18 +74,20 @@ namespace ImageProcessor.Imaging.Formats
/// The .
public override void ApplyProcessor(Func processor, ImageFactory factory)
{
- GifInfo info = FormatUtilities.GetGifInfo(factory.Image, this.ImageFormat);
+ //GifInfo info = FormatUtilities.GetGifInfo(factory.Image, this.ImageFormat);
- if (info.IsAnimated)
+ GifDecoder decoder = new GifDecoder(factory.Image);
+
+ if (decoder.IsAnimated)
{
OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
// We don't dispose of the memory stream as that is disposed when a new image is created and doing so
// beforehand will cause an exception.
MemoryStream stream = new MemoryStream();
- using (GifEncoder encoder = new GifEncoder(stream, null, null, info.LoopCount))
+ using (GifEncoder encoder = new GifEncoder(stream, null, null, decoder.LoopCount))
{
- foreach (GifFrame frame in info.GifFrames)
+ foreach (GifFrame frame in decoder.GifFrames)
{
factory.Image = frame.Image;
frame.Image = quantizer.Quantize(processor.Invoke(factory));
diff --git a/src/ImageProcessor/Imaging/Formats/GifInfo.cs b/src/ImageProcessor/Imaging/Formats/GifInfo.cs
deleted file mode 100644
index 43142971a..000000000
--- a/src/ImageProcessor/Imaging/Formats/GifInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South.
-// Licensed under the Apache License, Version 2.0.
-//
-//
-// Provides information about an image.
-//
-//
-// --------------------------------------------------------------------------------------------------------------------
-
-namespace ImageProcessor.Imaging.Formats
-{
- using System.Collections.Generic;
- using ImageProcessor.Imaging;
-
- ///
- /// Provides information about an image.
- ///
- ///
- public class GifInfo
- {
- ///
- /// Gets or sets the image width.
- ///
- public int Width { get; set; }
-
- ///
- /// Gets or sets the image height.
- ///
- public int Height { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the image is animated.
- ///
- public bool IsAnimated { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the image is looped.
- ///
- public bool IsLooped { get; set; }
-
- ///
- /// Gets or sets the loop count.
- ///
- public int LoopCount { get; set; }
-
- ///
- /// Gets or sets the gif frames.
- ///
- public ICollection GifFrames { get; set; }
-
- ///
- /// Gets or sets the animation length in milliseconds.
- ///
- public double AnimationLength { get; set; }
- }
-}
\ No newline at end of file