Browse Source

v2.3.0.6 Fixes issue #15

Former-commit-id: 77aee4fa6573802645f092b9b454d632f19ed361
pull/17/head
James South 13 years ago
parent
commit
98e1875477
  1. 32
      src/ImageProcessor.Web/NET45/Caching/DiskCache.cs
  2. 32
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  3. 4
      src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs
  4. 11
      src/ImageProcessor/Helpers/Extensions/StringExtensions.cs
  5. 30
      src/ImageProcessor/ImageFactory.cs
  6. 216
      src/ImageProcessor/Processors/Constrain.cs
  7. 2
      src/ImageProcessor/Processors/Crop.cs
  8. 36
      src/ImageProcessor/Processors/Resize.cs
  9. 275
      src/ImageProcessor/Processors/ResizeBase.cs
  10. 4
      src/ImageProcessor/Properties/AssemblyInfo.cs
  11. BIN
      src/Nuget/ImageProcessor.1.7.0.0.nupkg
  12. BIN
      src/Nuget/ImageProcessor.1.7.0.1.nupkg
  13. BIN
      src/Nuget/ImageProcessor.1.7.0.2.nupkg
  14. BIN
      src/Nuget/ImageProcessor.1.7.0.3.nupkg
  15. BIN
      src/Nuget/ImageProcessor.1.7.1.1.nupkg
  16. 1
      src/Nuget/ImageProcessor.Web.2.3.0.3.nupkg.REMOVED.git-id
  17. 1
      src/Nuget/ImageProcessor.Web.2.3.0.4.nupkg.REMOVED.git-id
  18. 1
      src/Nuget/ImageProcessor.Web.2.3.0.5.nupkg.REMOVED.git-id
  19. 1
      src/Nuget/ImageProcessor.Web.2.3.0.6.nupkg.REMOVED.git-id
  20. 6
      src/TestWebsites/NET4/Web.config
  21. 134
      src/TestWebsites/NET45/Test_Website_NET45/Web.config

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

@ -306,6 +306,18 @@ namespace ImageProcessor.Web.Caching
return isUpdated; return isUpdated;
} }
/// <summary>
/// Gets the <see cref="T:System.DateTime"/> set to the last write time of the file.
/// </summary>
/// <returns>
/// The last write time of the file.
/// </returns>
internal async Task<DateTime> GetLastWriteTimeAsync()
{
// Create Action delegate for TrimCachedFolders.
return await TaskHelpers.Run<DateTime>(this.GetLastWriteTime);
}
/// <summary> /// <summary>
/// Sets the LastWriteTime of the cached file to match the original file. /// Sets the LastWriteTime of the cached file to match the original file.
/// </summary> /// </summary>
@ -448,6 +460,26 @@ namespace ImageProcessor.Web.Caching
return cachedPath; return cachedPath;
} }
/// <summary>
/// Gets last modified time of the image.
/// </summary>
/// <returns>
/// The <see cref="DateTime"/> representing the last modified time of the image.
/// </returns>
private DateTime GetLastWriteTime()
{
string key = Path.GetFileNameWithoutExtension(this.CachedPath);
CachedImage cachedImage;
DateTime dateTime = DateTime.UtcNow;
if (PersistantDictionary.Instance.TryGetValue(key, out cachedImage))
{
dateTime = cachedImage.LastWriteTimeUtc;
}
return dateTime;
}
/// <summary> /// <summary>
/// The rough date time compare. /// The rough date time compare.
/// </summary> /// </summary>

32
src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs

