Browse Source

Reformatting and bug fixing

Former-commit-id: 1c76591159c870330300c2ce1ef3d7b7ff28e2d9
af/merge-core
James South 12 years ago
parent
commit
ae6b178ca2
  1. 6
      src/ImageProcessor.Web/NET4/ImageProcessor.Web.csproj
  2. 5
      src/ImageProcessor.Web/NET45/Caching/DiskCache.cs
  3. 4
      src/ImageProcessor.Web/NET45/Config/ImageCacheSection.cs
  4. 96
      src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs
  5. 56
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  6. 17
      src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs
  7. 2
      src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
  8. 121
      src/ImageProcessor.Web/NET45/Preset.cs
  9. 1
      src/ImageProcessor.Web/NET45/Settings.StyleCop
  10. 149
      src/ImageProcessor/Extensions/ImageFormatExtensions.cs
  11. 2
      src/ImageProcessor/Extensions/StringExtensions.cs
  12. 41
      src/ImageProcessor/Helpers/Extensions/EnumExtensions.cs
  13. 76
      src/ImageProcessor/Helpers/Extensions/ImageExtensions.cs
  14. 35
      src/ImageProcessor/ImageFactory.cs
  15. 7
      src/ImageProcessor/ImageProcessor.csproj
  16. 18
      src/ImageProcessor/Imaging/Filters/ComicMatrixFilter.cs
  17. 187
      src/ImageProcessor/Imaging/ImageUtils.cs
  18. 4
      src/ImageProcessor/Processors/Crop.cs
  19. 5
      src/ImageProcessor/Processors/Format.cs
  20. 3
      src/ImageProcessor/Processors/Resize.cs
  21. 2
      src/ImageProcessor/Processors/Saturation.cs
  22. 3
      src/ImageProcessor/Processors/Watermark.cs
  23. 2
      src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml
  24. 2
      src/TestWebsites/NET45/Test_Website_NET45/Web.config
  25. 2
      src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config

6
src/ImageProcessor.Web/NET4/ImageProcessor.Web.csproj

@ -82,13 +82,13 @@
<Compile Include="..\NET45\Config\ImageProcessingSection.cs" />
<Compile Include="..\NET45\Config\ImageProcessorConfig.cs" />
<Compile Include="..\NET45\Config\ImageSecuritySection.cs" />
<Compile Include="..\NET45\Helpers\ImageHelpers.cs">
<Link>ImageHelpers.cs</Link>
</Compile>
<Compile Include="..\NET45\Helpers\RemoteFile.cs" />
<Compile Include="..\NET45\Helpers\TaskHelpers.cs" />
<Compile Include="..\NET45\HttpModules\ImageProcessingModule.cs" />
<Compile Include="..\NET45\ImageFactoryExtensions.cs" />
<Compile Include="..\NET45\Preset.cs">
<Link>Preset.cs</Link>
</Compile>
<Compile Include="..\NET45\Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

5
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();

4
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
/// <summary>

96
src/ImageProcessor.Web/NET45/Helpers/ImageHelpers.cs

@ -0,0 +1,96 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageHelpers.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The image helpers.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Helpers
{
#region Using
using System.Drawing.Imaging;
using System.IO;
using System.Text.RegularExpressions;
#endregion
/// <summary>
/// The image helpers.
/// </summary>
public static class ImageHelpers
{
/// <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);
/// <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);
/// <summary>
/// Checks a given string to check whether the value contains a valid image extension.
/// </summary>
/// <param name="fileName">The string containing the filename to check.</param>
/// <returns>True the value contains a valid image extension, otherwise false.</returns>
public static bool IsValidImageExtension(string fileName)
{
return EndFormatRegex.IsMatch(fileName);
}
/// <summary>
/// Returns the correct file extension for the given string input
/// </summary>
/// <param name="input">
/// The string to parse.
/// </param>
/// <returns>
/// The correct file extension for the given string input if it can find one; otherwise an empty string.
/// </returns>
public static string GetExtension(string input)
{
Match match = FormatRegex.Matches(input)[0];
return match.Success ? match.Value : string.Empty;
}
/// <summary>
/// Returns the correct image format based on the given file extension.
/// </summary>
/// <param name="fileName">The string containing the filename to check against.</param>
/// <returns>The correct image format based on the given filename.</returns>
//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;
//}
}
}

