diff --git a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs b/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs index 9ec0fb696..1d8e954aa 100644 --- a/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs +++ b/src/ImageProcessor.Web/NET45/Caching/DiskCache.cs @@ -72,11 +72,6 @@ namespace ImageProcessor.Web.Caching /// The image name /// private readonly string imageName; - - /// - /// Whether the request is for a remote image. - /// - private readonly bool isRemote; #endregion #region Constructors @@ -95,16 +90,12 @@ namespace ImageProcessor.Web.Caching /// /// The image name. /// - /// - /// Whether the request is for a remote image. - /// - public DiskCache(HttpRequest request, string requestPath, string fullPath, string imageName, bool isRemote) + public DiskCache(HttpRequest request, string requestPath, string fullPath, string imageName) { this.request = request; this.requestPath = requestPath; this.fullPath = fullPath; this.imageName = imageName; - this.isRemote = isRemote; this.CachedPath = this.GetCachePath(); } #endregion @@ -163,35 +154,19 @@ namespace ImageProcessor.Web.Caching { string path = this.CachedPath; bool isUpdated = false; - CachedImage cachedImage; + CachedImage cachedImage = await CacheIndexer.GetValueAsync(path); - if (this.isRemote) + if (cachedImage == null) { - cachedImage = await CacheIndexer.GetValueAsync(path); - - if (cachedImage != null) - { - // Can't check the filestream so check to see if the cached image is set to expire. - if (this.IsExpired(cachedImage.CreationTimeUtc)) - { - CacheIndexer.Remove(path); - isUpdated = true; - } - } - else - { - // Nothing in the cache so we should return true. - isUpdated = true; - } + // Nothing in the cache so we should return true. + isUpdated = true; } else { - // Test now for locally requested files. - cachedImage = await CacheIndexer.GetValueAsync(path); - - if (cachedImage == null) + // Check to see if the cached image is set to expire. + if (this.IsExpired(cachedImage.CreationTimeUtc)) { - // Nothing in the cache so we should return true. + CacheIndexer.Remove(path); isUpdated = true; } } diff --git a/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs b/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs index c5000851e..1b6e45a3a 100644 --- a/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs +++ b/src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs @@ -11,7 +11,13 @@ namespace ImageProcessor.Web.Helpers { #region Using + + using System.Text; using System.Text.RegularExpressions; + + using ImageProcessor.Configuration; + using ImageProcessor.Imaging.Formats; + #endregion /// @@ -19,15 +25,20 @@ namespace ImageProcessor.Web.Helpers /// public static class ImageHelpers { + /// + /// The regex pattern. + /// + private static readonly string RegexPattern = BuildRegexPattern(); + /// /// 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); + private static readonly Regex FormatRegex = new Regex(@"(\.?)" + RegexPattern, 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); + private static readonly Regex EndFormatRegex = new Regex(@"(\.)" + RegexPattern + "$", RegexOptions.IgnoreCase | RegexOptions.RightToLeft); /// /// Checks a given string to check whether the value contains a valid image extension. @@ -36,7 +47,14 @@ namespace ImageProcessor.Web.Helpers /// True the value contains a valid image extension, otherwise false. public static bool IsValidImageExtension(string fileName) { - return EndFormatRegex.IsMatch(fileName); + Match match = EndFormatRegex.Matches(fileName)[0]; + + if (match.Success && !match.Value.ToLowerInvariant().EndsWith("png8")) + { + return true; + } + + return false; } /// @@ -51,7 +69,51 @@ namespace ImageProcessor.Web.Helpers public static string GetExtension(string input) { Match match = FormatRegex.Matches(input)[0]; - return match.Success ? match.Value : string.Empty; + + if (match.Success) + { + // Ah the enigma that is the png file. + if (match.Value.ToLowerInvariant().EndsWith("png8")) + { + return "png"; + } + + return match.Value; + } + + return string.Empty; + } + + /// + /// Builds a regular expression from the type, this allows extensibility. + /// + /// + /// The to match matrix filters. + /// + private static string BuildRegexPattern() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append("("); + int counter = 0; + foreach (ISupportedImageFormat imageFormat in ImageProcessorBootstrapper.Instance.SupportedImageFormats) + { + foreach (string fileExtension in imageFormat.FileExtensions) + { + if (counter == 0) + { + stringBuilder.Append(fileExtension.ToLowerInvariant()); + } + else + { + stringBuilder.AppendFormat("|{0}", fileExtension.ToLowerInvariant()); + } + } + + counter++; + } + + stringBuilder.Append(")"); + return stringBuilder.ToString(); } } -} +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs index c751fd095..21c3e4a31 100644 --- a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs @@ -347,7 +347,7 @@ namespace ImageProcessor.Web.HttpModules } // Create a new cache to help process and cache the request. - DiskCache cache = new DiskCache(request, requestPath, fullPath, imageName, isRemote); + DiskCache cache = new DiskCache(request, requestPath, fullPath, imageName); // Since we are now rewriting the path we need to check again that the current user has access // to the rewritten path. diff --git a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj b/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj index 694840487..7f63f275a 100644 --- a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj +++ b/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj @@ -67,6 +67,8 @@ + + diff --git a/src/ImageProcessor.Web/NET45/Processors/Filter.cs b/src/ImageProcessor.Web/NET45/Processors/Filter.cs index a83e9655c..ab9353c78 100644 --- a/src/ImageProcessor.Web/NET45/Processors/Filter.cs +++ b/src/ImageProcessor.Web/NET45/Processors/Filter.cs @@ -133,11 +133,11 @@ namespace ImageProcessor.Web.Processors stringBuilder.Append(")"); - return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase | RegexOptions.Compiled); + return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase); } /// - /// Parses the filter. + /// Parses the input string to return the correct . /// /// /// The identifier. diff --git a/src/ImageProcessor.Web/NET45/Processors/Flip.cs b/src/ImageProcessor.Web/NET45/Processors/Flip.cs new file mode 100644 index 000000000..085962030 --- /dev/null +++ b/src/ImageProcessor.Web/NET45/Processors/Flip.cs @@ -0,0 +1,103 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Flips an image horizontally or vertically. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System.Drawing; + using System.Text.RegularExpressions; + using ImageProcessor.Processors; + + /// + /// Flips an image horizontally or vertically. + /// + public class Flip : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"flip=(horizontal|vertical|both)", RegexOptions.Compiled); + + /// + /// Initializes a new instance of the class. + /// + public Flip() + { + this.Processor = new ImageProcessor.Processors.Flip(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + 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 direction = match.Value.Split('=')[1]; + + switch (direction) + { + case "horizontal": + this.Processor.DynamicParameter = RotateFlipType.RotateNoneFlipX; + break; + case "vertical": + this.Processor.DynamicParameter = RotateFlipType.RotateNoneFlipY; + break; + default: + this.Processor.DynamicParameter = RotateFlipType.RotateNoneFlipXY; + break; + } + } + + index += 1; + } + } + + return this.SortOrder; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Processors/Format.cs b/src/ImageProcessor.Web/NET45/Processors/Format.cs new file mode 100644 index 000000000..eaddab8e1 --- /dev/null +++ b/src/ImageProcessor.Web/NET45/Processors/Format.cs @@ -0,0 +1,156 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Sets the output of the image to a specific format. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Web.Processors +{ + using System; + using System.Linq; + using System.Text; + using System.Text.RegularExpressions; + using ImageProcessor.Configuration; + using ImageProcessor.Imaging.Formats; + using ImageProcessor.Processors; + + /// + /// Sets the output of the image to a specific format. + /// + public class Format : IWebGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = BuildRegex(); + + /// + /// Initializes a new instance of the class. + /// + public Format() + { + this.Processor = new ImageProcessor.Processors.Format(); + } + + /// + /// Gets the regular expression to search strings for. + /// + public Regex RegexPattern + { + get + { + return QueryRegex; + } + } + + /// + /// Gets the order in which this processor is to be used in a chain. + /// + public int SortOrder { get; private set; } + + /// + /// Gets the associated graphics processor. + /// + public IGraphicsProcessor Processor { get; private set; } + + /// + /// The position in the original string where the first character of the captured substring was found. + /// + /// + /// The query string to search. + /// + /// + /// The zero-based starting position in the original string where the captured substring was found. + /// + 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; + + ISupportedImageFormat format = this.ParseFormat(match.Value.Split('=')[1]); + if (format != null) + { + this.Processor.DynamicParameter = format; + } + } + + index += 1; + } + } + + return this.SortOrder; + } + + /// + /// Builds a regular expression from the type, this allows extensibility. + /// + /// + /// The to match matrix filters. + /// + private static Regex BuildRegex() + { + StringBuilder stringBuilder = new StringBuilder(); + + // png8 is a special case for determining indexed pngs. + stringBuilder.Append("format=(png8"); + foreach (ISupportedImageFormat imageFormat in ImageProcessorBootstrapper.Instance.SupportedImageFormats) + { + foreach (string fileExtension in imageFormat.FileExtensions) + { + stringBuilder.AppendFormat("|{0}", fileExtension.ToLowerInvariant()); + } + } + + stringBuilder.Append(")"); + + return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase); + } + + /// + /// Parses the input string to return the correct . + /// + /// + /// The identifier. + /// + /// + /// The . + /// + private ISupportedImageFormat ParseFormat(string identifier) + { + identifier = identifier.ToLowerInvariant(); + ISupportedImageFormat format = ImageProcessorBootstrapper.Instance.SupportedImageFormats + .FirstOrDefault(f => f.FileExtensions.Any(e => e.Equals(identifier, StringComparison.InvariantCultureIgnoreCase))); + + if (format != null) + { + // I wish this wasn't hardcoded but there's no way I can + // find to preserve the pallete. + if (identifier.Equals("png8")) + { + format.IsIndexed = true; + } + else if (identifier.Equals("png")) + { + format.IsIndexed = false; + } + } + + return format; + } + } +} \ No newline at end of file diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index aa62aab75..ee7efe5c1 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/src/ImageProcessor/ImageFactory.cs @@ -124,11 +124,6 @@ namespace ImageProcessor /// internal Image Image { get; set; } - /// - /// Gets or sets the original extension. - /// - internal string OriginalExtension { get; set; } - /// /// Gets or sets the memory stream for storing any input stream to prevent disposal. /// @@ -233,8 +228,6 @@ namespace ImageProcessor format.Quality = DefaultQuality; format.IsIndexed = ImageUtils.IsIndexed(this.Image); - this.OriginalExtension = Path.GetExtension(this.ImagePath); - // Always load the data. foreach (PropertyItem propertyItem in this.Image.PropertyItems) { diff --git a/src/ImageProcessor/Imaging/Formats/PngFormat.cs b/src/ImageProcessor/Imaging/Formats/PngFormat.cs index da6b4dc5f..c0de55ba5 100644 --- a/src/ImageProcessor/Imaging/Formats/PngFormat.cs +++ b/src/ImageProcessor/Imaging/Formats/PngFormat.cs @@ -32,12 +32,14 @@ namespace ImageProcessor.Imaging.Formats /// /// Gets the list of file extensions. + /// Obviously png8 isn't a valid file extension but it's a neat way to + /// add the value to the format method detection. /// public override string[] FileExtensions { get { - return new[] { "png" }; + return new[] { "png8", "png" }; } } @@ -73,7 +75,7 @@ namespace ImageProcessor.Imaging.Formats /// public override Image Save(MemoryStream memoryStream, Image image) { - if (FormatUtilities.IsIndexed(image)) + if (this.IsIndexed) { image = new OctreeQuantizer(255, 8).Quantize(image); } @@ -92,7 +94,7 @@ namespace ImageProcessor.Imaging.Formats /// public override Image Save(string path, Image image) { - if (FormatUtilities.IsIndexed(image)) + if (this.IsIndexed) { image = new OctreeQuantizer(255, 8).Quantize(image); } diff --git a/src/ImageProcessor/Imaging/Formats/TiffFormat.cs b/src/ImageProcessor/Imaging/Formats/TiffFormat.cs index 226c0efab..dacc0dd1a 100644 --- a/src/ImageProcessor/Imaging/Formats/TiffFormat.cs +++ b/src/ImageProcessor/Imaging/Formats/TiffFormat.cs @@ -38,7 +38,7 @@ namespace ImageProcessor.Imaging.Formats { get { - return new[] { "tif", "tiff" }; + return new[] { "tiff", "tif" }; } } diff --git a/src/ImageProcessor/Processors/Filter.cs b/src/ImageProcessor/Processors/Filter.cs index b179b47bb..a91ba1d4f 100644 --- a/src/ImageProcessor/Processors/Filter.cs +++ b/src/ImageProcessor/Processors/Filter.cs @@ -58,7 +58,7 @@ namespace ImageProcessor.Processors try { newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); - IMatrixFilter matrix = this.DynamicParameter as IMatrixFilter; + IMatrixFilter matrix = this.DynamicParameter; if (matrix != null) { diff --git a/src/ImageProcessor/Processors/Flip.cs b/src/ImageProcessor/Processors/Flip.cs index 81b3cd602..59eb37162 100644 --- a/src/ImageProcessor/Processors/Flip.cs +++ b/src/ImageProcessor/Processors/Flip.cs @@ -21,24 +21,6 @@ namespace ImageProcessor.Processors /// public class Flip : IGraphicsProcessor { - /// - /// The regular expression to search strings for. - /// - /// - private static readonly Regex QueryRegex = new Regex(@"flip=(horizontal|vertical|both)", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern - { - get - { - return QueryRegex; - } - } - /// /// Gets or sets DynamicParameter. /// @@ -48,15 +30,6 @@ namespace ImageProcessor.Processors 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. /// @@ -66,53 +39,6 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - 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 direction = match.Value.Split('=')[1]; - - switch (direction) - { - case "horizontal": - this.DynamicParameter = RotateFlipType.RotateNoneFlipX; - break; - case "vertical": - this.DynamicParameter = RotateFlipType.RotateNoneFlipY; - break; - default: - this.DynamicParameter = RotateFlipType.RotateNoneFlipXY; - break; - } - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// @@ -150,6 +76,5 @@ namespace ImageProcessor.Processors return image; } - #endregion } } diff --git a/src/ImageProcessor/Processors/Format.cs b/src/ImageProcessor/Processors/Format.cs index 4879c9d11..21f5ec278 100644 --- a/src/ImageProcessor/Processors/Format.cs +++ b/src/ImageProcessor/Processors/Format.cs @@ -15,6 +15,9 @@ namespace ImageProcessor.Processors using System.Drawing; using System.Drawing.Imaging; using System.Text.RegularExpressions; + + using ImageProcessor.Imaging.Formats; + #endregion /// @@ -22,23 +25,6 @@ namespace ImageProcessor.Processors /// public class Format : IGraphicsProcessor { - /// - /// The regular expression to search strings for. - /// - private static readonly Regex QueryRegex = new Regex(@"format=(j(pg|peg)|pn(g8|g)|bmp|gif|ti(ff|f)|ico)", RegexOptions.Compiled); - - #region IGraphicsProcessor Members - /// - /// Gets the regular expression to search strings for. - /// - public Regex RegexPattern - { - get - { - return QueryRegex; - } - } - /// /// Gets or sets DynamicParameter. /// @@ -48,15 +34,6 @@ namespace ImageProcessor.Processors 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. /// @@ -66,40 +43,6 @@ namespace ImageProcessor.Processors set; } - /// - /// The position in the original string where the first character of the captured substring was found. - /// - /// - /// The query string to search. - /// - /// - /// The zero-based starting position in the original string where the captured substring was found. - /// - 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; - this.DynamicParameter = match.Value.Split('=')[1]; - } - - index += 1; - } - } - - return this.SortOrder; - } - /// /// Processes the image. /// @@ -112,45 +55,9 @@ namespace ImageProcessor.Processors /// public Image ProcessImage(ImageFactory factory) { - string format = this.DynamicParameter; - bool isIndexed = false; - ImageFormat imageFormat; - switch (format) - { - case "png": - imageFormat = ImageFormat.Png; - break; - case "png8": - imageFormat = ImageFormat.Png; - isIndexed = true; - break; - case "bmp": - imageFormat = ImageFormat.Bmp; - break; - case "gif": - imageFormat = ImageFormat.Gif; - isIndexed = true; - break; - case "tif": - case "tiff": - imageFormat = ImageFormat.Tiff; - break; - case "ico": - imageFormat = ImageFormat.Icon; - break; - default: - // Should be a jpeg or jpg. - imageFormat = ImageFormat.Jpeg; - break; - } - - // Set the internal property. - factory.OriginalExtension = string.Format(".{0}", format); - // TODO: Fix this. - //factory.Format(imageFormat); - + ISupportedImageFormat format = this.DynamicParameter; + factory.Format(format); return factory.Image; } - #endregion } }