Browse Source

Fixing formats

Former-commit-id: eeb59daa69fe67942e208e4808fa7ba85786b2dd
af/merge-core
James South 12 years ago
parent
commit
8b450b1aed
  1. 41
      src/ImageProcessor.Web/NET45/Caching/DiskCache.cs
  2. 72
      src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs
  3. 2
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  4. 2
      src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
  5. 4
      src/ImageProcessor.Web/NET45/Processors/Filter.cs
  6. 103
      src/ImageProcessor.Web/NET45/Processors/Flip.cs
  7. 156
      src/ImageProcessor.Web/NET45/Processors/Format.cs
  8. 7
      src/ImageProcessor/ImageFactory.cs
  9. 8
      src/ImageProcessor/Imaging/Formats/PngFormat.cs
  10. 2
      src/ImageProcessor/Imaging/Formats/TiffFormat.cs
  11. 2
      src/ImageProcessor/Processors/Filter.cs
  12. 75
      src/ImageProcessor/Processors/Flip.cs
  13. 103
      src/ImageProcessor/Processors/Format.cs

41
src/ImageProcessor.Web/NET45/Caching/DiskCache.cs

@ -72,11 +72,6 @@ namespace ImageProcessor.Web.Caching
/// The image name
/// </summary>
private readonly string imageName;
/// <summary>
/// Whether the request is for a remote image.
/// </summary>
private readonly bool isRemote;
#endregion
#region Constructors
@ -95,16 +90,12 @@ namespace ImageProcessor.Web.Caching
/// <param name="imageName">
/// The image name.
/// </param>
/// <param name="isRemote">
/// Whether the request is for a remote image.
/// </param>
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;
}
}

72
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
/// <summary>
@ -19,15 +25,20 @@ namespace ImageProcessor.Web.Helpers
/// </summary>
public static class ImageHelpers
{
/// <summary>
/// The regex pattern.
/// </summary>
private static readonly string RegexPattern = BuildRegexPattern();
/// <summary>
/// The image format regex.
/// </summary>
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);
/// <summary>
/// The image format regex for matching the file format at the end of a string.
/// </summary>
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);
/// <summary>
/// Checks a given string to check whether the value contains a valid image extension.
@ -36,7 +47,14 @@ namespace ImageProcessor.Web.Helpers
/// <returns>True the value contains a valid image extension, otherwise false.</returns>
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;
}
/// <summary>
@ -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;
}
/// <summary>
/// Builds a regular expression from the <see cref="T:ImageProcessor.Imaging.Formats.ISupportedImageFormat"/> type, this allows extensibility.
/// </summary>
/// <returns>
/// The <see cref="Regex"/> to match matrix filters.
/// </returns>
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();
}
}
}
}

2
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.

2
src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj

@ -67,6 +67,8 @@
<Compile Include="Processors\Contrast.cs" />
<Compile Include="Processors\Crop.cs" />
<Compile Include="Processors\Filter.cs" />
<Compile Include="Processors\Flip.cs" />
<Compile Include="Processors\Format.cs" />
<Compile Include="Processors\IWebGraphicsProcessor.cs" />
<Compile Include="Processors\Quality.cs" />
<Compile Include="Processors\Resize.cs" />

4
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);
}
/// <summary>
/// Parses the filter.
/// Parses the input string to return the correct <see cref="IMatrixFilter"/>.
/// </summary>
/// <param name="identifier">
/// The identifier.

103
src/ImageProcessor.Web/NET45/Processors/Flip.cs

@ -0,0 +1,103 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Flip.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Flips an image horizontally or vertically.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Processors
{
using System.Drawing;
using System.Text.RegularExpressions;
using ImageProcessor.Processors;
/// <summary>
/// Flips an image horizontally or vertically.
/// </summary>
public class Flip : IWebGraphicsProcessor
{
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"flip=(horizontal|vertical|both)", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Flip"/> class.
/// </summary>
public Flip()
{
this.Processor = new ImageProcessor.Processors.Flip();
}
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
public Regex RegexPattern
{
get
{
return QueryRegex;
}
}
/// <summary>
/// Gets the order in which this processor is to be used in a chain.
/// </summary>
public int SortOrder { get; private set; }
/// <summary>
/// Gets the associated graphics processor.
/// </summary>
public IGraphicsProcessor Processor { get; private set; }
/// <summary>
/// The position in the original string where the first character of the captured substring was found.
/// </summary>
/// <param name="queryString">
/// The query string to search.
/// </param>
/// <returns>
/// The zero-based starting position in the original string where the captured substring was found.
/// </returns>
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;
}
}
}

156
src/ImageProcessor.Web/NET45/Processors/Format.cs