56
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
/// </summary>
private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE_054F217C-11CF-49FF-8D2F-698E8E6EB58F";
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex PresetRegex = new Regex(@"preset=[^&]*", RegexOptions.Compiled);
/// <summary>
/// The value to prefix any remote image requests with to ensure they get captured.
/// </summary>
@ -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<DateTime, DateTime> 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<DateTime, DateTime> 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);
}
/// <summary>
/// Replaces preset values stored in the configuration in the querystring.
/// </summary>
/// <param name="queryString">
/// The query string.
/// </param>
/// <returns>
/// The <see cref="string"/> containing the updated querystring.
/// </returns>
private string ReplacePresetsInQueryString(string queryString)
{
// We use the processor config system to store the preset values.
Dictionary<string, string> 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
}
}

17
src/ImageProcessor.Web/NET45/ImageFactoryExtensions.cs

@ -1,9 +1,12 @@
// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageFactoryExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
// <summary>
// Extends the ImageFactory class to provide a fluent API.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
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;
}
}
}
}

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

@ -53,11 +53,11 @@
<Compile Include="Config\ImageProcessingSection.cs" />
<Compile Include="Config\ImageProcessorConfig.cs" />
<Compile Include="Config\ImageSecuritySection.cs" />
<Compile Include="Helpers\ImageHelpers.cs" />
<Compile Include="Helpers\RemoteFile.cs" />
<Compile Include="Helpers\TaskHelpers.cs" />
<Compile Include="HttpModules\ImageProcessingModule.cs" />
<Compile Include="ImageFactoryExtensions.cs" />
<Compile Include="Preset.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

121
src/ImageProcessor.Web/NET45/Preset.cs

@ -1,121 +0,0 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Preset.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates methods to that allow the processing of preset image processing instructions.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web
{
using System.Collections.Generic;
using System.Drawing;
using System.Text.RegularExpressions;
using ImageProcessor.Processors;
/// <summary>
/// Encapsulates methods to that allow the processing of preset image processing instructions.
/// </summary>
public class Preset : IGraphicsProcessor
{
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"preset=[^&]*", RegexOptions.Compiled);
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
public Regex RegexPattern
{
get
{
return QueryRegex;
}
}
/// <summary>
/// Gets DynamicParameter.
/// </summary>
public dynamic DynamicParameter
{
get;
private 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>
public Dictionary<string, string> Settings
{
get;
set;
}
/// <summary>
/// The match regex index.
/// </summary>
/// <param name="queryString">
/// The query string.
/// </param>
/// <returns>
/// The <see cref="int"/>.
/// </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 preset = match.Value;
this.DynamicParameter = preset;
}
index += 1;
}
}
return this.SortOrder;
}
/// <summary>
/// Processes the image.
/// </summary>
/// <param name="factory">The the current instance of the <see cref="T:ImageProcessor.ImageFactory" /> class containing
/// the image to process.</param>
/// <returns>
/// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory" /> class.
/// </returns>
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;
}
}
}

1
src/ImageProcessor.Web/NET45/Settings.StyleCop

@ -2,6 +2,7 @@
<GlobalSettings>
<CollectionProperty Name="RecognizedWords">
<Value>Mutexes</Value>
<Value>querystring</Value>
</CollectionProperty>
</GlobalSettings>
<Analyzers>

149
src/ImageProcessor/Extensions/ImageFormatExtensions.cs

@ -0,0 +1,149 @@
// --------------------------------------------------------------------------------------------------------------------
// <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.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;
}
}
}

2
src/ImageProcessor/Helpers/Extensions/StringExtensions.cs → src/ImageProcessor/Extensions/StringExtensions.cs

