Browse Source

More refactorings

Former-commit-id: f2f5eaa2be637b1eb47979700e061df51c19e85b
af/merge-core
James South 12 years ago
parent
commit
ba967bd7ad
  1. 98
      src/ImageProcessor/Core/Common/Extensions/ImageExtensions.cs
  2. 151
      src/ImageProcessor/Core/Common/Extensions/ImageFormatExtensions.cs
  3. 4
      src/ImageProcessor/ImageFactory.cs
  4. 9
      src/ImageProcessor/ImageProcessor.csproj
  5. 119
      src/ImageProcessor/Imaging/Formats/FormatUtilities.cs
  6. 4
      src/ImageProcessor/Imaging/Formats/GifEncoder.cs
  7. 13
      src/ImageProcessor/Imaging/Formats/GifFormat.cs
  8. 2
      src/ImageProcessor/Imaging/Formats/GifFrame.cs
  9. 12
      src/ImageProcessor/Imaging/Formats/GifInfo.cs
  10. 4
      src/ImageProcessor/Imaging/Formats/JpegFormat.cs
  11. 78
      src/ImageProcessor/Imaging/ImageUtils.cs

98
src/ImageProcessor/Core/Common/Extensions/ImageExtensions.cs

@ -1,98 +0,0 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates a series of time saving extension methods to the <see cref="T:System.Drawing.Imaging.Image" /> class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Core.Common.Extensions
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using ImageProcessor.Imaging;
/// <summary>
/// Encapsulates a series of time saving extension methods to the <see cref="T:System.Drawing.Imaging.Image" /> class.
/// </summary>
public static class ImageExtensions
{
/// <summary>
/// Returns information about the given <see cref="System.Drawing.Image"/>.
/// </summary>
/// <param name="image">
/// The image to extend.
/// </param>
/// <param name="format">
/// The image format.
/// </param>
/// <param name="fetchFrames">
/// Whether to fetch the images frames.
/// </param>
/// <returns>
/// The <see cref="ImageInfo"/>.
/// </returns>
public static ImageInfo GetImageInfo(this Image image, ImageFormat format, bool fetchFrames = true)
{
ImageInfo info = new ImageInfo
{
Height = image.Height,
Width = image.Width,
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
IsIndexed = (image.PixelFormat & PixelFormat.Indexed) != 0
};
if (image.RawFormat.Guid == ImageFormat.Gif.Guid && format.Guid == ImageFormat.Gif.Guid)
{
if (ImageAnimator.CanAnimate(image))
{
info.IsAnimated = true;
if (fetchFrames)
{
FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]);
int frameCount = image.GetFrameCount(frameDimension);
int last = frameCount - 1;
int delay = 0;
int index = 0;
List<GifFrame> gifFrames = new List<GifFrame>();
for (int f = 0; f < frameCount; f++)
{
int thisDelay = BitConverter.ToInt32(image.GetPropertyItem(20736).Value, index);
int toAddDelay = thisDelay * 10 < 20 ? 20 : thisDelay * 10; // Minimum delay is 20 ms
// Find the frame
image.SelectActiveFrame(frameDimension, f);
// TODO: Get positions.
gifFrames.Add(new GifFrame { Delay = toAddDelay, Image = (Image)image.Clone() });
// Reset the position.
if (f == last)
{
image.SelectActiveFrame(frameDimension, 0);
}
delay += toAddDelay;
index += 4;
}
info.GifFrames = gifFrames;
info.AnimationLength = delay;
// Loop info is stored at byte 20737.
info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0);
info.IsLooped = info.LoopCount != 1;
}
}
}
return info;
}
}
}

151
src/ImageProcessor/Core/Common/Extensions/ImageFormatExtensions.cs