@ -0,0 +1,156 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Format.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Sets the output of the image to a specific format.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
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;
/// <summary>
/// Sets the output of the image to a specific format.
/// </summary>
public class Format : IWebGraphicsProcessor
{
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = BuildRegex();
/// <summary>
/// Initializes a new instance of the <see cref="Format"/> class.
/// </summary>
public Format()
{
this.Processor = new ImageProcessor.Processors.Format();
}
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
public Regex RegexPattern
{
get
{
return QueryRegex;
}
}
/// <summary>
/// Gets the order in which this processor is to be used in a chain.
/// </summary>
public int SortOrder { get; private set; }
/// <summary>
/// Gets the associated graphics processor.
/// </summary>
public IGraphicsProcessor Processor { get; private set; }
/// <summary>
/// The position in the original string where the first character of the captured substring was found.
/// </summary>
/// <param name="queryString">
/// The query string to search.
/// </param>
/// <returns>
/// The zero-based starting position in the original string where the captured substring was found.
/// </returns>
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;
}
/// <summary>
/// Builds a regular expression from the <see cref="T:ImageProcessor.Imaging.Formats.ISupportedImageFormat"/> type, this allows extensibility.
/// </summary>
/// <returns>
/// The <see cref="Regex"/> to match matrix filters.
/// </returns>
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);
}
/// <summary>
/// Parses the input string to return the correct <see cref="ISupportedImageFormat"/>.
/// </summary>
/// <param name="identifier">
/// The identifier.
/// </param>
/// <returns>
/// The <see cref="ISupportedImageFormat"/>.
/// </returns>
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;
}
}
}

7
src/ImageProcessor/ImageFactory.cs

@ -124,11 +124,6 @@ namespace ImageProcessor
/// </summary>
internal Image Image { get; set; }
/// <summary>
/// Gets or sets the original extension.
/// </summary>
internal string OriginalExtension { get; set; }
/// <summary>
/// Gets or sets the memory stream for storing any input stream to prevent disposal.
/// </summary>
@ -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)
{

8
src/ImageProcessor/Imaging/Formats/PngFormat.cs

@ -32,12 +32,14 @@ namespace ImageProcessor.Imaging.Formats
/// <summary>
/// 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.
/// </summary>
public override string[] FileExtensions
{
get
{
return new[] { "png" };
return new[] { "png8", "png" };
}
}
@ -73,7 +75,7 @@ namespace ImageProcessor.Imaging.Formats
/// </returns>
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
/// </returns>
public override Image Save(string path, Image image)
{
if (FormatUtilities.IsIndexed(image))
if (this.IsIndexed)
{
image = new OctreeQuantizer(255, 8).Quantize(image);
}

2
src/ImageProcessor/Imaging/Formats/TiffFormat.cs

@ -38,7 +38,7 @@ namespace ImageProcessor.Imaging.Formats
{
get
{
return new[] { "tif", "tiff" };
return new[] { "tiff", "tif" };
}
}

2
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)
{

75
src/ImageProcessor/Processors/Flip.cs

@ -21,24 +21,6 @@ namespace ImageProcessor.Processors
/// </summary>
public class Flip : IGraphicsProcessor
{
/// <summary>
/// The regular expression to search strings for.
/// <see cref="http://stackoverflow.com/a/6400969/427899"/>
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"flip=(horizontal|vertical|both)", RegexOptions.Compiled);
#region IGraphicsProcessor Members
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
public Regex RegexPattern
{
get
{
return QueryRegex;
}
}
/// <summary>
/// Gets or sets DynamicParameter.
/// </summary>
@ -48,15 +30,6 @@ namespace ImageProcessor.Processors
set;
}
/// <summary>
/// Gets the order in which this processor is to be used in a chain.
/// </summary>
public int SortOrder
{
get;
private set;
}
/// <summary>
/// Gets or sets any additional settings required by the processor.
/// </summary>
@ -66,53 +39,6 @@ namespace ImageProcessor.Processors
set;
}
/// <summary>
/// The position in the original string where the first character of the captured substring was found.
/// </summary>
/// <param name="queryString">
/// The query string to search.
/// </param>
/// <returns>
/// The zero-based starting position in the original string where the captured substring was found.
/// </returns>
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;
}
/// <summary>
/// Processes the image.
/// </summary>
@ -150,6 +76,5 @@ namespace ImageProcessor.Processors
return image;
}
#endregion
}
}

103
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
/// <summary>
@ -22,23 +25,6 @@ namespace ImageProcessor.Processors
/// </summary>
public class Format : IGraphicsProcessor
{
/// <summary>
/// The regular expression to search strings for.
/// </summary>
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
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
public Regex RegexPattern
{
get
{
return QueryRegex;
}
}
/// <summary>
/// Gets or sets DynamicParameter.
/// </summary>
@ -48,15 +34,6 @@ namespace ImageProcessor.Processors
set;
}
/// <summary>
/// Gets the order in which this processor is to be used in a chain.
/// </summary>
public int SortOrder
{
get;
private set;
}
/// <summary>
/// Gets or sets any additional settings required by the processor.
/// </summary>
@ -66,40 +43,6 @@ namespace ImageProcessor.Processors
set;
}
/// <summary>
/// The position in the original string where the first character of the captured substring was found.
/// </summary>
/// <param name="queryString">
/// The query string to search.
/// </param>
/// <returns>
/// The zero-based starting position in the original string where the captured substring was found.
/// </returns>
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;
}
/// <summary>
/// Processes the image.
/// </summary>
@ -112,45 +55,9 @@ namespace ImageProcessor.Processors
/// </returns>
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
}
}

Loading…
Cancel
Save