Browse Source

Updating tests and adding rounded corners.

TODO: Finish rounded corners

Former-commit-id: 369c11006c59b8c30dd52c132d8beacbde62f475
pull/17/head
James South 12 years ago
parent
commit
d130d7e2b1
  1. 46
      src/ImageProcessor.Tests/RegularExpressionUnitTests.cs
  2. 173
      src/ImageProcessor.Web/NET45/Processors/RoundedCorners.cs
  3. 180
      src/ImageProcessor/Processors/RoundedCorners.cs

46
src/ImageProcessor.Tests/RegularExpressionUnitTests.cs

@ -8,6 +8,8 @@ namespace ImageProcessor.Tests
{ {
#region Using #region Using
using System.Drawing; using System.Drawing;
using ImageProcessor.Configuration;
using ImageProcessor.Imaging; using ImageProcessor.Imaging;
using ImageProcessor.Processors; using ImageProcessor.Processors;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -31,10 +33,10 @@ namespace ImageProcessor.Tests
const string Querystring = "alpha=56"; const string Querystring = "alpha=56";
const int Expected = 56; const int Expected = 56;
Alpha alpha = new Alpha(); Web.Processors.Alpha alpha = new Web.Processors.Alpha();
alpha.MatchRegexIndex(Querystring); alpha.MatchRegexIndex(Querystring);
int actual = alpha.DynamicParameter; int actual = alpha.Processor.DynamicParameter;
Assert.AreEqual(Expected, actual); Assert.AreEqual(Expected, actual);
} }
@ -48,10 +50,10 @@ namespace ImageProcessor.Tests
const string Querystring = "brightness=56"; const string Querystring = "brightness=56";
const int Expected = 56; const int Expected = 56;
Brightness brightness = new Brightness(); Web.Processors.Brightness brightness = new Web.Processors.Brightness();
brightness.MatchRegexIndex(Querystring); brightness.MatchRegexIndex(Querystring);
int actual = brightness.DynamicParameter; int actual = brightness.Processor.DynamicParameter;
Assert.AreEqual(Expected, actual); Assert.AreEqual(Expected, actual);
} }
@ -65,10 +67,10 @@ namespace ImageProcessor.Tests
const string Querystring = "contrast=56"; const string Querystring = "contrast=56";
const int Expected = 56; const int Expected = 56;
Contrast contrast = new Contrast(); Web.Processors.Contrast contrast = new Web.Processors.Contrast();
contrast.MatchRegexIndex(Querystring); contrast.MatchRegexIndex(Querystring);
int actual = contrast.DynamicParameter; int actual = contrast.Processor.DynamicParameter;
Assert.AreEqual(Expected, actual); Assert.AreEqual(Expected, actual);
} }
@ -82,10 +84,10 @@ namespace ImageProcessor.Tests
const string Querystring = "crop=0,0,150,300"; const string Querystring = "crop=0,0,150,300";
CropLayer expected = new CropLayer(0, 0, 150, 300, CropMode.Pixels); CropLayer expected = new CropLayer(0, 0, 150, 300, CropMode.Pixels);
Crop crop = new Crop(); Web.Processors.Crop crop = new Web.Processors.Crop();
crop.MatchRegexIndex(Querystring); crop.MatchRegexIndex(Querystring);
CropLayer actual = crop.DynamicParameter; CropLayer actual = crop.Processor.DynamicParameter;
Assert.AreEqual(expected, actual); Assert.AreEqual(expected, actual);
} }
@ -99,10 +101,10 @@ namespace ImageProcessor.Tests
const string Querystring = "filter=lomograph"; const string Querystring = "filter=lomograph";
const string Expected = "lomograph"; const string Expected = "lomograph";
Filter filter = new Filter(); Web.Processors.Filter filter = new Web.Processors.Filter();
filter.MatchRegexIndex(Querystring); filter.MatchRegexIndex(Querystring);
string actual = filter.DynamicParameter; string actual = filter.Processor.DynamicParameter;
Assert.AreEqual(Expected, actual); Assert.AreEqual(Expected, actual);
} }
@ -116,10 +118,10 @@ namespace ImageProcessor.Tests
const string Querystring = "format=gif"; const string Querystring = "format=gif";
const string Expected = "gif"; const string Expected = "gif";
Format format = new Format(); Web.Processors.Format format = new Web.Processors.Format();
format.MatchRegexIndex(Querystring); format.MatchRegexIndex(Querystring);
string actual = format.DynamicParameter; string actual = format.Processor.DynamicParameter;
Assert.AreEqual(Expected, actual); Assert.AreEqual(Expected, actual);
} }
@ -133,10 +135,10 @@ namespace ImageProcessor.Tests
const string Querystring = "quality=56"; const string Querystring = "quality=56";
const int Expected = 56; const int Expected = 56;
Quality quality = new Quality(); Web.Processors.Quality quality = new Web.Processors.Quality();
quality.MatchRegexIndex(Querystring); quality.MatchRegexIndex(Querystring);
int actual = quality.DynamicParameter; int actual = quality.Processor.DynamicParameter;
Assert.AreEqual(Expected, actual); Assert.AreEqual(Expected, actual);
} }
@ -150,10 +152,10 @@ namespace ImageProcessor.Tests
const string Querystring = "width=300"; const string Querystring = "width=300";
ResizeLayer expected = new ResizeLayer(new Size(300, 0)); ResizeLayer expected = new ResizeLayer(new Size(300, 0));
Resize resize = new Resize(); Web.Processors.Resize resize = new Web.Processors.Resize();
resize.MatchRegexIndex(Querystring); resize.MatchRegexIndex(Querystring);
ResizeLayer actual = resize.DynamicParameter; ResizeLayer actual = resize.Processor.DynamicParameter;
Assert.AreEqual(expected, actual); Assert.AreEqual(expected, actual);
} }
@ -167,10 +169,10 @@ namespace ImageProcessor.Tests
const string Querystring = "rotate=270"; const string Querystring = "rotate=270";
RotateLayer expected = new RotateLayer(270, Color.Transparent); RotateLayer expected = new RotateLayer(270, Color.Transparent);
Rotate rotate = new Rotate(); Web.Processors.Rotate rotate = new Web.Processors.Rotate();
rotate.MatchRegexIndex(Querystring); rotate.MatchRegexIndex(Querystring);
RotateLayer actual = rotate.DynamicParameter; RotateLayer actual = rotate.Processor.DynamicParameter;
Assert.AreEqual(expected, actual); Assert.AreEqual(expected, actual);
} }
@ -203,14 +205,14 @@ namespace ImageProcessor.Tests
Color expectedHex = ColorTranslator.FromHtml("#" + "6aa6cc"); Color expectedHex = ColorTranslator.FromHtml("#" + "6aa6cc");
Color expectedRgba = Color.FromArgb(255, 106, 166, 204); Color expectedRgba = Color.FromArgb(255, 106, 166, 204);
Tint tint = new Tint(); Web.Processors.Tint tint = new Web.Processors.Tint();
tint.MatchRegexIndex(HexQuerystring); tint.MatchRegexIndex(HexQuerystring);
Color actualHex = tint.DynamicParameter; Color actualHex = tint.Processor.DynamicParameter;
Assert.AreEqual(expectedHex, actualHex); Assert.AreEqual(expectedHex, actualHex);
tint = new Tint(); tint = new Web.Processors.Tint();
tint.MatchRegexIndex(RgbaQuerystring); tint.MatchRegexIndex(RgbaQuerystring);
Color actualRgba = tint.DynamicParameter; Color actualRgba = tint.Processor.DynamicParameter;
Assert.AreEqual(expectedRgba, actualRgba); Assert.AreEqual(expectedRgba, actualRgba);
} }
#endregion #endregion