@ -1,151 +0,0 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageFormatExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates a series of time saving extension methods to the <see cref="T:System.Drawing.Imaging.ImageFormat" />
// class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Core.Common.Extensions
{
#region
using System.Drawing.Imaging;
using System.Linq;
#endregion
/// <summary>
/// Encapsulates a series of time saving extension methods to the <see cref="T:System.Drawing.Imaging.ImageFormat" /> class.
/// </summary>
public static class ImageFormatExtensions
{
/// <summary>
/// Gets the correct mime-type for the given <see cref="T:System.Drawing.Imaging.ImageFormat" />.
/// </summary>
/// <param name="imageFormat">The <see cref="T:System.Drawing.Imaging.ImageFormat" />.</param>
/// <returns>The correct mime-type for the given <see cref="T:System.Drawing.Imaging.ImageFormat" />.</returns>
public static string GetMimeType(this ImageFormat imageFormat)
{
if (imageFormat.Equals(ImageFormat.Icon))
{
return "image/x-icon";
}
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
return codecs.First(codec => codec.FormatID == imageFormat.Guid).MimeType;
}
/// <summary>
/// Gets the name for the given <see cref="T:System.Drawing.Imaging.ImageFormat" />.
/// </summary>
/// <param name="format">
/// The <see cref="T:System.Drawing.Imaging.ImageFormat" /> to get the name for.
/// </param>
/// <returns>
/// The <see cref="string"/> representing the name of the <see cref="T:System.Drawing.Imaging.ImageFormat" />.
/// </returns>
public static string GetName(this ImageFormat format)
{
if (format.Guid == ImageFormat.MemoryBmp.Guid)
{
return "MemoryBMP";
}
if (format.Guid == ImageFormat.Bmp.Guid)
{
return "Bmp";
}
if (format.Guid == ImageFormat.Emf.Guid)
{
return "Emf";
}
if (format.Guid == ImageFormat.Wmf.Guid)
{
return "Wmf";
}
if (format.Guid == ImageFormat.Gif.Guid)
{
return "Gif";
}
if (format.Guid == ImageFormat.Jpeg.Guid)
{
return "Jpeg";
}
if (format.Guid == ImageFormat.Png.Guid)
{
return "Png";
}
if (format.Guid == ImageFormat.Tiff.Guid)
{
return "Tiff";
}
if (format.Guid == ImageFormat.Exif.Guid)
{
return "Exif";
}
if (format.Guid == ImageFormat.Icon.Guid)
{
return "Icon";
}
return "[ImageFormat: " + format.Guid + "]";
}
/// <summary>
/// Returns the correct file extension for the given <see cref="T:System.Drawing.Imaging.ImageFormat"/>.
/// </summary>
/// <param name="imageFormat">
/// The <see cref="T:System.Drawing.Imaging.ImageFormat"/> to return the extension for.
/// </param>
/// <param name="originalExtension">
/// The original Extension.
/// </param>
/// <returns>
/// The correct file extension for the given <see cref="T:System.Drawing.Imaging.ImageFormat"/>.
/// </returns>
public static string GetFileExtension(this ImageFormat imageFormat, string originalExtension)
{
string name = imageFormat.GetName();
switch (name)
{
case "Icon":
return ".ico";
case "Gif":
return ".gif";
case "Bmp":
return ".bmp";
case "Png":
return ".png";
case "Tiff":
if (!string.IsNullOrWhiteSpace(originalExtension) && originalExtension.ToUpperInvariant() == ".TIF")
{
return ".tif";
}
return ".tiff";
case "Jpeg":
if (!string.IsNullOrWhiteSpace(originalExtension) && originalExtension.ToUpperInvariant() == ".JPG")
{
return ".jpg";
}
break;
}
return null;
}
}
}

4
src/ImageProcessor/ImageFactory.cs

@ -152,7 +152,7 @@ namespace ImageProcessor
// Set the other properties.
format.Quality = DefaultQuality;
format.IsIndexed = ImageUtils.IsIndexed(this.Image);
format.IsIndexed = FormatUtilities.IsIndexed(this.Image);
this.backupFormat = format;
this.CurrentImageFormat = format;
@ -207,7 +207,7 @@ namespace ImageProcessor
// Set the other properties.
format.Quality = DefaultQuality;
format.IsIndexed = ImageUtils.IsIndexed(this.Image);
format.IsIndexed = FormatUtilities.IsIndexed(this.Image);
this.backupFormat = format;
this.CurrentImageFormat = format;

9
src/ImageProcessor/ImageProcessor.csproj

@ -63,9 +63,7 @@
<Compile Include="Configuration\ImageProcessorBootstrapper.cs" />
<Compile Include="Core\Common\Exceptions\ImageProcessingException.cs" />
<Compile Include="Core\Common\Extensions\DoubleExtensions.cs" />
<Compile Include="Core\Common\Extensions\ImageExtensions.cs" />
<Compile Include="Core\Common\Extensions\ImageFormatExtensions.cs" />
<Compile Include="Core\Common\Extensions\ImageInfo.cs" />
<Compile Include="Imaging\Formats\GifInfo.cs" />
<Compile Include="Core\Common\Extensions\IntegerExtensions.cs" />
<Compile Include="Core\Common\Extensions\StringExtensions.cs" />
<Compile Include="Core\Common\Exceptions\ImageFormatException.cs" />
@ -87,8 +85,8 @@
<Compile Include="Imaging\Formats\FormatBase.cs" />
<Compile Include="Imaging\Formats\ISupportedImageFormat.cs" />
<Compile Include="Imaging\GaussianLayer.cs" />
<Compile Include="Imaging\GifEncoder.cs" />
<Compile Include="Imaging\GifFrame.cs" />
<Compile Include="Imaging\Formats\GifEncoder.cs" />
<Compile Include="Imaging\Formats\GifFrame.cs" />
<Compile Include="Imaging\Quantizer.cs" />
<Compile Include="Imaging\ResizeLayer.cs" />
<Compile Include="Imaging\Filters\BlackWhiteMatrixFilter.cs" />
@ -103,7 +101,6 @@
<Compile Include="Imaging\Filters\PolaroidMatrixFilter.cs" />
<Compile Include="Imaging\Filters\SepiaMatrixFilter.cs" />
<Compile Include="Imaging\Filters\IMatrixFilter.cs" />
<Compile Include="Imaging\ImageUtils.cs" />
<Compile Include="Imaging\ResizeMode.cs" />
<Compile Include="Imaging\ResponseType.cs" />
<Compile Include="Imaging\RoundedCornerLayer.cs" />