@ -304,6 +304,23 @@ namespace ImageProcessor.Web.HttpModules
// Store the response type in the context for later retrieval. // Store the response type in the context for later retrieval.
context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(fullPath).ToDescription(); context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(fullPath).ToDescription();
string incomingEtag = context.Request.Headers["If-None-Match"];
if (incomingEtag != null && !isNewOrUpdated)
{
// Explicitly set the Content-Length header so the client doesn't wait for
// content but keeps the connection open for other requests
context.Response.AddHeader("Content-Length", "0");
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
context.Response.SuppressContent = true;
this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey]);
if (!isRemote)
{
return;
}
}
// The cached file is valid so just rewrite the path. // The cached file is valid so just rewrite the path.
context.RewritePath(cache.GetVirtualCachedPath(), false); context.RewritePath(cache.GetVirtualCachedPath(), false);
@ -334,7 +351,7 @@ namespace ImageProcessor.Web.HttpModules
response.AddHeader("Image-Served-By", "ImageProcessor.Web/" + AssemblyVersion); response.AddHeader("Image-Served-By", "ImageProcessor.Web/" + AssemblyVersion);
HttpCachePolicy cache = response.Cache; HttpCachePolicy cache = response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.VaryByHeaders["Accept-Encoding"] = true; cache.VaryByHeaders["Accept-Encoding"] = true;
int maxDays = DiskCache.MaxFileCachedDuration; int maxDays = DiskCache.MaxFileCachedDuration;
@ -342,19 +359,6 @@ namespace ImageProcessor.Web.HttpModules
cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(maxDays)); cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(maxDays));
cache.SetMaxAge(new TimeSpan(maxDays, 0, 0, 0)); cache.SetMaxAge(new TimeSpan(maxDays, 0, 0, 0));
cache.SetRevalidation(HttpCacheRevalidation.AllCaches); cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
string incomingEtag = context.Request.Headers["If-None-Match"];
cache.SetCacheability(HttpCacheability.Public);
if (incomingEtag == null)
{
return;
}
response.Clear();
response.StatusCode = (int)HttpStatusCode.NotModified;
response.SuppressContent = true;
} }
#endregion #endregion
} }

4
src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs

@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("2.3.0.4")] [assembly: AssemblyVersion("2.3.0.6")]
[assembly: AssemblyFileVersion("2.3.0.4")] [assembly: AssemblyFileVersion("2.3.0.6")]

11
src/ImageProcessor/Helpers/Extensions/StringExtensions.cs

@ -1,9 +1,12 @@
// ----------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// <copyright file="StringExtensions.cs" company="James South"> // <copyright file="StringExtensions.cs" company="James South">
// Copyright (c) James South. // Copyright (c) James South.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
// ----------------------------------------------------------------------- // <summary>
// Encapsulates a series of time saving extension methods to the <see cref="T:System.String" /> class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Helpers.Extensions namespace ImageProcessor.Helpers.Extensions
{ {

30
src/ImageProcessor/ImageFactory.cs

@ -189,7 +189,7 @@ namespace ImageProcessor
this.JpegQuality = DefaultJpegQuality; this.JpegQuality = DefaultJpegQuality;
ImageFormat imageFormat = ImageUtils.GetImageFormat(imageName); ImageFormat imageFormat = ImageUtils.GetImageFormat(imageName);
this.backupImageFormat = imageFormat; this.backupImageFormat = imageFormat;
this.originalExtension = Path.GetExtension(imagePath); this.originalExtension = Path.GetExtension(this.ImagePath);
this.ImageFormat = imageFormat; this.ImageFormat = imageFormat;
this.isIndexed = ImageUtils.IsIndexed(this.Image); this.isIndexed = ImageUtils.IsIndexed(this.Image);
this.ShouldProcess = true; this.ShouldProcess = true;
@ -321,6 +321,32 @@ namespace ImageProcessor
return this; return this;
} }
/// <summary>
/// Constrains the current image, resizing it to fit within the given dimensions whilst keeping its aspect ratio.
/// </summary>
/// <param name="size">
/// The <see cref="T:System.Drawing.Size"/> containing the maximum width and height to set the image to.
/// </param>
/// <returns>
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
/// </returns>
public ImageFactory Constrain(Size size)
{
if (this.ShouldProcess)
{
int width = size.Width;
int height = size.Height;
var constrainSettings = new Dictionary<string, string> { { "MaxWidth", width.ToString("G") }, { "MaxHeight", height.ToString("G") } };
Constrain constrain = new Constrain { DynamicParameter = new Size(width, height), Settings = constrainSettings };
this.Image = constrain.ProcessImage(this);
}
return this;
}
/// <summary> /// <summary>
/// Changes the contrast of the current image. /// Changes the contrast of the current image.
/// </summary> /// </summary>
@ -349,6 +375,8 @@ namespace ImageProcessor
return this; return this;
} }
/// <summary> /// <summary>
/// Crops the current image to the given location and size. /// Crops the current image to the given location and size.
/// </summary> /// </summary>