@ -8,7 +8,7 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Helpers.Extensions
namespace ImageProcessor.Extensions
{
#region Using
using System;

41
src/ImageProcessor/Helpers/Extensions/EnumExtensions.cs

@ -1,41 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="EnumExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
namespace ImageProcessor.Helpers.Extensions
{
#region Using
using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
#endregion
/// <summary>
/// Encapsulates a series of time saving extension methods to <see cref="T:System.Enum">Enum</see>s.
/// </summary>
public static class EnumExtensions
{
#region Methods
/// <summary>
/// Extends the <see cref="T:System.Enum">Enum</see> type to return the description attribute for the given type.
/// Useful for when the type to match in the data source contains spaces.
/// </summary>
/// <param name="expression">The given <see cref="T:System.Enum">Enum</see> that this method extends.</param>
/// <returns>A string containing the Enum's description attribute.</returns>
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
}
}

76
src/ImageProcessor/Helpers/Extensions/ImageExtensions.cs

@ -1,76 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ImageExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
namespace ImageProcessor.Helpers.Extensions
{
#region Using
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
#endregion
/// <summary>
/// Extensions to the <see cref="T:System.Drawing.Image"/> class
/// </summary>
public static class ImageExtensions
{
/// <summary>
/// Converts an image to an array of bytes.
/// </summary>
/// <param name="image">The <see cref="T:System.Drawing.Image"/> instance that this method extends.</param>
/// <param name="imageFormat">The <see cref="T:System.Drawing.Imaging.ImageFormat"/> to export the image with.</param>
/// <returns>A byte array representing the current image.</returns>
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;
}
}
}

35
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.
/// </summary>
public ImageFormat ImageFormat { get; private set; }
/// <summary>
/// Gets the mime type.
/// </summary>
public string MimeType
{
get
{
return this.ImageFormat.GetMimeType();
}
}
/// <summary>
/// Gets or sets the original extension.
/// </summary>
@ -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
/// </returns>
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)
{

7
src/ImageProcessor/ImageProcessor.csproj

@ -59,9 +59,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helpers\Extensions\ImageExtensions.cs" />
<Compile Include="Helpers\Extensions\EnumExtensions.cs" />
<Compile Include="Helpers\Extensions\StringExtensions.cs" />
<Compile Include="Extensions\EnumExtensions.cs" />
<Compile Include="Extensions\ImageFormatExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="ImageFactory.cs" />
<Compile Include="Imaging\AnchorPosition.cs" />
<Compile Include="Imaging\Convolution.cs" />
@ -105,6 +105,7 @@
<Compile Include="Processors\Watermark.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

18
src/ImageProcessor/Imaging/Filters/ComicMatrixFilter.cs

@ -50,7 +50,7 @@ namespace ImageProcessor.Imaging.Filters
/// </summary>
Alpha = 3
}
/// <summary>
/// Gets the <see cref="T:System.Drawing.Imaging.ColorMatrix"/> for this filter instance.
/// </summary>
@ -77,6 +77,7 @@ namespace ImageProcessor.Imaging.Filters
Bitmap highBitmap = null;
Bitmap lowBitmap = null;
Bitmap patternBitmap = null;
Bitmap edgeBitmap = null;
try
{
@ -92,6 +93,14 @@ namespace ImageProcessor.Imaging.Filters
// Apply a oil painting filter to the image.
highBitmap = OilPaintFilter((Bitmap)image, 3, 5);
// Draw the edges.
edgeBitmap = DrawEdges((Bitmap)image, 120);
//GaussianLayer gaussianLayer = new GaussianLayer(1);
//Convolution convolution = new Convolution(gaussianLayer.Sigma) { Threshold = gaussianLayer.Threshold };
//double[,] kernel = convolution.CreateGuassianBlurFilter(gaussianLayer.Size);
//edgeBitmap = convolution.ProcessKernel(edgeBitmap, kernel);
using (Graphics graphics = Graphics.FromImage(highBitmap))
{
graphics.DrawImage(highBitmap, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
@ -137,6 +146,7 @@ namespace ImageProcessor.Imaging.Filters
// Overlay the image.
graphics.DrawImage(highBitmap, 0, 0);
graphics.DrawImage(lowBitmap, 0, 0);
graphics.DrawImage(edgeBitmap, 0, 0);
// Draw an edge around the image.
using (Pen blackPen = new Pen(Color.Black))
@ -149,6 +159,7 @@ namespace ImageProcessor.Imaging.Filters
highBitmap.Dispose();
lowBitmap.Dispose();
patternBitmap.Dispose();
edgeBitmap.Dispose();
}
}
@ -177,6 +188,11 @@ namespace ImageProcessor.Imaging.Filters
{
patternBitmap.Dispose();
}
if (edgeBitmap != null)
{
edgeBitmap.Dispose();
}
}
return image;