119
src/ImageProcessor/Imaging/Formats/FormatUtilities.cs

@ -16,6 +16,8 @@ namespace ImageProcessor.Imaging.Formats
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using ImageProcessor.Configuration;
/// <summary>
@ -94,5 +96,120 @@ namespace ImageProcessor.Imaging.Formats
{
return ImageAnimator.CanAnimate(image);
}
/// <summary>
/// Returns information about the given <see cref="System.Drawing.Image"/>.
/// </summary>
/// <param name="image">
/// The image to extend.
/// </param>
/// <param name="format">
/// The image format.
/// </param>
/// <param name="fetchFrames">
/// Whether to fetch the images frames.
/// </param>
/// <returns>
/// The <see cref="GifInfo"/>.
/// </returns>
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)
{
FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]);
int frameCount = image.GetFrameCount(frameDimension);
int last = frameCount - 1;
int delay = 0;
int index = 0;
List<GifFrame> gifFrames = new List<GifFrame>();
for (int f = 0; f < frameCount; f++)
{
int thisDelay = BitConverter.ToInt32(image.GetPropertyItem(20736).Value, index);
int toAddDelay = thisDelay * 10 < 20 ? 20 : thisDelay * 10; // Minimum delay is 20 ms
// Find the frame
image.SelectActiveFrame(frameDimension, f);
// TODO: Get positions.
gifFrames.Add(new GifFrame { Delay = toAddDelay, Image = (Image)image.Clone() });
// Reset the position.
if (f == last)
{
image.SelectActiveFrame(frameDimension, 0);
}
delay += toAddDelay;
index += 4;
}
info.GifFrames = gifFrames;
info.AnimationLength = delay;
// Loop info is stored at byte 20737.
info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0);
info.IsLooped = info.LoopCount != 1;
}
}
return info;
}
/// <summary>
/// Returns an instance of EncodingParameters for jpeg compression.
/// </summary>
/// <param name="quality">The quality to return the image at.</param>
/// <returns>The encodingParameters for jpeg compression. </returns>
public static EncoderParameters GetEncodingParameters(int quality)
{
EncoderParameters encoderParameters = null;
try
{
// Create a series of encoder parameters.
encoderParameters = new EncoderParameters(1);
// Set the quality.
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
}
catch
{
if (encoderParameters != null)
{
encoderParameters.Dispose();
}
}
return encoderParameters;
}
/// <summary>
/// Uses reflection to allow the creation of an instance of <see cref="PropertyItem"/>.
/// </summary>
/// <returns>
/// The <see cref="PropertyItem"/>.
/// </returns>
public static PropertyItem CreatePropertyItem()
{
Type type = typeof(PropertyItem);
ConstructorInfo constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
return (PropertyItem)constructor.Invoke(null);
}
}
}
}

4
src/ImageProcessor/Imaging/GifEncoder.cs → src/ImageProcessor/Imaging/Formats/GifEncoder.cs