216
src/ImageProcessor/Processors/Constrain.cs

@ -1,88 +1,136 @@
using System.Collections.Generic; // --------------------------------------------------------------------------------------------------------------------
using System.Drawing; // <copyright file="Constrain.cs" company="James South">
using System.Text.RegularExpressions; // Copyright (c) James South.
using ImageProcessor.Helpers.Extensions; // Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Constrains an image to the given dimensions.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Processors namespace ImageProcessor.Processors
{ {
/// <summary> #region Using
/// Constrains an image to the given dimensions. using System.Collections.Generic;
/// </summary> using System.Drawing;
public class Constrain : ResizeBase using System.Text.RegularExpressions;
{ using ImageProcessor.Helpers.Extensions;
private static readonly Regex QueryRegex = new Regex(@"constrain=\d+,\d+", RegexOptions.Compiled); #endregion
public override Regex RegexPattern /// <summary>
{ /// Constrains an image to the given dimensions.
get /// </summary>
{ public class Constrain : ResizeBase
return QueryRegex; {
} /// <summary>
} /// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"constrain=\d+[,-]\d+", RegexOptions.Compiled);
public override dynamic DynamicParameter { get; set; }
public override int SortOrder { get; protected set; } #region IGraphicsProcessor Members
public override Dictionary<string, string> Settings { get; set; } /// <summary>
/// Gets the regular expression to search strings for.
public override int MatchRegexIndex(string queryString) /// </summary>
{ public override Regex RegexPattern
int index = 0; {
get
// Set the sort order to max to allow filtering. {
this.SortOrder = int.MaxValue; return QueryRegex;
}
foreach (Match match in this.RegexPattern.Matches(queryString)) }
{
if (match.Success) /// <summary>
{ /// Gets or sets DynamicParameter.
if (index == 0) /// </summary>
{ public override dynamic DynamicParameter { get; set; }
// Set the index on the first instance only.
this.SortOrder = match.Index; /// <summary>
int[] constraints = match.Value.ToPositiveIntegerArray(); /// Gets the order in which this processor is to be used in a chain.
/// </summary>
int x = constraints[0]; public override int SortOrder { get; protected set; }
int y = constraints[1];
/// <summary>
this.DynamicParameter = new Size(x, y); /// Gets or sets any additional settings required by the processor.
} /// </summary>
public override Dictionary<string, string> Settings { get; set; }
index += 1;
} /// <summary>
} /// The position in the original string where the first character of the captured substring was found.
/// </summary>
return this.SortOrder; /// <param name="queryString">
} /// The query string to search.
/// </param>
public override Image ProcessImage(ImageFactory factory) /// <returns>
{ /// The zero-based starting position in the original string where the captured substring was found.
/// </returns>
double constrainedWidth = DynamicParameter.Width; public override int MatchRegexIndex(string queryString)
double constrainedHeight = DynamicParameter.Height; {
int index = 0;
var original = factory.Image;
double width = original.Width; // Set the sort order to max to allow filtering.
double height = original.Height; this.SortOrder = int.MaxValue;
if (width > constrainedWidth || height > constrainedHeight) foreach (Match match in this.RegexPattern.Matches(queryString))
{ {
if (match.Success)
double constraintRatio = constrainedHeight / constrainedWidth; {
double originalRatio = height / width; if (index == 0)
{
Size newSize = originalRatio < constraintRatio // Set the index on the first instance only.
? new Size((int)constrainedWidth, 0) this.SortOrder = match.Index;
: new Size(0, (int)constrainedHeight); int[] constraints = match.Value.ToPositiveIntegerArray();
int defaultMaxWidth; int x = constraints[0];
int defaultMaxHeight; int y = constraints[1];
int.TryParse(this.Settings["MaxWidth"], out defaultMaxWidth);
int.TryParse(this.Settings["MaxHeight"], out defaultMaxHeight); this.DynamicParameter = new Size(x, y);
}
return ResizeImage(factory, newSize.Width, newSize.Height, defaultMaxWidth, defaultMaxHeight);
} index += 1;
return factory.Image; }
} }
}
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 override Image ProcessImage(ImageFactory factory)
{
double constrainedWidth = this.DynamicParameter.Width;
double constrainedHeight = this.DynamicParameter.Height;
Image original = factory.Image;
double width = original.Width;
double height = original.Height;
if (width > constrainedWidth || height > constrainedHeight)
{
double constraintRatio = constrainedHeight / constrainedWidth;
double originalRatio = height / width;
Size newSize = originalRatio < constraintRatio
? new Size((int)constrainedWidth, 0)
: new Size(0, (int)constrainedHeight);
int defaultMaxWidth;
int defaultMaxHeight;
int.TryParse(this.Settings["MaxWidth"], out defaultMaxWidth);
int.TryParse(this.Settings["MaxHeight"], out defaultMaxHeight);
return this.ResizeImage(factory, newSize.Width, newSize.Height, defaultMaxWidth, defaultMaxHeight);
}
return factory.Image;
}
#endregion
}
} }

