From ba967bd7ad5d7d318fb17855a4697cdd697222a9 Mon Sep 17 00:00:00 2001 From: James South Date: Mon, 23 Jun 2014 12:25:29 +0100 Subject: [PATCH] More refactorings Former-commit-id: f2f5eaa2be637b1eb47979700e061df51c19e85b --- .../Core/Common/Extensions/ImageExtensions.cs | 98 ------------ .../Extensions/ImageFormatExtensions.cs | 151 ------------------ src/ImageProcessor/ImageFactory.cs | 4 +- src/ImageProcessor/ImageProcessor.csproj | 9 +- .../Imaging/Formats/FormatUtilities.cs | 119 +++++++++++++- .../Imaging/{ => Formats}/GifEncoder.cs | 4 +- .../Imaging/Formats/GifFormat.cs | 13 +- .../Imaging/{ => Formats}/GifFrame.cs | 2 +- .../Formats/GifInfo.cs} | 12 +- .../Imaging/Formats/JpegFormat.cs | 4 +- src/ImageProcessor/Imaging/ImageUtils.cs | 78 --------- 11 files changed, 136 insertions(+), 358 deletions(-) delete mode 100644 src/ImageProcessor/Core/Common/Extensions/ImageExtensions.cs delete mode 100644 src/ImageProcessor/Core/Common/Extensions/ImageFormatExtensions.cs rename src/ImageProcessor/Imaging/{ => Formats}/GifEncoder.cs (99%) rename src/ImageProcessor/Imaging/{ => Formats}/GifFrame.cs (96%) rename src/ImageProcessor/{Core/Common/Extensions/ImageInfo.cs => Imaging/Formats/GifInfo.cs} (85%) delete mode 100644 src/ImageProcessor/Imaging/ImageUtils.cs diff --git a/src/ImageProcessor/Core/Common/Extensions/ImageExtensions.cs b/src/ImageProcessor/Core/Common/Extensions/ImageExtensions.cs deleted file mode 100644 index 39210c33c..000000000 --- a/src/ImageProcessor/Core/Common/Extensions/ImageExtensions.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates a series of time saving extension methods to the class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Core.Common.Extensions -{ - using System; - using System.Collections.Generic; - using System.Drawing; - using System.Drawing.Imaging; - using ImageProcessor.Imaging; - - /// - /// Encapsulates a series of time saving extension methods to the class. - /// - public static class ImageExtensions - { - /// - /// Returns information about the given . - /// - /// - /// The image to extend. - /// - /// - /// The image format. - /// - /// - /// Whether to fetch the images frames. - /// - /// - /// The . - /// - 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 gifFrames = new List(); - - 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; - } - } -} diff --git a/src/ImageProcessor/Core/Common/Extensions/ImageFormatExtensions.cs b/src/ImageProcessor/Core/Common/Extensions/ImageFormatExtensions.cs deleted file mode 100644 index dcdaa4550..000000000 --- a/src/ImageProcessor/Core/Common/Extensions/ImageFormatExtensions.cs +++ /dev/null @@ -1,151 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates a series of time saving extension methods to the -// class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Core.Common.Extensions -{ - #region - - using System.Drawing.Imaging; - using System.Linq; - - #endregion - - /// - /// Encapsulates a series of time saving extension methods to the class. - /// - public static class ImageFormatExtensions - { - /// - /// Gets the correct mime-type for the given . - /// - /// The . - /// The correct mime-type for the given . - 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; - } - - /// - /// Gets the name for the given . - /// - /// - /// The to get the name for. - /// - /// - /// The representing the name of the . - /// - 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 + "]"; - } - - /// - /// Returns the correct file extension for the given . - /// - /// - /// The to return the extension for. - /// - /// - /// The original Extension. - /// - /// - /// The correct file extension for the given . - /// - 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; - } - } -} \ No newline at end of file diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index 65de7464b..4d623c246 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/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; diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index ba02d703a..cd884e30c 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -63,9 +63,7 @@ - - - + @@ -87,8 +85,8 @@ - - + + @@ -103,7 +101,6 @@ - diff --git a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs index 2520d23de..39ea4cfd1 100644 --- a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs +++ b/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; /// @@ -94,5 +96,120 @@ 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) + { + FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]); + int frameCount = image.GetFrameCount(frameDimension); + int last = frameCount - 1; + int delay = 0; + int index = 0; + List gifFrames = new List(); + + 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; + } + + /// + /// Returns an instance of EncodingParameters for jpeg compression. + /// + /// The quality to return the image at. + /// The encodingParameters for jpeg compression. + 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; + } + + /// + /// Uses reflection to allow the creation of an instance of . + /// + /// + /// The . + /// + 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); + } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor/Imaging/GifEncoder.cs b/src/ImageProcessor/Imaging/Formats/GifEncoder.cs similarity index 99% rename from src/ImageProcessor/Imaging/GifEncoder.cs rename to src/ImageProcessor/Imaging/Formats/GifEncoder.cs index 20a8ba0f0..d667f35f5 100644 --- a/src/ImageProcessor/Imaging/GifEncoder.cs +++ b/src/ImageProcessor/Imaging/Formats/GifEncoder.cs @@ -14,14 +14,12 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Imaging +namespace ImageProcessor.Imaging.Formats { - #region Using using System; using System.Drawing.Imaging; using System.IO; using System.Linq; - #endregion /// /// Encodes multiple images as an animated gif to a stream. diff --git a/src/ImageProcessor/Imaging/Formats/GifFormat.cs b/src/ImageProcessor/Imaging/Formats/GifFormat.cs index f29e3f446..dffccb99b 100644 --- a/src/ImageProcessor/Imaging/Formats/GifFormat.cs +++ b/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; /// /// Provides the necessary information to support gif images. @@ -73,18 +72,18 @@ namespace ImageProcessor.Imaging.Formats /// The . public override void ApplyProcessor(Func 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 /// 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 /// public override Image Save(string path, Image image) { - if (!ImageAnimator.CanAnimate(image)) + if (!FormatUtilities.IsAnimated(image)) { image = new OctreeQuantizer(255, 8).Quantize(image); } diff --git a/src/ImageProcessor/Imaging/GifFrame.cs b/src/ImageProcessor/Imaging/Formats/GifFrame.cs similarity index 96% rename from src/ImageProcessor/Imaging/GifFrame.cs rename to src/ImageProcessor/Imaging/Formats/GifFrame.cs index 9a2e1e20b..943961cb9 100644 --- a/src/ImageProcessor/Imaging/GifFrame.cs +++ b/src/ImageProcessor/Imaging/Formats/GifFrame.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Imaging +namespace ImageProcessor.Imaging.Formats { using System.Drawing; diff --git a/src/ImageProcessor/Core/Common/Extensions/ImageInfo.cs b/src/ImageProcessor/Imaging/Formats/GifInfo.cs similarity index 85% rename from src/ImageProcessor/Core/Common/Extensions/ImageInfo.cs rename to src/ImageProcessor/Imaging/Formats/GifInfo.cs index 41ef6f5b0..c0b75bae3 100644 --- a/src/ImageProcessor/Core/Common/Extensions/ImageInfo.cs +++ b/src/ImageProcessor/Imaging/Formats/GifInfo.cs @@ -1,5 +1,5 @@ // -------------------------------------------------------------------------------------------------------------------- -// +// // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // @@ -9,17 +9,16 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Core.Common.Extensions +namespace ImageProcessor.Imaging.Formats { using System.Collections.Generic; - using ImageProcessor.Imaging; /// /// Provides information about an image. /// /// - public class ImageInfo + public class GifInfo { /// /// Gets or sets the image width. @@ -31,11 +30,6 @@ namespace ImageProcessor.Core.Common.Extensions /// public int Height { get; set; } - /// - /// Gets or sets a value indicating whether the image is indexed. - /// - public bool IsIndexed { get; set; } - /// /// Gets or sets a value indicating whether the image is animated. /// diff --git a/src/ImageProcessor/Imaging/Formats/JpegFormat.cs b/src/ImageProcessor/Imaging/Formats/JpegFormat.cs index 9447375d9..0111ee1d6 100644 --- a/src/ImageProcessor/Imaging/Formats/JpegFormat.cs +++ b/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() diff --git a/src/ImageProcessor/Imaging/ImageUtils.cs b/src/ImageProcessor/Imaging/ImageUtils.cs deleted file mode 100644 index 7c338a79e..000000000 --- a/src/ImageProcessor/Imaging/ImageUtils.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates useful image utility methods. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Imaging -{ - #region Using - - using System; - using System.Drawing; - using System.Drawing.Imaging; - using System.Reflection; - - #endregion - - /// - /// Encapsulates useful image utility methods. - /// - public static class ImageUtils - { - /// - /// Returns an instance of EncodingParameters for jpeg compression. - /// - /// The quality to return the image at. - /// The encodingParameters for jpeg compression. - 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; - } - - /// Returns a value indicating whether or not the given bitmap is indexed. - /// The image to check - /// Whether or not the given bitmap is indexed. - public static bool IsIndexed(Image image) - { - // Test value of flags using bitwise AND. - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - return (image.PixelFormat & PixelFormat.Indexed) != 0; - } - - /// - /// Uses reflection to allow the creation of an instance of . - /// - /// - /// The . - /// - 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); - } - } -}