187
src/ImageProcessor/Imaging/ImageUtils.cs

@ -11,12 +11,8 @@
namespace ImageProcessor.Imaging
{
#region Using
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
#endregion
/// <summary>
@ -24,163 +20,6 @@ namespace ImageProcessor.Imaging
/// </summary>
public static class ImageUtils
{
/// <summary>
/// The image format regex.
/// </summary>
private static readonly Regex FormatRegex = new Regex(@"(\.?)(j(pg|peg)|bmp|png|gif|ti(ff|f))", RegexOptions.Compiled | 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))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft);
/// <summary>
/// Returns the correct response type based on the given request path.
/// </summary>
/// <param name="request">
/// The request to match.
/// </param>
/// <returns>
/// The correct <see cref="ResponseType"/>.
/// </returns>
public static ResponseType GetResponseType(string request)
{
Match match = FormatRegex.Matches(request)[0];
switch (match.Value.ToUpperInvariant())
{
case "PNG":
case ".PNG":
return ResponseType.Png;
case "BMP":
case ".BMP":
return ResponseType.Bmp;
case "GIF":
case ".GIF":
return ResponseType.Gif;
case "TIF":
case "TIFF":
case ".TIF":
case ".TIFF":
return ResponseType.Tiff;
default:
return ResponseType.Jpeg;
}
}
/// <summary>
/// Returns the correct image format based on the given file extension.
/// </summary>
/// <param name="fileName">The string containing the filename to check against.</param>
/// <returns>The correct image format based on the given filename.</returns>
public static ImageFormat GetImageFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
if (extension != null)
{
string ext = extension.ToUpperInvariant();
switch (ext)
{
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;
}
/// <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 GetExtensionFromImageFormat(ImageFormat imageFormat, string originalExtension)
{
switch (imageFormat.ToString())
{
case "Gif":
return ".gif";
case "Bmp":
return ".bmp";
case "Png":
return ".png";
case "Tif":
case "Tiff":
if (!string.IsNullOrWhiteSpace(originalExtension) && originalExtension.ToUpperInvariant() == ".TIFF")
{
return ".tiff";
}
return ".tif";
default:
if (!string.IsNullOrWhiteSpace(originalExtension) && originalExtension.ToUpperInvariant() == ".JPEG")
{
return ".jpeg";
}
return ".jpg";
}
}
/// <summary>
/// Returns the correct image format based on the given response type.
/// </summary>
/// <param name="responseType">
/// The <see cref="ImageProcessor.Imaging.ResponseType"/> to check against.
/// </param>
/// <returns>The correct image format based on the given response type.</returns>
public static ImageFormat GetImageFormat(ResponseType responseType)
{
switch (responseType)
{
case ResponseType.Png:
return ImageFormat.Png;
case ResponseType.Bmp:
return ImageFormat.Bmp;
case ResponseType.Gif:
return ImageFormat.Gif;
case ResponseType.Tiff:
return ImageFormat.Tiff;
default:
// Should be a jpeg.
return ImageFormat.Jpeg;
}
}
/// <summary>
/// Returns the first ImageCodeInfo instance with the specified mime type.
/// </summary>
/// <param name="mimeType">
/// A string that contains the codec's Multipurpose Internet Mail Extensions (MIME) type.
/// </param>
/// <returns>
/// The first ImageCodeInfo instance with the specified mime type.
/// </returns>
public static ImageCodecInfo GetImageCodeInfo(string mimeType)
{
ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
return info.FirstOrDefault(ici => ici.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase));
}
/// <summary>
/// Returns an instance of EncodingParameters for jpeg compression.
/// </summary>
@ -208,32 +47,6 @@ namespace ImageProcessor.Imaging
return encoderParameters;
}
/// <summary>
/// Checks a given string to check whether the value contains a valid image extension.
/// </summary>
/// <param name="fileName">The string containing the filename to check.</param>
/// <returns>True the value contains a valid image extension, otherwise false.</returns>
public static bool IsValidImageExtension(string fileName)
{
return EndFormatRegex.IsMatch(fileName);
}
/// <summary>
/// Returns the correct file extension for the given string input
/// </summary>
/// <param name="input">
/// The string to parse.
/// </param>
/// <returns>
/// The correct file extension for the given string input if it can find one; otherwise an empty string.
/// </returns>
public static string GetExtension(string input)
{
Match match = FormatRegex.Matches(input)[0];
return match.Success ? match.Value : string.Empty;
}
/// <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>