2
src/ImageProcessor/Processors/Crop.cs

@ -25,7 +25,7 @@ namespace ImageProcessor.Processors
/// The regular expression to search strings for. /// The regular expression to search strings for.
/// <see cref="http://stackoverflow.com/a/6400969/427899"/> /// <see cref="http://stackoverflow.com/a/6400969/427899"/>
/// </summary> /// </summary>
private static readonly Regex QueryRegex = new Regex(@"crop=\d+-\d+-\d+-\d+", RegexOptions.Compiled); private static readonly Regex QueryRegex = new Regex(@"crop=\d+[,-]\d+[,-]\d+[,-]\d+", RegexOptions.Compiled);
#region IGraphicsProcessor Members #region IGraphicsProcessor Members
/// <summary> /// <summary>

36
src/ImageProcessor/Processors/Resize.cs

@ -1,18 +1,18 @@
// ----------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// <copyright file="Resize.cs" company="James South"> // <copyright file="Resize.cs" company="James South">
// Copyright (c) James South. // Copyright (c) James South.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
// ----------------------------------------------------------------------- // <summary>
// Resizes an image to the given dimensions.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Processors namespace ImageProcessor.Processors
{ {
#region Using #region Using
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ImageProcessor.Helpers.Extensions; using ImageProcessor.Helpers.Extensions;
#endregion #endregion
@ -92,7 +92,7 @@ namespace ImageProcessor.Processors
// Set the index on the first instance only. // Set the index on the first instance only.
this.SortOrder = match.Index; this.SortOrder = match.Index;
} }
// Match syntax // Match syntax
if (match.Value.Contains("width")) if (match.Value.Contains("width"))
{ {
@ -102,7 +102,7 @@ namespace ImageProcessor.Processors
{ {
size.Height = match.Value.ToPositiveIntegerArray()[0]; size.Height = match.Value.ToPositiveIntegerArray()[0];
} }
index += 1; index += 1;
} }
} }
@ -123,18 +123,16 @@ namespace ImageProcessor.Processors
/// </returns> /// </returns>
public override Image ProcessImage(ImageFactory factory) public override Image ProcessImage(ImageFactory factory)
{ {
int width = this.DynamicParameter.Width ?? 0;
int height = this.DynamicParameter.Height ?? 0;
int width = this.DynamicParameter.Width ?? 0; int defaultMaxWidth;
int height = this.DynamicParameter.Height ?? 0; int defaultMaxHeight;
int.TryParse(this.Settings["MaxWidth"], out defaultMaxWidth);
int.TryParse(this.Settings["MaxHeight"], out defaultMaxHeight);
int defaultMaxWidth; return this.ResizeImage(factory, width, height, defaultMaxWidth, defaultMaxHeight);
int defaultMaxHeight;
int.TryParse(this.Settings["MaxWidth"], out defaultMaxWidth);
int.TryParse(this.Settings["MaxHeight"], out defaultMaxHeight);
return ResizeImage(factory, width, height, defaultMaxWidth, defaultMaxHeight);
} }
#endregion
#endregion
} }
} }

275
src/ImageProcessor/Processors/ResizeBase.cs