@ -14,14 +14,12 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging
namespace ImageProcessor.Imaging.Formats
{
#region Using
using System;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
#endregion
/// <summary>
/// Encodes multiple images as an animated gif to a stream.

13
src/ImageProcessor/Imaging/Formats/GifFormat.cs

@ -15,7 +15,6 @@ namespace ImageProcessor.Imaging.Formats
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using ImageProcessor.Core.Common.Extensions;
/// <summary>
/// Provides the necessary information to support gif images.
@ -73,18 +72,18 @@ namespace ImageProcessor.Imaging.Formats
/// <param name="factory">The <see cref="ImageFactory" />.</param>
public override void ApplyProcessor(Func<ImageFactory, Image> processor, ImageFactory factory)
{
ImageInfo imageInfo = factory.Image.GetImageInfo(this.ImageFormat);
GifInfo info = FormatUtilities.GetGifInfo(factory.Image, this.ImageFormat);
if (imageInfo.IsAnimated)
if (info.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, imageInfo.LoopCount))
using (GifEncoder encoder = new GifEncoder(stream, null, null, info.LoopCount))
{
foreach (GifFrame frame in imageInfo.GifFrames)
foreach (GifFrame frame in info.GifFrames)
{
factory.Image = frame.Image;
frame.Image = quantizer.Quantize(processor.Invoke(factory));
@ -113,7 +112,7 @@ namespace ImageProcessor.Imaging.Formats
/// </returns>
public override Image Save(Stream stream, Image image)
{
if (!ImageAnimator.CanAnimate(image))
if (!FormatUtilities.IsAnimated(image))
{
image = new OctreeQuantizer(255, 8).Quantize(image);
}
@ -132,7 +131,7 @@ namespace ImageProcessor.Imaging.Formats
/// </returns>
public override Image Save(string path, Image image)
{
if (!ImageAnimator.CanAnimate(image))
if (!FormatUtilities.IsAnimated(image))
{
image = new OctreeQuantizer(255, 8).Quantize(image);
}

2
src/ImageProcessor/Imaging/GifFrame.cs → src/ImageProcessor/Imaging/Formats/GifFrame.cs

@ -8,7 +8,7 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging
namespace ImageProcessor.Imaging.Formats
{
using System.Drawing;

12
src/ImageProcessor/Core/Common/Extensions/ImageInfo.cs → src/ImageProcessor/Imaging/Formats/GifInfo.cs

@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageInfo.cs" company="James South">
// <copyright file="GifInfo.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -9,17 +9,16 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Core.Common.Extensions
namespace ImageProcessor.Imaging.Formats
{
using System.Collections.Generic;
using ImageProcessor.Imaging;
/// <summary>
/// Provides information about an image.
/// <see cref="http://madskristensen.net/post/examine-animated-gife28099s-in-c"/>
/// </summary>
public class ImageInfo
public class GifInfo
{
/// <summary>
/// Gets or sets the image width.
@ -31,11 +30,6 @@ namespace ImageProcessor.Core.Common.Extensions
/// </summary>
public int Height { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the image is indexed.
/// </summary>
public bool IsIndexed { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the image is animated.
/// </summary>

4
src/ImageProcessor/Imaging/Formats/JpegFormat.cs

@ -109,7 +109,7 @@ namespace ImageProcessor.Imaging.Formats
{
// Jpegs can be saved with different settings to include a quality setting for the JPEG compression.
// This improves output compression and quality.
using (EncoderParameters encoderParameters = ImageUtils.GetEncodingParameters(this.Quality))
using (EncoderParameters encoderParameters = FormatUtilities.GetEncodingParameters(this.Quality))
{
ImageCodecInfo imageCodecInfo =
ImageCodecInfo.GetImageEncoders()
@ -137,7 +137,7 @@ namespace ImageProcessor.Imaging.Formats
{
// Jpegs can be saved with different settings to include a quality setting for the JPEG compression.
// This improves output compression and quality.
using (EncoderParameters encoderParameters = ImageUtils.GetEncodingParameters(this.Quality))
using (EncoderParameters encoderParameters = FormatUtilities.GetEncodingParameters(this.Quality))
{
ImageCodecInfo imageCodecInfo =
ImageCodecInfo.GetImageEncoders()

78
src/ImageProcessor/Imaging/ImageUtils.cs

@ -1,78 +0,0 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageUtils.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates useful image utility methods.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging
{
#region Using
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
#endregion
/// <summary>
/// Encapsulates useful image utility methods.
/// </summary>
public static class ImageUtils
{
/// <summary>
/// Returns an instance of EncodingParameters for jpeg compression.
/// </summary>
/// <param name="quality">The quality to return the image at.</param>
/// <returns>The encodingParameters for jpeg compression. </returns>
public static EncoderParameters GetEncodingParameters(int quality)
{
EncoderParameters encoderParameters = null;
try
{
// Create a series of encoder parameters.
encoderParameters = new EncoderParameters(1);
// Set the quality.
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
}
catch
{
if (encoderParameters != null)
{
encoderParameters.Dispose();
}
}
return encoderParameters;
}
/// <summary>Returns a value indicating whether or not the given bitmap is indexed.</summary>
/// <param name="image">The image to check</param>
/// <returns>Whether or not the given bitmap is indexed.</returns>
public static bool IsIndexed(Image image)
{
// Test value of flags using bitwise AND.
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
return (image.PixelFormat & PixelFormat.Indexed) != 0;
}
/// <summary>
/// Uses reflection to allow the creation of an instance of <see cref="PropertyItem"/>.
/// </summary>
/// <returns>
/// The <see cref="PropertyItem"/>.
/// </returns>
public static PropertyItem CreatePropertyItem()
{
Type type = typeof(PropertyItem);
ConstructorInfo constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
return (PropertyItem)constructor.Invoke(null);
}
}
}
Loading…
Cancel
Save