4
src/ImageProcessor/Processors/Crop.cs

@ -16,7 +16,9 @@ namespace ImageProcessor.Processors
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using ImageProcessor.Helpers.Extensions;
using ImageProcessor.Extensions;
#endregion
/// <summary>

5
src/ImageProcessor/Processors/Format.cs

@ -25,7 +25,7 @@ namespace ImageProcessor.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"format=(j(pg|peg)|png|png8|bmp|gif|ti(ff|f))", RegexOptions.Compiled);
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>
@ -135,6 +135,9 @@ namespace ImageProcessor.Processors
case "tiff":
imageFormat = ImageFormat.Tiff;
break;
case "ico":
imageFormat = ImageFormat.Icon;
break;
default:
// Should be a jpeg or jpg.
imageFormat = ImageFormat.Jpeg;

3
src/ImageProcessor/Processors/Resize.cs

@ -19,7 +19,8 @@ namespace ImageProcessor.Processors
using System.Drawing.Imaging;
using System.Text;
using System.Text.RegularExpressions;
using ImageProcessor.Helpers.Extensions;
using ImageProcessor.Extensions;
using ImageProcessor.Imaging;
#endregion

2
src/ImageProcessor/Processors/Saturation.cs

@ -15,7 +15,7 @@ namespace ImageProcessor.Processors
using System.Drawing;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using ImageProcessor.Helpers.Extensions;
#endregion
/// <summary>

3
src/ImageProcessor/Processors/Watermark.cs

@ -18,7 +18,8 @@ namespace ImageProcessor.Processors
using System.Drawing.Text;
using System.Linq;
using System.Text.RegularExpressions;
using ImageProcessor.Helpers.Extensions;
using ImageProcessor.Extensions;
using ImageProcessor.Imaging;
#endregion

2
src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml

@ -177,7 +177,7 @@
</div>
<div class="col-s-6">
<h2>Gaussian Sharpen</h2>
<img src="/images/Penguins.jpg?width=300&blur=11,sigma-1.5,threshold-10" />
<img src="/images/Penguins.jpg?width=300&sharpen=11,sigma-1.5,threshold-10" />
</div>
</div>
</section>

2
src/TestWebsites/NET45/Test_Website_NET45/Web.config

@ -49,7 +49,7 @@
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />

2
src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config

@ -23,7 +23,7 @@
</plugin>
<plugin name="Preset">
<settings>
<setting key="demo" value="width=300&#038;height=150"/>
<setting key="demo" value="width=300&#038;height=150&#038;format=png"/>
</settings>
</plugin>
</plugins>

Loading…
Cancel
Save