diff --git a/src/ImageProcessor.Web/NET4/ImageProcessor.Web.csproj b/src/ImageProcessor.Web/NET4/ImageProcessor.Web.csproj index 0a0c3eb9a..6c01a8bcc 100644 --- a/src/ImageProcessor.Web/NET4/ImageProcessor.Web.csproj +++ b/src/ImageProcessor.Web/NET4/ImageProcessor.Web.csproj @@ -82,13 +82,13 @@ + + ImageHelpers.cs + - - Preset.cs - diff --git a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs b/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs index 8e4cf7401..f04c745f7 100644 --- a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs +++ b/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs @@ -20,7 +20,8 @@ namespace ImageProcessor.Web.Caching using System.Threading.Tasks; using System.Web; using System.Web.Hosting; - using ImageProcessor.Helpers.Extensions; + + using ImageProcessor.Extensions; using ImageProcessor.Imaging; using ImageProcessor.Web.Config; using ImageProcessor.Web.Helpers; @@ -372,7 +373,7 @@ namespace ImageProcessor.Web.Caching // Use an sha1 hash of the full path including the querystring to create the image name. // That name can also be used as a key for the cached image and we should be able to use // The characters of that hash as subfolders. - string parsedExtension = ImageUtils.GetExtension(this.fullPath); + string parsedExtension = ImageHelpers.GetExtension(this.fullPath); string fallbackExtension = this.imageName.Substring(this.imageName.LastIndexOf(".", StringComparison.Ordinal) + 1); string encryptedName = this.fullPath.ToSHA1Fingerprint(); diff --git a/src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs b/src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs index 92015a83d..b4b74f45d 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs +++ b/src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs @@ -9,7 +9,9 @@ namespace ImageProcessor.Web.Config { #region Using using System.Configuration; - using ImageProcessor.Helpers.Extensions; + + using ImageProcessor.Extensions; + #endregion /// diff --git a/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs b/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs new file mode 100644 index 000000000..c08a60bea --- /dev/null +++ b/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs @@ -0,0 +1,96 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The image helpers. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Helpers +{ + #region Using + using System.Drawing.Imaging; + using System.IO; + using System.Text.RegularExpressions; + #endregion + + /// + /// The image helpers. + /// + public static class ImageHelpers + { + /// + /// The image format regex. + /// + private static readonly Regex FormatRegex = new Regex(@"(\.?)(j(pg|peg)|bmp|png|gif|ti(ff|f)|ico)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft); + + /// + /// The image format regex for matching the file format at the end of a string. + /// + private static readonly Regex EndFormatRegex = new Regex(@"(\.)(j(pg|peg)|bmp|png|gif|ti(ff|f)|ico)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft); + + /// + /// Checks a given string to check whether the value contains a valid image extension. + /// + /// The string containing the filename to check. + /// True the value contains a valid image extension, otherwise false. + public static bool IsValidImageExtension(string fileName) + { + return EndFormatRegex.IsMatch(fileName); + } + + /// + /// Returns the correct file extension for the given string input + /// + /// + /// The string to parse. + /// + /// + /// The correct file extension for the given string input if it can find one; otherwise an empty string. + /// + public static string GetExtension(string input) + { + Match match = FormatRegex.Matches(input)[0]; + + return match.Success ? match.Value : string.Empty; + } + + /// + /// Returns the correct image format based on the given file extension. + /// + /// The string containing the filename to check against. + /// The correct image format based on the given filename. + //public static ImageFormat GetImageFormat(string fileName) + //{ + // string extension = Path.GetExtension(fileName); + + // if (extension != null) + // { + // string ext = extension.ToUpperInvariant(); + + // switch (ext) + // { + // case ".ICO": + // return ImageFormat.Icon; + // case ".PNG": + // return ImageFormat.Png; + // case ".BMP": + // return ImageFormat.Bmp; + // case ".GIF": + // return ImageFormat.Gif; + // case ".TIF": + // case ".TIFF": + // return ImageFormat.Tiff; + // default: + // // Should be a jpeg. + // return ImageFormat.Jpeg; + // } + // } + + // // TODO: Show custom exception? + // return null; + //} + } +} diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs index edd48f88e..d98447302 100644 --- a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs @@ -21,13 +21,13 @@ namespace ImageProcessor.Web.HttpModules using System.Security; using System.Security.Permissions; using System.Security.Principal; + using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Hosting; using System.Web.Security; - using ImageProcessor.Helpers.Extensions; - using ImageProcessor.Imaging; + using ImageProcessor.Extensions; using ImageProcessor.Web.Caching; using ImageProcessor.Web.Config; using ImageProcessor.Web.Helpers; @@ -44,6 +44,11 @@ namespace ImageProcessor.Web.HttpModules /// private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE_054F217C-11CF-49FF-8D2F-698E8E6EB58F"; + /// + /// The regular expression to search strings for. + /// + private static readonly Regex PresetRegex = new Regex(@"preset=[^&]*", RegexOptions.Compiled); + /// /// The value to prefix any remote image requests with to ensure they get captured. /// @@ -312,8 +317,11 @@ namespace ImageProcessor.Web.HttpModules } // Only process requests that pass our sanitizing filter. - if ((ImageUtils.IsValidImageExtension(requestPath) || validExtensionLessUrl) && !string.IsNullOrWhiteSpace(queryString)) + if ((ImageHelpers.IsValidImageExtension(requestPath) || validExtensionLessUrl) && !string.IsNullOrWhiteSpace(queryString)) { + // Replace any presets in the querystring with the actual value. + queryString = this.ReplacePresetsInQueryString(queryString); + string fullPath = string.Format("{0}?{1}", requestPath, queryString); string imageName = Path.GetFileName(requestPath); @@ -400,10 +408,12 @@ namespace ImageProcessor.Web.HttpModules // Process the Image imageFactory.Load(memoryStream) .AddQueryString(queryString) - .Format(ImageUtils.GetImageFormat(imageName)) .AutoProcess() .Save(cachedPath); + // Store the response type in the context for later retrieval. + context.Items[CachedResponseTypeKey] = imageFactory.MimeType; + // Ensure that the LastWriteTime property of the source and cached file match. Tuple creationAndLastWriteDateTimes = await cache.SetCachedLastWriteTimeAsync(); @@ -441,6 +451,9 @@ namespace ImageProcessor.Web.HttpModules // Process the Image imageFactory.Load(fullPath).AutoProcess().Save(cachedPath); + // Store the response type in the context for later retrieval. + context.Items[CachedResponseTypeKey] = imageFactory.MimeType; + // Ensure that the LastWriteTime property of the source and cached file match. Tuple creationAndLastWriteDateTimes = await cache.SetCachedLastWriteTimeAsync(); @@ -458,8 +471,6 @@ namespace ImageProcessor.Web.HttpModules } } - // Store the response type in the context for later retrieval. - context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(fullPath).ToDescription(); string incomingEtag = context.Request.Headers["If-None-Match"]; if (incomingEtag != null && !isNewOrUpdated) @@ -478,8 +489,10 @@ namespace ImageProcessor.Web.HttpModules } } + string virtualPath = cache.GetVirtualCachedPath(); + // The cached file is valid so just rewrite the path. - context.RewritePath(cache.GetVirtualCachedPath(), false); + context.RewritePath(virtualPath, false); } else { @@ -517,6 +530,35 @@ namespace ImageProcessor.Web.HttpModules cache.SetMaxAge(new TimeSpan(maxDays, 0, 0, 0)); cache.SetRevalidation(HttpCacheRevalidation.AllCaches); } + + /// + /// Replaces preset values stored in the configuration in the querystring. + /// + /// + /// The query string. + /// + /// + /// The containing the updated querystring. + /// + private string ReplacePresetsInQueryString(string queryString) + { + // We use the processor config system to store the preset values. + Dictionary presets = ImageProcessorConfig.Instance.GetPluginSettings("Preset"); + + foreach (Match match in PresetRegex.Matches(queryString)) + { + if (match.Success) + { + // Set the index on the first instance only. + string preset = match.Value; + string replacements; + presets.TryGetValue(preset.Split('=')[1], out replacements); + queryString = Regex.Replace(queryString, preset, replacements ?? string.Empty); + } + } + + return queryString; + } #endregion } } \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs b/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs index a8d4bf783..bca0c6665 100644 --- a/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs +++ b/src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs @@ -1,9 +1,12 @@ -// ----------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. // -// ----------------------------------------------------------------------- +// +// Extends the ImageFactory class to provide a fluent API. +// +// -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Web { @@ -54,12 +57,6 @@ namespace ImageProcessor.Web { Image img = graphicsProcessor.ProcessImage(factory); factory.Update(img); - - // Break to prevent loop as Preset calls AutoProcess internally. - if (graphicsProcessor.GetType() == typeof(Preset)) - { - break; - } } } } diff --git a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj b/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj index 66c11195d..cdb14683e 100644 --- a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj +++ b/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj @@ -53,11 +53,11 @@ + - diff --git a/src/ImageProcessor.Web/NET45/Preset.cs b/src/ImageProcessor.Web/NET45/Preset.cs deleted file mode 100644 index 769049dca..000000000 --- a/src/ImageProcessor.Web/NET45/Preset.cs +++ /dev/null @@ -1,121 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// -// Encapsulates methods to that allow the processing of preset image processing instructions. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace ImageProcessor.Web -{ - using System.Collections.Generic; - using System.Drawing; - using System.Text.RegularExpressions; - using ImageProcessor.Processors; - - /// - /// Encapsulates methods to that allow the processing of preset image processing instructions. - /// - public class Preset : IGraphicsProcessor - { - /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"preset=[^&]*", RegexOptions.Compiled); - - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern - { - get - { - return QueryRegex; - } - } - - /// - /// Gets DynamicParameter. - /// - public dynamic DynamicParameter - { - get; - private set; - } - - /// - /// Gets the order in which this processor is to be used in a chain. - /// - public int SortOrder - { - get; - private set; - } - - /// - /// Gets or sets any additional settings required by the processor. - /// - public Dictionary Settings - { - get; - set; - } - - /// - /// The match regex index. - /// - /// - /// The query string. - /// - /// - /// The . - /// - public int MatchRegexIndex(string queryString) - { - int index = 0; - - // Set the sort order to max to allow filtering. - this.SortOrder = int.MaxValue; - - foreach (Match match in this.RegexPattern.Matches(queryString)) - { - if (match.Success) - { - if (index == 0) - { - // Set the index on the first instance only. - this.SortOrder = match.Index; - string preset = match.Value; - this.DynamicParameter = preset; - } - - index += 1; - } - } - - return this.SortOrder; - } - - /// - /// Processes the image. - /// - /// The the current instance of the class containing - /// the image to process. - /// - /// The processed image from the current instance of the class. - /// - public Image ProcessImage(ImageFactory factory) - { - string preset = this.DynamicParameter; - string querystring; - this.Settings.TryGetValue(preset.Split('=')[1], out querystring); - - string oldQueryString = factory.QueryString; - string newQueryString = Regex.Replace(oldQueryString, preset, querystring ?? string.Empty); - - return factory.AddQueryString(newQueryString).AutoProcess().Image; - } - } -} diff --git a/src/ImageProcessor.Web/NET45/Settings.StyleCop b/src/ImageProcessor.Web/NET45/Settings.StyleCop index 578d6f188..13af6f9ae 100644 --- a/src/ImageProcessor.Web/NET45/Settings.StyleCop +++ b/src/ImageProcessor.Web/NET45/Settings.StyleCop @@ -2,6 +2,7 @@ Mutexes + querystring diff --git a/src/ImageProcessor/Extensions/ImageFormatExtensions.cs b/src/ImageProcessor/Extensions/ImageFormatExtensions.cs new file mode 100644 index 000000000..036a4153e --- /dev/null +++ b/src/ImageProcessor/Extensions/ImageFormatExtensions.cs @@ -0,0 +1,149 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// 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.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/Helpers/Extensions/StringExtensions.cs b/src/ImageProcessor/Extensions/StringExtensions.cs similarity index 99% rename from src/ImageProcessor/Helpers/Extensions/StringExtensions.cs rename to src/ImageProcessor/Extensions/StringExtensions.cs index 723c679b4..40380a1aa 100644 --- a/src/ImageProcessor/Helpers/Extensions/StringExtensions.cs +++ b/src/ImageProcessor/Extensions/StringExtensions.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Helpers.Extensions +namespace ImageProcessor.Extensions { #region Using using System; diff --git a/src/ImageProcessor/Helpers/Extensions/EnumExtensions.cs b/src/ImageProcessor/Helpers/Extensions/EnumExtensions.cs deleted file mode 100644 index 736402edb..000000000 --- a/src/ImageProcessor/Helpers/Extensions/EnumExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// ----------------------------------------------------------------------- - -namespace ImageProcessor.Helpers.Extensions -{ - #region Using - using System; - using System.ComponentModel; - using System.Diagnostics.Contracts; - #endregion - - /// - /// Encapsulates a series of time saving extension methods to Enums. - /// - public static class EnumExtensions - { - #region Methods - /// - /// Extends the Enum type to return the description attribute for the given type. - /// Useful for when the type to match in the data source contains spaces. - /// - /// The given Enum that this method extends. - /// A string containing the Enum's description attribute. - public static string ToDescription(this Enum expression) - { - Contract.Requires(expression != null); - - DescriptionAttribute[] descriptionAttribute = - (DescriptionAttribute[]) - expression.GetType().GetField(expression.ToString()) - .GetCustomAttributes(typeof(DescriptionAttribute), false); - - return descriptionAttribute.Length > 0 ? descriptionAttribute[0].Description : expression.ToString(); - } - #endregion - } -} diff --git a/src/ImageProcessor/Helpers/Extensions/ImageExtensions.cs b/src/ImageProcessor/Helpers/Extensions/ImageExtensions.cs deleted file mode 100644 index 564a360d0..000000000 --- a/src/ImageProcessor/Helpers/Extensions/ImageExtensions.cs +++ /dev/null @@ -1,76 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. -// -// ----------------------------------------------------------------------- - -namespace ImageProcessor.Helpers.Extensions -{ - #region Using - - using System; - using System.Drawing; - using System.Drawing.Imaging; - using System.IO; - using System.Runtime.InteropServices; - - #endregion - - /// - /// Extensions to the class - /// - public static class ImageExtensions - { - /// - /// Converts an image to an array of bytes. - /// - /// The instance that this method extends. - /// The to export the image with. - /// A byte array representing the current image. - public static byte[] ToBytes(this Image image, ImageFormat imageFormat) - { - BitmapData data = ((Bitmap)image).LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - int length = image.Width * image.Height * 4; - byte[] byteArray = new byte[length]; - - if (data.Stride == image.Width * 4) - { - Marshal.Copy(data.Scan0, byteArray, 0, length); - } - else - { - for (int i = 0, l = image.Height; i < l; i++) - { - IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i); - Marshal.Copy(p, byteArray, i * image.Width * 4, image.Width * 4); - } - } - - ((Bitmap)image).UnlockBits(data); - - return byteArray; - } - - public static Image FromBytes(this Image image, byte[] bytes) - { - BitmapData data = ((Bitmap)image).LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); - - if (data.Stride == image.Width * 4) - { - Marshal.Copy(bytes, 0, data.Scan0, bytes.Length); - } - else - { - for (int i = 0, l = image.Height; i < l; i++) - { - IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i); - Marshal.Copy(bytes, i * image.Width * 4, p, image.Width * 4); - } - } - - ((Bitmap)image).UnlockBits(data); - return image; - } - } -} diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index c2c97ea45..3b610f444 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/src/ImageProcessor/ImageFactory.cs @@ -20,6 +20,7 @@ namespace ImageProcessor using System.Linq; using System.Threading; + using ImageProcessor.Extensions; using ImageProcessor.Imaging; using ImageProcessor.Processors; #endregion @@ -109,7 +110,18 @@ namespace ImageProcessor /// Gets the file format of the image. /// public ImageFormat ImageFormat { get; private set; } - + + /// + /// Gets the mime type. + /// + public string MimeType + { + get + { + return this.ImageFormat.GetMimeType(); + } + } + /// /// Gets or sets the original extension. /// @@ -141,8 +153,8 @@ namespace ImageProcessor // Set the other properties. this.JpegQuality = DefaultJpegQuality; - this.backupImageFormat = ImageFormat.Jpeg; - this.ImageFormat = ImageFormat.Jpeg; + this.ImageFormat = this.Image.RawFormat; + this.backupImageFormat = this.ImageFormat; this.isIndexed = ImageUtils.IsIndexed(this.Image); this.ShouldProcess = true; @@ -158,6 +170,7 @@ namespace ImageProcessor /// public ImageFactory Load(string imagePath) { + // Remove any querystring parameters passed by web requests. string[] paths = imagePath.Split('?'); string path = paths[0]; string query = string.Empty; @@ -167,8 +180,6 @@ namespace ImageProcessor query = paths[1]; } - string imageName = Path.GetFileName(path); - if (File.Exists(path)) { this.ImagePath = path; @@ -193,7 +204,7 @@ namespace ImageProcessor // Set the other properties. this.JpegQuality = DefaultJpegQuality; - ImageFormat imageFormat = ImageUtils.GetImageFormat(imageName); + ImageFormat imageFormat = this.Image.RawFormat; this.backupImageFormat = imageFormat; this.OriginalExtension = Path.GetExtension(this.ImagePath); this.ImageFormat = imageFormat; @@ -761,8 +772,12 @@ namespace ImageProcessor // We need to check here if the path has an extension and remove it if so. // This is so we can add the correct image format. int length = filePath.LastIndexOf(".", StringComparison.Ordinal); - string extension = ImageUtils.GetExtensionFromImageFormat(this.ImageFormat, this.OriginalExtension); - filePath = length == -1 ? filePath + extension : filePath.Substring(0, length) + extension; + string extension = this.ImageFormat.GetFileExtension(this.OriginalExtension); + + if (!string.IsNullOrWhiteSpace(extension)) + { + filePath = length == -1 ? filePath + extension : filePath.Substring(0, length) + extension; + } // Fix the colour palette of indexed images. this.FixIndexedPallete(); @@ -778,7 +793,7 @@ namespace ImageProcessor { ImageCodecInfo imageCodecInfo = ImageCodecInfo.GetImageEncoders() - .FirstOrDefault(ici => ici.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)); + .FirstOrDefault(ici => ici.MimeType.Equals(this.MimeType, StringComparison.OrdinalIgnoreCase)); if (imageCodecInfo != null) { @@ -851,7 +866,7 @@ namespace ImageProcessor { ImageCodecInfo imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault( - ici => ici.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)); + ici => ici.MimeType.Equals(this.MimeType, StringComparison.OrdinalIgnoreCase)); if (imageCodecInfo != null) { diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index 36f11960d..0acdba19f 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -59,9 +59,9 @@ - - - + + + @@ -105,6 +105,7 @@ +