173
src/ImageProcessor.Web/NET45/Processors/RoundedCorners.cs

@ -1,8 +1,10 @@
 
namespace ImageProcessor.Web.Processors namespace ImageProcessor.Web.Processors
{ {
using System; using System.Drawing;
using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ImageProcessor.Imaging;
using ImageProcessor.Processors; using ImageProcessor.Processors;
/// <summary> /// <summary>
@ -10,15 +12,180 @@ namespace ImageProcessor.Web.Processors
/// </summary> /// </summary>
public class RoundedCorners : IWebGraphicsProcessor public class RoundedCorners : IWebGraphicsProcessor
{ {
public Regex RegexPattern { get; private set; } /// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"roundedcorners=(\d+|[^&]*)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the angle attribute.
/// </summary>
private static readonly Regex RadiusRegex = new Regex(@"radius-(\d+)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the color attribute.
/// </summary>
private static readonly Regex ColorRegex = new Regex(@"bgcolor-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the top left attribute.
/// </summary>
private static readonly Regex TopLeftRegex = new Regex(@"tl-(true|false)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the top right attribute.
/// </summary>
private static readonly Regex TopRightRegex = new Regex(@"tr-(true|false)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the bottom left attribute.
/// </summary>
private static readonly Regex BottomLeftRegex = new Regex(@"bl-(true|false)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the bottom right attribute.
/// </summary>
private static readonly Regex BottomRightRegex = new Regex(@"br-(true|false)", RegexOptions.Compiled);
/// <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; } public int SortOrder { get; private set; }
/// <summary>
/// Gets the associated graphics processor.
/// </summary>
public IGraphicsProcessor Processor { get; private set; } 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) public int MatchRegexIndex(string queryString)
{ {
throw new NotImplementedException(); 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;
RoundedCornerLayer roundedCornerLayer;
string toParse = match.Value;
if (toParse.Contains("bgcolor"))
{
roundedCornerLayer = new RoundedCornerLayer(this.ParseRadius(toParse), this.ParseColor(toParse), this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse));
}
else
{
int radius;
int.TryParse(match.Value.Split('=')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius);
roundedCornerLayer = new RoundedCornerLayer(radius, this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse));
}
this.Processor.DynamicParameter = roundedCornerLayer;
}
index += 1;
}
}
return this.SortOrder;
}
#region Private Methods
/// <summary>
/// Returns the correct <see cref="T:System.Int32"/> containing the radius for the given string.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Int32"/> containing the radius for the given string.
/// </returns>
private int ParseRadius(string input)
{
foreach (Match match in RadiusRegex.Matches(input))
{
// Split on radius-
int radius;
int.TryParse(match.Value.Split('-')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius);
return radius;
}
// No rotate - matches the RotateLayer default.
return 0;
}
/// <summary>
/// Returns the correct <see cref="T:System.Drawing.Color"/> for the given string.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Drawing.Color"/>
/// </returns>
private Color ParseColor(string input)
{
foreach (Match match in ColorRegex.Matches(input))
{
// split on color-hex
return ColorTranslator.FromHtml("#" + match.Value.Split('-')[1]);
}
return Color.Transparent;
}
/// <summary>
/// Returns a <see cref="T:System.Boolean"/> either true or false.
/// </summary>
/// <param name="corner">
/// The corner.
/// </param>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Boolean"/> true or false.
/// </returns>
private bool ParseCorner(Regex corner, string input)
{
foreach (Match match in corner.Matches(input))
{
// Split on corner-
bool cornerRound;
bool.TryParse(match.Value.Split('-')[1], out cornerRound);
return cornerRound;
}
// No rotate - matches the RotateLayer default.
return true;
} }
#endregion
} }
} }