@ -1,104 +1,179 @@
using System; // --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic; // <copyright file="ResizeBase.cs" company="James South">
using System.Drawing; // Copyright (c) James South.
using System.Drawing.Drawing2D; // Licensed under the Apache License, Version 2.0.
using System.Drawing.Imaging; // </copyright>
using System.Text.RegularExpressions; // <summary>
// The resize base for inheriting resizable methods from.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Processors namespace ImageProcessor.Processors
{ {
public abstract class ResizeBase : IGraphicsProcessor #region Using
{ using System;
public abstract Regex RegexPattern { get; } using System.Collections.Generic;
public abstract dynamic DynamicParameter { get; set; } using System.Drawing;
public abstract int SortOrder { get; protected set; } using System.Drawing.Drawing2D;
public abstract Dictionary<string, string> Settings { get; set; } using System.Drawing.Imaging;
public abstract int MatchRegexIndex(string queryString); using System.Text.RegularExpressions;
public abstract Image ProcessImage(ImageFactory factory); #endregion
protected Image ResizeImage(ImageFactory factory, int width, int height, int defaultMaxWidth, int defaultMaxHeight) /// <summary>
{ /// The resize base for inheriting resizable methods from.
Bitmap newImage = null; /// </summary>
Image image = factory.Image; public abstract class ResizeBase : IGraphicsProcessor
{
try #region IGraphicsProcessor Members
{ /// <summary>
int sourceWidth = image.Width; /// Gets the regular expression to search strings for.
int sourceHeight = image.Height; /// </summary>
public abstract Regex RegexPattern { get; }
int maxWidth = defaultMaxWidth > 0 ? defaultMaxWidth : int.MaxValue;
int maxHeight = defaultMaxHeight > 0 ? defaultMaxHeight : int.MaxValue; /// <summary>
/// Gets or sets DynamicParameter.
// If height or width is not passed we assume that the standard ratio is to be kept. /// </summary>
if (height == 0) public abstract dynamic DynamicParameter { get; set; }
{
// Bit of simple fractional maths here. /// <summary>
float percentWidth = Math.Abs(width/(float) sourceWidth); /// Gets or sets the order in which this processor is to be used in a chain.
height = (int) Math.Floor(sourceHeight*percentWidth); /// </summary>
} public abstract int SortOrder { get; protected set; }
if (width == 0) /// <summary>
{ /// Gets or sets any additional settings required by the processor.
float percentHeight = Math.Abs(height/(float) sourceHeight); /// </summary>
width = (int) Math.Floor(sourceWidth*percentHeight); public abstract Dictionary<string, string> Settings { get; set; }
}
/// <summary>
if (width > 0 && height > 0 && width <= maxWidth && height <= maxHeight) /// The position in the original string where the first character of the captured substring was found.
{ /// </summary>
// Dont use an object initializer here. /// <param name="queryString">
newImage = new Bitmap(width, height, PixelFormat.Format32bppPArgb); /// The query string to search.
newImage.Tag = image.Tag; /// </param>
/// <returns>
using (Graphics graphics = Graphics.FromImage(newImage)) /// The zero-based starting position in the original string where the captured substring was found.
{ /// </returns>
// We want to use two different blending algorithms for enlargement/shrinking. public abstract int MatchRegexIndex(string queryString);
// Bicubic is better enlarging for whilst Bilinear is better for shrinking.
// http://www.codinghorror.com/blog/2007/07/better-image-resizing.html /// <summary>
if (image.Width < width && image.Height < height) /// Processes the image.
{ /// </summary>
// We are making it larger. /// <param name="factory">
graphics.SmoothingMode = SmoothingMode.AntiAlias; /// The the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; /// the image to process.
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; /// </param>
graphics.CompositingQuality = CompositingQuality.HighQuality; /// <returns>
} /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
else /// </returns>
{ public abstract Image ProcessImage(ImageFactory factory);
// We are making it smaller.
graphics.SmoothingMode = SmoothingMode.None; /// <summary>
/// The resize image.
// Contrary to everything I have read bicubic is producing the best results. /// </summary>
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; /// <param name="factory">
graphics.PixelOffsetMode = PixelOffsetMode.None; /// The the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
graphics.CompositingQuality = CompositingQuality.HighSpeed; /// the image to process.
} /// </param>
/// <param name="width">
// An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image /// The width to resize the image to.
// as the algorithm appears to be pulling averaging detail from surFlooring pixels beyond the edge /// </param>
// of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror /// <param name="height">
// images of the pixels within solves this problem. /// The height to resize the image to.
using (ImageAttributes wrapMode = new ImageAttributes()) /// </param>
{ /// <param name="defaultMaxWidth">
wrapMode.SetWrapMode(WrapMode.TileFlipXY); /// The default max width to resize the image to.
Rectangle destRect = new Rectangle(0, 0, width, height); /// </param>
graphics.DrawImage(image, destRect, 0, 0, sourceWidth, sourceHeight, GraphicsUnit.Pixel, wrapMode); /// <param name="defaultMaxHeight">
} /// The default max height to resize the image to.
/// </param>
// Reassign the image. /// <returns>
image.Dispose(); /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
image = newImage; /// </returns>
} protected Image ResizeImage(ImageFactory factory, int width, int height, int defaultMaxWidth, int defaultMaxHeight)
} {
} Bitmap newImage = null;
catch Image image = factory.Image;
{
if (newImage != null) try
{ {
newImage.Dispose(); int sourceWidth = image.Width;
} int sourceHeight = image.Height;
}
int maxWidth = defaultMaxWidth > 0 ? defaultMaxWidth : int.MaxValue;
return image; int maxHeight = defaultMaxHeight > 0 ? defaultMaxHeight : int.MaxValue;
}
} // If height or width is not passed we assume that the standard ratio is to be kept.
if (height == 0)
{
// Bit of simple fractional maths here.
float percentWidth = Math.Abs(width / (float)sourceWidth);
height = (int)Math.Floor(sourceHeight * percentWidth);
}
if (width == 0)
{
float percentHeight = Math.Abs(height / (float)sourceHeight);
width = (int)Math.Floor(sourceWidth * percentHeight);
}
if (width > 0 && height > 0 && width <= maxWidth && height <= maxHeight)
{
// Dont use an object initializer here.
newImage = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
newImage.Tag = image.Tag;
using (Graphics graphics = Graphics.FromImage(newImage))
{
// We want to use two different blending algorithms for enlargement/shrinking.
// Bicubic is better enlarging for whilst Bilinear is better for shrinking.
// http://www.codinghorror.com/blog/2007/07/better-image-resizing.html
if (image.Width < width && image.Height < height)
{
// We are making it larger.
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
}
else
{
// We are making it smaller.
graphics.SmoothingMode = SmoothingMode.None;
// Contrary to everything I have read bicubic is producing the best results.
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.None;
graphics.CompositingQuality = CompositingQuality.HighSpeed;
}
// An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image
// as the algorithm appears to be pulling averaging detail from surFlooring pixels beyond the edge
// of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror
// images of the pixels within solves this problem.
using (ImageAttributes wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
Rectangle destRect = new Rectangle(0, 0, width, height);
graphics.DrawImage(image, destRect, 0, 0, sourceWidth, sourceHeight, GraphicsUnit.Pixel, wrapMode);
}
// Reassign the image.
image.Dispose();
image = newImage;
}
}
}
catch
{
if (newImage != null)
{
newImage.Dispose();
}
}
return image;
}
#endregion
}
} }

