diff --git a/build/NuSpecs/ImageProcessor.Plugins.Cair.nuspec b/build/NuSpecs/ImageProcessor.Plugins.Cair.nuspec
index 941a3d985c..fbd51688d8 100644
--- a/build/NuSpecs/ImageProcessor.Plugins.Cair.nuspec
+++ b/build/NuSpecs/ImageProcessor.Plugins.Cair.nuspec
@@ -21,7 +21,7 @@ Feedback is always welcome
Image Resize Crop Rotate Quality Watermark Gif Jpg Jpeg Bitmap Png Tiff Cair Seam Carving
-
+
diff --git a/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec b/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec
index 35dfadfec7..daf9d61864 100644
--- a/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec
+++ b/build/NuSpecs/ImageProcessor.Plugins.WebP.nuspec
@@ -21,7 +21,7 @@ Feedback is always welcome
Image Resize Crop Rotate Quality Watermark Gif Jpg Jpeg Bitmap Png Tiff WebP
-
+
diff --git a/build/NuSpecs/ImageProcessor.Web.Config.nuspec b/build/NuSpecs/ImageProcessor.Web.Config.nuspec
index 3084916e40..3d283d6119 100644
--- a/build/NuSpecs/ImageProcessor.Web.Config.nuspec
+++ b/build/NuSpecs/ImageProcessor.Web.Config.nuspec
@@ -21,8 +21,8 @@ Feedback is always welcome
Image Resize Crop Rotate Quality Watermark Gif Jpg Jpeg Bitmap Png Tiff ASP Cache EXIF
-
-
+
+
diff --git a/build/NuSpecs/ImageProcessor.Web.Plugins.AzureBlobCache.nuspec b/build/NuSpecs/ImageProcessor.Web.Plugins.AzureBlobCache.nuspec
index 06a1b4efed..9f548dea3a 100644
--- a/build/NuSpecs/ImageProcessor.Web.Plugins.AzureBlobCache.nuspec
+++ b/build/NuSpecs/ImageProcessor.Web.Plugins.AzureBlobCache.nuspec
@@ -21,9 +21,9 @@ Feedback is always welcome
Image Resize Crop Rotate Quality Watermark Gif Jpg Jpeg Bitmap Png Tiff Azure Cache Asp
-
-
-
+
+
+
diff --git a/build/NuSpecs/ImageProcessor.Web.PostProcessor.nuspec b/build/NuSpecs/ImageProcessor.Web.PostProcessor.nuspec
index 02246eafbd..bb5f649a56 100644
--- a/build/NuSpecs/ImageProcessor.Web.PostProcessor.nuspec
+++ b/build/NuSpecs/ImageProcessor.Web.PostProcessor.nuspec
@@ -21,8 +21,8 @@ Feedback is always welcome
Image Resize Crop Rotate Quality Watermark Gif Jpg Jpeg Bitmap Png Tiff ASP Cache EXIF
-
-
+
+
diff --git a/build/NuSpecs/ImageProcessor.Web.nuspec b/build/NuSpecs/ImageProcessor.Web.nuspec
index 0fe93698f2..5c6c433859 100644
--- a/build/NuSpecs/ImageProcessor.Web.nuspec
+++ b/build/NuSpecs/ImageProcessor.Web.nuspec
@@ -2,7 +2,7 @@
ImageProcessor.Web
- 4.2.1.0
+ 4.3.0.0
ImageProcessor.Web
James South
James South
@@ -23,7 +23,7 @@ Feedback is always welcome
Image Resize Crop Rotate Quality Watermark Gif Jpg Jpeg Bitmap Png Tiff ASP Cache EXIF
-
+
diff --git a/build/build.xml b/build/build.xml
index 84b9865cb0..dd40840b8e 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -13,7 +13,7 @@
ImageProcessor Web
- 4.2.1.0
+ 4.3.0.0
..\src\ImageProcessor.Web
ImageProcessor.Web.csproj
@@ -22,9 +22,15 @@
ImageProcessor.Web.nuspec
+
+ ImageProcessor Web.config sample
+ 2.2.1.0
+ ImageProcessor.Web.Config.nuspec
+
+
ImageProcessor Web PostProcessor
- 1.0.2.0
+ 1.0.3.0
..\src\ImageProcessor.Web.PostProcessor
ImageProcessor.Web.PostProcessor.csproj
@@ -33,15 +39,9 @@
ImageProcessor.Web.PostProcessor.nuspec
-
- ImageProcessor Web.config sample
- 2.2.0.0
- ImageProcessor.Web.Config.nuspec
-
-
ImageProcessor Web Azure Blob Cache plugin
- 1.0.0.0
+ 1.0.1.0
..\src\Plugins\ImageProcessor.Web\ImageProcessor.Web.Plugins.AzureBlobCache
ImageProcessor.Web.Plugins.AzureBlobCache.csproj
@@ -52,7 +52,7 @@
ImageProcessor Cair plugin
- 1.0.0.0
+ 1.0.1.0
..\src\Plugins\ImageProcessor\ImageProcessor.Plugins.Cair
ImageProcessor.Plugins.Cair.csproj
@@ -63,7 +63,7 @@
ImageProcessor WebP plugin
- 1.0.1.0
+ 1.0.2.0
..\src\Plugins\ImageProcessor\ImageProcessor.Plugins.WebP
ImageProcessor.Plugins.WebP.csproj
diff --git a/src/ImageProcessor.Web.UnitTests/QueryParamParserUnitTests.cs b/src/ImageProcessor.Web.UnitTests/QueryParamParserUnitTests.cs
index c0514770a8..2ab57c1f98 100644
--- a/src/ImageProcessor.Web.UnitTests/QueryParamParserUnitTests.cs
+++ b/src/ImageProcessor.Web.UnitTests/QueryParamParserUnitTests.cs
@@ -1,5 +1,16 @@
-namespace ImageProcessor.Web.UnitTests
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// The query parameter parser unit tests.
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Web.UnitTests
{
+ using System;
using System.Collections.Specialized;
using System.Drawing;
using System.Web;
@@ -10,7 +21,7 @@
using NUnit.Framework;
///
- /// The query param parser unit tests.
+ /// The query parameter parser unit tests.
///
[TestFixture]
public class QueryParamParserUnitTests
@@ -44,6 +55,18 @@
Assert.IsNotNull(result);
}
+ [TestCase("", "entropycrop", 0)]
+ [TestCase("entropycrop=0", "entropycrop", 0)]
+ [TestCase("entropycrop=128", "entropycrop", 128)]
+ [TestCase("entropycrop=128.4", "entropycrop", 128)]
+ [TestCase("entropycrop=128.5", "entropycrop", 129)]
+ public void IntRounded(string queryString, string parameter, int expected)
+ {
+ NameValueCollection query = HttpUtility.ParseQueryString(queryString);
+ int result = (int)Math.Round(QueryParamParser.Instance.ParseValue(query[parameter]), MidpointRounding.AwayFromZero);
+ Assert.AreEqual(result, expected);
+ }
+
[TestCase("", "entropycrop")]
[TestCase("entropycrop=0", "entropycrop")]
[TestCase("entropycrop=128", "entropycrop")]
diff --git a/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs b/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
index ec1fe19ec8..eb5962dbb5 100644
--- a/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
+++ b/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
@@ -106,14 +106,24 @@ namespace ImageProcessor.Web.UnitTests
[Test]
public void TestCropRegex()
{
- const string Querystring = "crop=0,0,150,300";
- CropLayer expected = new CropLayer(0, 0, 150, 300, CropMode.Pixels);
+ Dictionary data = new Dictionary
+ {
+ {
+ "crop=0,0,150,300", new CropLayer(0, 0, 150, 300, CropMode.Pixels)
+ },
+ {
+ "crop=0.1,0.1,.2,.2&cropmode=percentage", new CropLayer(0.1f, 0.1f, 0.2f, 0.2f, CropMode.Percentage)
+ }
+ };
Processors.Crop crop = new Processors.Crop();
- crop.MatchRegexIndex(Querystring);
- CropLayer actual = crop.Processor.DynamicParameter;
- Assert.AreEqual(expected, actual);
+ foreach (KeyValuePair item in data)
+ {
+ crop.MatchRegexIndex(item.Key);
+ CropLayer result = crop.Processor.DynamicParameter;
+ Assert.AreEqual(item.Value, result);
+ }
}
///
@@ -252,12 +262,18 @@ namespace ImageProcessor.Web.UnitTests
{
"height=300", new ResizeLayer(new Size(0, 300))
},
+ {
+ "height=300.6", new ResizeLayer(new Size(0, 301))
+ },
{
"height=300&mode=crop", new ResizeLayer(new Size(0, 300), ResizeMode.Crop)
},
{
"width=300&mode=crop", new ResizeLayer(new Size(300, 0), ResizeMode.Crop)
},
+ {
+ "width=300.2&mode=crop", new ResizeLayer(new Size(300, 0), ResizeMode.Crop)
+ },
{
"width=600&heightratio=0.416", new ResizeLayer(new Size(600, 250))
},
@@ -289,6 +305,7 @@ namespace ImageProcessor.Web.UnitTests
[TestCase("rotate=270", 270F)]
[TestCase("rotate=-270", -270F)]
[TestCase("rotate=28", 28F)]
+ [TestCase("rotate=28.7", 28.7F)]
public void TestRotateRegex(string input, float expected)
{
Processors.Rotate rotate = new Processors.Rotate();
@@ -439,6 +456,22 @@ namespace ImageProcessor.Web.UnitTests
DropShadow = true,
FontFamily = new FontFamily("arial")
}
+ },
+ {
+ "watermark=لا أحد يحب الألم بذاته، يسعى ورائه أو يبتغيه، ببساطة لأنه الألم&color=fff&fontsize=36&fontstyle=italic&fontopacity=80&textposition=30,150&dropshadow=true&fontfamily=arial&vertical=true&rtl=true",
+ new TextLayer
+ {
+ Text = "لا أحد يحب الألم بذاته، يسعى ورائه أو يبتغيه، ببساطة لأنه الألم",
+ FontColor = ColorTranslator.FromHtml("#" + "ffffff"),
+ FontSize = 36,
+ Style = FontStyle.Italic,
+ Opacity = 80,
+ Position = new Point(30, 150),
+ DropShadow = true,
+ FontFamily = new FontFamily("arial"),
+ Vertical = true,
+ RightToLeft = true
+ }
}
};
diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
index 231cd7b236..15ebffb124 100644
--- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
+++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
@@ -522,7 +522,7 @@ namespace ImageProcessor.Web.HttpModules
{
string origin = context.Request.Headers["Origin"];
- if (this.IsValidOriginRequest(origin))
+ if (this.IsValidCorsRequest(origin))
{
response.AddHeader("Access-Control-Allow-Origin", origin);
}
@@ -626,7 +626,7 @@ namespace ImageProcessor.Web.HttpModules
///
/// True if the request is valid; otherwise, False.
///
- private bool IsValidOriginRequest(string path)
+ private bool IsValidCorsRequest(string path)
{
ImageSecuritySection.CORSOriginElement origins =
ImageProcessorConfiguration.Instance.GetImageSecuritySection().CORSOrigin;
diff --git a/src/ImageProcessor.Web/Processors/Resize.cs b/src/ImageProcessor.Web/Processors/Resize.cs
index e04c64e079..65ac74cb8c 100644
--- a/src/ImageProcessor.Web/Processors/Resize.cs
+++ b/src/ImageProcessor.Web/Processors/Resize.cs
@@ -124,23 +124,27 @@ namespace ImageProcessor.Web.Processors
string heightRatio = queryCollection["heightratio"];
Size size = new Size();
+ // Umbraco calls the API incorrectly so we have to deal with floats.
+ // We round up so that single pixel lines are not produced.
+ const MidpointRounding Rounding = MidpointRounding.AwayFromZero;
+
// First cater for single dimensions.
if (width != null && height == null)
{
- size = new Size(QueryParamParser.Instance.ParseValue(width), 0);
+ size = new Size((int)Math.Round(QueryParamParser.Instance.ParseValue(width), Rounding), 0);
}
if (width == null && height != null)
{
- size = new Size(0, QueryParamParser.Instance.ParseValue(height));
+ size = new Size(0, (int)Math.Round(QueryParamParser.Instance.ParseValue(height), Rounding));
}
// Both supplied
if (width != null && height != null)
{
size = new Size(
- QueryParamParser.Instance.ParseValue(width),
- QueryParamParser.Instance.ParseValue(height));
+ (int)Math.Round(QueryParamParser.Instance.ParseValue(width), Rounding),
+ (int)Math.Round(QueryParamParser.Instance.ParseValue(height), Rounding));
}
// Calculate any ratio driven sizes.
@@ -149,13 +153,13 @@ namespace ImageProcessor.Web.Processors
// Replace 0 width
if (size.Width == 0 && size.Height > 0 && widthRatio != null && heightRatio == null)
{
- size.Width = Convert.ToInt32(QueryParamParser.Instance.ParseValue(widthRatio) * size.Height);
+ size.Width = (int)Math.Round(QueryParamParser.Instance.ParseValue(widthRatio) * size.Height, Rounding);
}
// Replace 0 height
if (size.Width > 0 && size.Height == 0 && widthRatio == null && heightRatio != null)
{
- size.Height = Convert.ToInt32(QueryParamParser.Instance.ParseValue(heightRatio) * size.Width);
+ size.Height = (int)Math.Round(QueryParamParser.Instance.ParseValue(heightRatio) * size.Width, Rounding);
}
}
diff --git a/src/ImageProcessor.Web/Processors/Watermark.cs b/src/ImageProcessor.Web/Processors/Watermark.cs
index d6dec4f4df..e589550730 100644
--- a/src/ImageProcessor.Web/Processors/Watermark.cs
+++ b/src/ImageProcessor.Web/Processors/Watermark.cs
@@ -85,7 +85,9 @@ namespace ImageProcessor.Web.Processors
FontSize = this.ParseFontSize(queryCollection),
FontFamily = this.ParseFontFamily(queryCollection),
Style = this.ParseFontStyle(queryCollection),
- DropShadow = this.ParseDropShadow(queryCollection)
+ DropShadow = this.ParseDropShadow(queryCollection),
+ Vertical = this.ParseVertical(queryCollection),
+ RightToLeft = this.ParseRightToLeft(queryCollection)
};
textLayer.Opacity = this.ParseOpacity(queryCollection, textLayer.FontColor);
@@ -198,7 +200,7 @@ namespace ImageProcessor.Web.Processors
/// The of query parameters.
///
///
- /// The true if the watermark is to have a shadow; otherwise false.
+ /// True if the watermark is to have a shadow; otherwise false.
///
private bool ParseDropShadow(NameValueCollection queryCollection)
{
@@ -229,6 +231,33 @@ namespace ImageProcessor.Web.Processors
: 100;
}
+ ///
+ /// Returns a value indicating whether the watermark is to be written right to left.
+ ///
+ ///
+ /// The of query parameters.
+ ///
+ ///
+ /// True if the watermark is to be written right to left; otherwise false.
+ ///
+ private bool ParseRightToLeft(NameValueCollection queryCollection)
+ {
+ return QueryParamParser.Instance.ParseValue(queryCollection["rtl"]);
+ }
+
+ ///
+ /// Returns a value indicating whether the watermark is to be written vertically.
+ ///
+ ///
+ /// The of query parameters.
+ ///
+ ///
+ /// True if the watermark is to be written vertically; otherwise false.
+ ///
+ private bool ParseVertical(NameValueCollection queryCollection)
+ {
+ return QueryParamParser.Instance.ParseValue(queryCollection["vertical"]);
+ }
#endregion
}
}