180
src/ImageProcessor/Processors/RoundedCorners.cs

@ -24,53 +24,6 @@ namespace ImageProcessor.Processors
/// </summary> /// </summary>
public class RoundedCorners : IGraphicsProcessor public class RoundedCorners : IGraphicsProcessor
{ {
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"roundedcorners=(\d+|[^&]*)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the angle attribute.
/// </summary>
private static readonly Regex RadiusRegex = new Regex(@"radius-(\d+)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the color attribute.
/// </summary>
private static readonly Regex ColorRegex = new Regex(@"bgcolor-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the top left attribute.
/// </summary>
private static readonly Regex TopLeftRegex = new Regex(@"tl-(true|false)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the top right attribute.
/// </summary>
private static readonly Regex TopRightRegex = new Regex(@"tr-(true|false)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the bottom left attribute.
/// </summary>
private static readonly Regex BottomLeftRegex = new Regex(@"bl-(true|false)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the bottom right attribute.
/// </summary>
private static readonly Regex BottomRightRegex = new Regex(@"br-(true|false)", RegexOptions.Compiled);
#region IGraphicsProcessor Members
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
public Regex RegexPattern
{
get
{
return QueryRegex;
}
}
/// <summary> /// <summary>
/// Gets or sets DynamicParameter. /// Gets or sets DynamicParameter.
/// </summary> /// </summary>
@ -80,15 +33,6 @@ namespace ImageProcessor.Processors
set; set;
} }
/// <summary>
/// Gets the order in which this processor is to be used in a chain.
/// </summary>
public int SortOrder
{
get;
private set;
}
/// <summary> /// <summary>
/// Gets or sets any additional settings required by the processor. /// Gets or sets any additional settings required by the processor.
/// </summary> /// </summary>
@ -98,57 +42,6 @@ namespace ImageProcessor.Processors
set; 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;
RoundedCornerLayer roundedCornerLayer;
string toParse = match.Value;
if (toParse.Contains("bgcolor"))
{
roundedCornerLayer = new RoundedCornerLayer(this.ParseRadius(toParse), this.ParseColor(toParse), this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse));
}
else
{
int radius;
int.TryParse(match.Value.Split('=')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius);
roundedCornerLayer = new RoundedCornerLayer(radius, this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse));
}
this.DynamicParameter = roundedCornerLayer;
}
index += 1;
}
}
return this.SortOrder;
}
/// <summary> /// <summary>
/// Processes the image. /// Processes the image.
/// </summary> /// </summary>
@ -174,7 +67,7 @@ namespace ImageProcessor.Processors
bool bottomLeft = roundedCornerLayer.BottomLeft; bool bottomLeft = roundedCornerLayer.BottomLeft;
bool bottomRight = roundedCornerLayer.BottomRight; bool bottomRight = roundedCornerLayer.BottomRight;
// Create a rotated image. // Create a rounded image.
newImage = this.RoundCornerImage(image, radius, backgroundColor, topLeft, topRight, bottomLeft, bottomRight); newImage = this.RoundCornerImage(image, radius, backgroundColor, topLeft, topRight, bottomLeft, bottomRight);
image.Dispose(); image.Dispose();
@ -190,9 +83,7 @@ namespace ImageProcessor.Processors
return image; return image;
} }
#endregion
#region Private Methods
/// <summary> /// <summary>
/// Adds rounded corners to the image /// Adds rounded corners to the image
/// </summary> /// </summary>
@ -281,74 +172,5 @@ namespace ImageProcessor.Processors
return newImage; return newImage;
} }
/// <summary>
/// Returns the correct <see cref="T:System.Int32"/> containing the radius for the given string.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Int32"/> containing the radius for the given string.
/// </returns>
private int ParseRadius(string input)
{
foreach (Match match in RadiusRegex.Matches(input))
{
// Split on radius-
int radius;
int.TryParse(match.Value.Split('-')[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius);
return radius;
}
// No rotate - matches the RotateLayer default.
return 0;
}
/// <summary>
/// Returns the correct <see cref="T:System.Drawing.Color"/> for the given string.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Drawing.Color"/>
/// </returns>
private Color ParseColor(string input)
{
foreach (Match match in ColorRegex.Matches(input))
{
// split on color-hex
return ColorTranslator.FromHtml("#" + match.Value.Split('-')[1]);
}
return Color.Transparent;
}
/// <summary>
/// Returns a <see cref="T:System.Boolean"/> either true or false.
/// </summary>
/// <param name="corner">
/// The corner.
/// </param>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Boolean"/> true or false.
/// </returns>
private bool ParseCorner(Regex corner, string input)
{
foreach (Match match in corner.Matches(input))
{
// Split on corner-
bool cornerRound;
bool.TryParse(match.Value.Split('-')[1], out cornerRound);
return cornerRound;
}
// No rotate - matches the RotateLayer default.
return true;
}
#endregion
} }
} }

Loading…
Cancel
Save