4
src/ImageProcessor/Properties/AssemblyInfo.cs

@ -32,6 +32,6 @@ using System.Security;
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("1.7.0.3")] [assembly: AssemblyVersion("1.7.1.1")]
[assembly: AssemblyFileVersion("1.7.0.3")] [assembly: AssemblyFileVersion("1.7.1.1")]

BIN
src/Nuget/ImageProcessor.1.7.0.0.nupkg

Binary file not shown.

BIN
src/Nuget/ImageProcessor.1.7.0.1.nupkg

Binary file not shown.

BIN
src/Nuget/ImageProcessor.1.7.0.2.nupkg

Binary file not shown.

BIN
src/Nuget/ImageProcessor.1.7.0.3.nupkg

Binary file not shown.

BIN
src/Nuget/ImageProcessor.1.7.1.1.nupkg

Binary file not shown.

1
src/Nuget/ImageProcessor.Web.2.3.0.3.nupkg.REMOVED.git-id

@ -1 +0,0 @@
0a367af8c6588fe2be54ef5950820a7f06f7b0f1

1
src/Nuget/ImageProcessor.Web.2.3.0.4.nupkg.REMOVED.git-id

@ -1 +0,0 @@
129834a775acc5e2bfe85dc7db9edd37b9219e43

1
src/Nuget/ImageProcessor.Web.2.3.0.5.nupkg.REMOVED.git-id

@ -1 +0,0 @@
9d6097d930bbf60f2d333f80e7c916759a3c3f0c

1
src/Nuget/ImageProcessor.Web.2.3.0.6.nupkg.REMOVED.git-id

@ -0,0 +1 @@
7f1cb06ddbb5a91892188c8a18109d8db0f76115

6
src/TestWebsites/NET4/Web.config

@ -83,6 +83,12 @@
<setting key="MaxHeight" value="768" /> <setting key="MaxHeight" value="768" />
</settings> </settings>
</plugin> </plugin>
<plugin name="Constrain">
<settings>
<setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/>
</settings>
</plugin>
</plugins> </plugins>
</processing> </processing>
</imageProcessor> </imageProcessor>

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

@ -5,80 +5,86 @@
--> -->
<configuration> <configuration>
<configSections> <configSections>
<sectionGroup name="imageProcessor"> <sectionGroup name="imageProcessor">
<section name="security" requirePermission="false" type="ImageProcessor.Web.Config.ImageSecuritySection, ImageProcessor.Web"/> <section name="security" requirePermission="false" type="ImageProcessor.Web.Config.ImageSecuritySection, ImageProcessor.Web"/>
<section name="processing" requirePermission="false" type="ImageProcessor.Web.Config.ImageProcessingSection, ImageProcessor.Web"/> <section name="processing" requirePermission="false" type="ImageProcessor.Web.Config.ImageProcessingSection, ImageProcessor.Web"/>
<section name="cache" requirePermission="false" type="ImageProcessor.Web.Config.ImageCacheSection, ImageProcessor.Web"/> <section name="cache" requirePermission="false" type="ImageProcessor.Web.Config.ImageCacheSection, ImageProcessor.Web"/>
</sectionGroup> </sectionGroup>
</configSections> </configSections>
<appSettings> <appSettings>
<add key="webpages:Version" value="2.0.0.0" /> <add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" /> <add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" /> <add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" /> <add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings> </appSettings>
<system.web> <system.web>
<httpRuntime targetFramework="4.5" /> <httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" /> <compilation debug="true" targetFramework="4.5" />
<pages> <pages>
<namespaces> <namespaces>
<add namespace="System.Web.Helpers" /> <add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" /> <add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" /> <add namespace="System.Web.WebPages" />
</namespaces> </namespaces>
</pages> </pages>
<httpModules> <httpModules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/> <add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
</httpModules> </httpModules>
</system.web> </system.web>
<system.webServer> <system.webServer>
<validation validateIntegratedModeConfiguration="false" /> <validation validateIntegratedModeConfiguration="false" />
<handlers> <handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" /> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" /> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers> </handlers>
<modules> <modules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/> <add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
</modules> </modules>
</system.webServer> </system.webServer>
<imageProcessor> <imageProcessor>
<security allowRemoteDownloads="true" timeout="300000" maxBytes="524288" remotePrefix="/remote.axd"> <security allowRemoteDownloads="true" timeout="300000" maxBytes="524288" remotePrefix="/remote.axd">
<whiteList> <whiteList>
<add url="http://images.mymovies.net"/> <add url="http://images.mymovies.net"/>
<add url="http://www.theworldeffect.com" /> <add url="http://www.theworldeffect.com" />
</whiteList> </whiteList>
</security> </security>
<cache virtualPath="~/app_data/cache" maxDays="56"/> <cache virtualPath="~/app_data/cache" maxDays="56"/>
<processing> <processing>
<plugins> <plugins>
<plugin name="Resize"> <plugin name="Resize">
<settings> <settings>
<setting key="MaxWidth" value="3000"/> <setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/> <setting key="MaxHeight" value="3000"/>
</settings> </settings>
</plugin> </plugin>
</plugins> <plugin name="Constrain">
</processing> <settings>
</imageProcessor> <setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/>
</settings>
</plugin>
</plugins>
</processing>
</imageProcessor>
</configuration> </configuration>

Loading…
Cancel
Save