Browse Source

Transferring more processors.

Former-commit-id: 249d2715f40b60384076d3710d91070ed5342db6
Former-commit-id: f339fc46f58eca21106100cf918416a703e7ff7b
Former-commit-id: d3d169819d61c264bd9564263b87c88772b5fda6
af/merge-core
James South 11 years ago
parent
commit
4fd25f4eb4
  1. 42
      src/ImageProcessor.Web/Helpers/QuerystringParser/ExtendedColorTypeConverter.cs
  2. 141
      src/ImageProcessor.Web/Helpers/QuerystringParser/FontFamilyConverter.cs
  3. 9
      src/ImageProcessor.Web/Helpers/QuerystringParser/QueryParamParser.cs
  4. 45
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
  5. 1
      src/ImageProcessor.Web/ImageProcessor.Web.csproj
  6. 1
      src/ImageProcessor.Web/Processors/Alpha.cs
  7. 4
      src/ImageProcessor.Web/Processors/Brightness.cs
  8. 4
      src/ImageProcessor.Web/Processors/Contrast.cs
  9. 2
      src/ImageProcessor.Web/Processors/DetectEdges.cs
  10. 1
      src/ImageProcessor.Web/Processors/EntropyCrop.cs
  11. 239
      src/ImageProcessor.Web/Processors/Resize.cs
  12. 27
      src/ImageProcessor.Web/Processors/Rotate.cs
  13. 30
      src/ImageProcessor.Web/Processors/RotateBounded.cs
  14. 112
      src/ImageProcessor.Web/Processors/RoundedCorners.cs
  15. 32
      src/ImageProcessor.Web/Processors/Saturation.cs
  16. 26
      src/ImageProcessor.Web/Processors/Tint.cs
  17. 34
      src/ImageProcessor.Web/Processors/Vignette.cs
  18. 283
      src/ImageProcessor.Web/Processors/Watermark.cs
  19. 9
      src/TestWebsites/MVC/Views/Home/External.cshtml
  20. 9
      src/TestWebsites/MVC/Web.config

42
src/ImageProcessor.Web/Helpers/QuerystringParser/ExtendedColorTypeConverter.cs

@ -26,7 +26,12 @@ namespace ImageProcessor.Web.Helpers
/// <summary>
/// The web color regex.
/// </summary>
private static readonly Regex WebColorRegex = new Regex("([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled);
private static readonly Regex HexColorRegex = new Regex("([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled);
/// <summary>
/// The number color regex.
/// </summary>
private static readonly Regex NumberRegex = new Regex(@"\d+", RegexOptions.Compiled);
/// <summary>
/// The html system color table map.
@ -68,9 +73,42 @@ namespace ImageProcessor.Web.Helpers
return Color.LightGray;
}
// Handle a,r,g,b
char separator = culture.TextInfo.ListSeparator[0];
if (colorText.Contains(separator.ToString()))
{
string[] components = colorText.Split(separator);
bool convert = true;
foreach (string component in components)
{
if (!NumberRegex.IsMatch(component))
{
convert = false;
}
}
if (convert)
{
if (components.Length == 4)
{
return Color.FromArgb(
Convert.ToInt32(components[0]),
Convert.ToInt32(components[1]),
Convert.ToInt32(components[2]),
Convert.ToInt32(components[3]));
}
return Color.FromArgb(
Convert.ToInt32(components[0]),
Convert.ToInt32(components[1]),
Convert.ToInt32(components[2]));
}
}
// Hex based color values.
char hash = colorText[0];
if (hash == '#' || WebColorRegex.IsMatch(colorText))
if (hash == '#' || HexColorRegex.IsMatch(colorText))
{
if (hash != '#')
{

141
src/ImageProcessor.Web/Helpers/QuerystringParser/FontFamilyConverter.cs

@ -0,0 +1,141 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FontFamilyConverter.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// FontFamilyConverter - converter class for converting between the <see cref="FontFamily" />
// and <see cref="String" /> types.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Helpers
{
using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
/// <summary>
/// FontFamilyConverter - converter class for converting between the <see cref="FontFamily"/>
/// and <see cref="String"/> types.
/// </summary>
public class FontFamilyConverter : TypeConverter
{
/// <summary>
/// Returns whether this converter can convert an object of the given type to the type of
/// this converter, using the specified context.
/// </summary>
/// <returns>
/// true if this converter can perform the conversion; otherwise, false.
/// </returns>
/// <param name="context">
/// An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.
/// </param>
/// <param name="sourceType">
/// A <see cref="T:System.Type"/> that represents the type you want to convert from.
/// </param>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
/// <summary>
/// Returns whether this converter can convert the object to the specified type, using
/// the specified context.
/// </summary>
/// <returns>
/// true if this converter can perform the conversion; otherwise, false.
/// </returns>
/// <param name="context">
/// An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.
/// </param>
/// <param name="destinationType">
/// A <see cref="T:System.Type"/> that represents the type you want to convert to.
/// </param>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string) || destinationType == typeof(FontFamily))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
/// <summary>
/// Converts the given object to the type of this converter, using the specified context and
/// culture information.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the converted value.
/// </returns>
/// <param name="context">
/// An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.
/// </param>
/// <param name="culture">
/// The <see cref="T:System.Globalization.CultureInfo"/> to use as the current culture.
/// </param>
/// <param name="value">The <see cref="T:System.Object"/> to convert. </param>
/// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception>
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string s = value as string;
if (!string.IsNullOrWhiteSpace(s))
{
return new FontFamily(s);
}
return base.ConvertFrom(context, culture, value);
}
/// <summary>
/// Converts the given value object to the specified type, using the specified context and culture
/// information.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the converted value.
/// </returns>
/// <param name="context">
/// An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.
/// </param>
/// <param name="culture">
/// A <see cref="T:System.Globalization.CultureInfo"/>. If null is passed, the current culture is assumed.
/// </param><param name="value">The <see cref="T:System.Object"/> to convert. </param>
/// <param name="destinationType">
/// The <see cref="T:System.Type"/> to convert the <paramref name="value"/> parameter to.
/// </param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="destinationType"/> parameter is null. </exception>
/// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception>
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (null == value)
{
throw new ArgumentNullException("value");
}
FontFamily fontFamily = value as FontFamily;
if (fontFamily == null)
{
throw new ArgumentException("value");
}
if (null == destinationType)
{
throw new ArgumentNullException("destinationType");
}
if (destinationType == typeof(string))
{
return fontFamily.Name;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}

9
src/ImageProcessor.Web/Helpers/QuerystringParser/QueryParamParser.cs

@ -41,6 +41,7 @@ namespace ImageProcessor.Web.Helpers
private QueryParamParser()
{
this.AddColorConverters();
this.AddFontFamilyConverters();
this.AddListConverters();
this.AddArrayConverters();
}
@ -138,6 +139,14 @@ namespace ImageProcessor.Web.Helpers
this.AddTypeConverter(typeof(Color), typeof(ExtendedColorTypeConverter));
}
/// <summary>
/// Adds font family converters.
/// </summary>
private void AddFontFamilyConverters()
{
this.AddTypeConverter(typeof(FontFamily), typeof(FontFamilyConverter));
}
/// <summary>
/// Adds a selection of default list type converters.
/// </summary>

45
src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs

@ -3,7 +3,11 @@
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Processes any image requests within the web application.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.HttpModules
{
using System;
@ -45,10 +49,15 @@ namespace ImageProcessor.Web.HttpModules
private const string CachedResponseFileDependency = "CACHED_IMAGE_DEPENDENCY_054F217C-11CF-49FF-8D2F-698E8E6EB58F";
/// <summary>
/// The regular expression to search strings for.
/// The regular expression to search strings for presets with.
/// </summary>
private static readonly Regex PresetRegex = new Regex(@"preset=[^&]+", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for protocols with.
/// </summary>
private static readonly Regex ProtocolRegex = new Regex("http(s)?://", RegexOptions.Compiled);
/// <summary>
/// The assembly version.
/// </summary>
@ -295,26 +304,28 @@ namespace ImageProcessor.Web.HttpModules
if (currentService != null)
{
bool isFileLocal = currentService.IsFileLocalService;
bool hasMultiParams = request.Url.ToString().Count(f => f == '?') > 1;
string url = request.Url.ToString();
bool isLegacy = ProtocolRegex.Matches(url).Count > 1;
bool hasMultiParams = url.Count(f => f == '?') > 1;
string requestPath = string.Empty;
string queryString = string.Empty;
string urlParameters = string.Empty;
// Legacy support. I'd like to remove this asap.
if (hasMultiParams)
if (isLegacy && hasMultiParams)
{
// We need to split the querystring to get the actual values we want.
string urlDecode = HttpUtility.UrlDecode(request.QueryString.ToString());
string multiQuery = request.QueryString.ToString();
if (!string.IsNullOrWhiteSpace(urlDecode))
if (!string.IsNullOrWhiteSpace(multiQuery))
{
// UrlDecode seems to mess up in some circumstance.
if (urlDecode.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)
if (multiQuery.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)
{
urlDecode = urlDecode.Replace(":/", "://");
multiQuery = multiQuery.Replace(":/", "://");
}
string[] paths = urlDecode.Split('?');
string[] paths = multiQuery.Split('?');
requestPath = paths[0];
@ -335,7 +346,7 @@ namespace ImageProcessor.Web.HttpModules
if (string.IsNullOrWhiteSpace(currentService.Prefix))
{
requestPath = HostingEnvironment.MapPath(request.Path);
queryString = HttpUtility.UrlDecode(request.QueryString.ToString());
queryString = request.QueryString.ToString();
}
else
{
@ -344,8 +355,20 @@ namespace ImageProcessor.Web.HttpModules
? currentService.Settings["Protocol"] + "://"
: string.Empty;
requestPath = protocol + request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/');
queryString = HttpUtility.UrlDecode(request.QueryString.ToString());
// Handle requests that require parameters.
if (hasMultiParams)
{
string[] paths = url.Split('?');
requestPath = protocol
+ request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/')
+ "?" + paths[1];
queryString = paths[2];
}
else
{
requestPath = protocol + request.Path.Replace(currentService.Prefix, string.Empty).TrimStart('/');
queryString = request.QueryString.ToString();
}
}
}

1
src/ImageProcessor.Web/ImageProcessor.Web.csproj

@ -53,6 +53,7 @@
<Compile Include="Configuration\Shared\SettingElementCollection.cs" />
<Compile Include="Extensions\TypeInitializationExtensions.cs" />
<Compile Include="Helpers\ProcessQueryStringEventArgs.cs" />
<Compile Include="Helpers\QuerystringParser\FontFamilyConverter.cs" />
<Compile Include="Helpers\QuerystringParser\ExtendedColorTypeConverter.cs" />
<Compile Include="Helpers\QuerystringParser\QueryParamParser.cs" />
<Compile Include="Helpers\QuerystringParser\GenericArrayTypeConverter.cs" />

1
src/ImageProcessor.Web/Processors/Alpha.cs

@ -10,7 +10,6 @@
namespace ImageProcessor.Web.Processors
{
using System;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Web;

4
src/ImageProcessor.Web/Processors/Brightness.cs

@ -26,7 +26,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"brightness=\d+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"brightness=(-)?\d+", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Brightness"/> class.
@ -74,7 +74,7 @@ namespace ImageProcessor.Web.Processors
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
int percentage = QueryParamParser.Instance.ParseValue<int>(queryCollection["brightness"]);
percentage = ImageMaths.Clamp(percentage, 0, 100);
percentage = ImageMaths.Clamp(percentage, -100, 100);
this.Processor.DynamicParameter = percentage;
}

4
src/ImageProcessor.Web/Processors/Contrast.cs

@ -26,7 +26,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"contrast=\d+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"contrast=(-)?\d+", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Contrast"/> class.
@ -74,7 +74,7 @@ namespace ImageProcessor.Web.Processors
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
int percentage = QueryParamParser.Instance.ParseValue<int>(queryCollection["contrast"]);
percentage = ImageMaths.Clamp(percentage, 0, 100);
percentage = ImageMaths.Clamp(percentage, -100, 100);
this.Processor.DynamicParameter = percentage;
}

2
src/ImageProcessor.Web/Processors/DetectEdges.cs

@ -90,7 +90,7 @@ namespace ImageProcessor.Web.Processors
{
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
IEdgeFilter filter = (IEdgeFilter)detectors[queryCollection["detectedges"]];
IEdgeFilter filter = (IEdgeFilter)detectors[QueryParamParser.Instance.ParseValue<string>(queryCollection["detectedges"])];
bool greyscale = QueryParamParser.Instance.ParseValue<bool>(queryCollection["greyscale"]);
this.Processor.DynamicParameter = new Tuple<IEdgeFilter, bool>(filter, greyscale);
}

1
src/ImageProcessor.Web/Processors/EntropyCrop.cs

@ -14,7 +14,6 @@ namespace ImageProcessor.Web.Processors
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;

239
src/ImageProcessor.Web/Processors/Resize.cs

@ -12,14 +12,15 @@ namespace ImageProcessor.Web.Processors
{
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Imaging;
using ImageProcessor.Processors;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
/// <summary>
/// Resizes an image to the given dimensions.
@ -29,37 +30,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"(width|height)=|(width|height)ratio=|mode=(carve|percent)?|anchor=|center=|upscale=", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the size attribute.
/// </summary>
private static readonly Regex SizeRegex = new Regex(@"(width|height)=\d+(.\d+)?", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the ratio attribute.
/// </summary>
private static readonly Regex RatioRegex = new Regex(@"(width|height)ratio=\d+(.\d+)?", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the mode attribute.
/// </summary>
private static readonly Regex ModeRegex = new Regex(@"mode=(pad|stretch|crop|max)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the anchor attribute.
/// </summary>
private static readonly Regex AnchorRegex = new Regex(@"anchor=(top|bottom|left|right|center)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the center attribute.
/// </summary>
private static readonly Regex CenterRegex = new Regex(@"center=\d+(.\d+)?[,-]\d+(.\d+)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the upscale attribute.
/// </summary>
private static readonly Regex UpscaleRegex = new Regex(@"upscale=false", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"(width|height)=((.)?\d+|\d+(.\d+)?)+", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Resize"/> class.
@ -93,54 +64,33 @@ namespace ImageProcessor.Web.Processors
/// <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>
/// <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;
Match match = this.RegexPattern.Match(queryString);
// First merge the matches so we can parse .
StringBuilder stringBuilder = new StringBuilder();
foreach (Match match in this.RegexPattern.Matches(queryString))
{
if (match.Success)
{
// We don't want any resize carve or percentile crops requests to interfere.
// TODO: This is hacky and awful and should go.
if (match.Value.ToUpperInvariant().Contains("CARVE") || match.Value.ToUpperInvariant().Contains("PERCENT"))
{
continue;
}
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
stringBuilder.Append(queryString);
}
index += 1;
}
}
if (this.SortOrder < int.MaxValue)
if (match.Success)
{
// Match syntax
string toParse = stringBuilder.ToString();
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
Size size = this.ParseSize(queryCollection);
ResizeMode mode = QueryParamParser.Instance.ParseValue<ResizeMode>(queryCollection["mode"]);
AnchorPosition position = QueryParamParser.Instance.ParseValue<AnchorPosition>(queryCollection["anchor"]);
bool upscale = queryCollection["upscale"] == null || QueryParamParser.Instance.ParseValue<bool>(queryCollection["upscale"]);
float[] center = QueryParamParser.Instance.ParseValue<float[]>(queryCollection["center"]);
Size size = this.ParseSize(toParse);
ResizeLayer resizeLayer = new ResizeLayer(size)
{
ResizeMode = this.ParseMode(toParse),
AnchorPosition = this.ParsePosition(toParse),
Upscale = !UpscaleRegex.IsMatch(toParse),
CenterCoordinates = this.ParseCoordinates(toParse),
ResizeMode = mode,
AnchorPosition = position,
Upscale = upscale,
CenterCoordinates = center
};
this.Processor.DynamicParameter = resizeLayer;
@ -151,168 +101,65 @@ namespace ImageProcessor.Web.Processors
((ImageProcessor.Processors.Resize)this.Processor).RestrictedSizes = this.ParseRestrictions(
restrictions);
}
return this.SortOrder;
}
/// <summary>
/// Returns the correct <see cref="Size"/> for the given string.
/// Returns the correct <see cref="Size"/> for the given query collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> containing the query parameters to parse.
/// </param>
/// <returns>
/// The <see cref="Size"/>.
/// </returns>
private Size ParseSize(string input)
private Size ParseSize(NameValueCollection queryCollection)
{
const string Width = "width=";
const string Height = "height=";
const string WidthRatio = "widthratio=";
const string HeightRatio = "heightratio=";
string width = queryCollection["width"];
string height = queryCollection["height"];
string widthRatio = queryCollection["widthratio"];
string heightRatio = queryCollection["heightratio"];
Size size = new Size();
// First merge the matches so we can parse .
StringBuilder stringBuilder = new StringBuilder();
foreach (Match match in SizeRegex.Matches(input))
{
stringBuilder.Append(match.Value);
}
// First cater for single dimensions.
string value = stringBuilder.ToString();
if (input.Contains(Width) && !input.Contains(Height))
if (width != null && height == null)
{
size = new Size(Convert.ToInt32(value.ToPositiveFloatArray()[0]), 0);
size = new Size(QueryParamParser.Instance.ParseValue<int>(width), 0);
}
if (input.Contains(Height) && !input.Contains(Width))
if (width == null && height != null)
{
size = new Size(0, Convert.ToInt32(value.ToPositiveFloatArray()[0]));
size = new Size(0, QueryParamParser.Instance.ParseValue<int>(height));
}
// Both dimensions supplied.
if (input.Contains(Height) && input.Contains(Width))
// Both supplied
if (width != null && height != null)
{
float[] dimensions = value.ToPositiveFloatArray();
// Check the order in which they have been supplied.
size = input.IndexOf(Width, StringComparison.Ordinal) < input.IndexOf(Height, StringComparison.Ordinal)
? new Size(Convert.ToInt32(dimensions[0]), Convert.ToInt32(dimensions[1]))
: new Size(Convert.ToInt32(dimensions[1]), Convert.ToInt32(dimensions[0]));
size = new Size(
QueryParamParser.Instance.ParseValue<int>(width),
QueryParamParser.Instance.ParseValue<int>(height));
}
// Calculate any ratio driven sizes.
if (size.Width == 0 || size.Height == 0)
{
stringBuilder.Clear();
foreach (Match match in RatioRegex.Matches(input))
{
stringBuilder.Append(match.Value);
}
value = stringBuilder.ToString();
// Replace 0 width
if (size.Width == 0 && size.Height > 0 && input.Contains(WidthRatio) && !input.Contains(HeightRatio))
if (size.Width == 0 && size.Height > 0 && widthRatio != null && heightRatio == null)
{
size.Width = Convert.ToInt32(value.ToPositiveFloatArray()[0] * size.Height);
size.Width = Convert.ToInt32(QueryParamParser.Instance.ParseValue<float>(widthRatio) * size.Height);
}
// Replace 0 height
if (size.Height == 0 && size.Width > 0 && input.Contains(HeightRatio) && !input.Contains(WidthRatio))
if (size.Width > 0 && size.Height == 0 && widthRatio == null && heightRatio != null)
{
size.Height = Convert.ToInt32(value.ToPositiveFloatArray()[0] * size.Width);
size.Height = Convert.ToInt32(QueryParamParser.Instance.ParseValue<float>(heightRatio) * size.Width);
}
}
return size;
}
/// <summary>
/// Returns the correct <see cref="ResizeMode"/> for the given string.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="ResizeMode"/>.
/// </returns>
private ResizeMode ParseMode(string input)
{
foreach (Match match in ModeRegex.Matches(input))
{
// Split on =
string mode = match.Value.Split('=')[1];
switch (mode)
{
case "stretch":
return ResizeMode.Stretch;
case "crop":
return ResizeMode.Crop;
case "max":
return ResizeMode.Max;
default:
return ResizeMode.Pad;
}
}
return ResizeMode.Pad;
}
/// <summary>
/// Returns the correct <see cref="AnchorPosition"/> for the given string.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The correct <see cref="AnchorPosition"/>.
/// </returns>
private AnchorPosition ParsePosition(string input)
{
foreach (Match match in AnchorRegex.Matches(input))
{
// Split on =
string anchor = match.Value.Split('=')[1];
switch (anchor)
{
case "top":
return AnchorPosition.Top;
case "bottom":
return AnchorPosition.Bottom;
case "left":
return AnchorPosition.Left;
case "right":
return AnchorPosition.Right;
default:
return AnchorPosition.Center;
}
}
return AnchorPosition.Center;
}
/// <summary>
/// Parses the coordinates.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>The <see cref="float"/> array containing the coordinates</returns>
private float[] ParseCoordinates(string input)
{
float[] floats = { };
foreach (Match match in CenterRegex.Matches(input))
{
floats = match.Value.ToPositiveFloatArray();
}
return floats;
}
/// <summary>
/// Returns a <see cref="List{T}"/> of sizes to restrict resizing to.
/// </summary>
@ -328,7 +175,7 @@ namespace ImageProcessor.Web.Processors
if (!string.IsNullOrWhiteSpace(input))
{
sizes.AddRange(input.Split(',').Select(this.ParseSize));
sizes.AddRange(input.Split(',').Select(q => this.ParseSize(HttpUtility.ParseQueryString(q))));
}
return sizes;

27
src/ImageProcessor.Web/Processors/Rotate.cs

@ -10,7 +10,10 @@
namespace ImageProcessor.Web.Processors
{
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
@ -22,7 +25,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"(^(rotate|angle)|[^.](&,)?rotate|angle)(=|-)[^&|,]+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"rotate=[^&]", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Rotate"/> class.
@ -32,7 +35,6 @@ namespace ImageProcessor.Web.Processors
this.Processor = new ImageProcessor.Processors.Rotate();
}
#region IGraphicsProcessor Members
/// <summary>
/// Gets the regular expression to search strings for.
/// </summary>
@ -69,28 +71,17 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
this.Processor.DynamicParameter = CommonParameterParserUtility.ParseAngle(match.Value);
}
index += 1;
}
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
this.Processor.DynamicParameter = QueryParamParser.Instance.ParseValue<float>(queryCollection["rotate"]);
}
return this.SortOrder;
}
#endregion
}
}

30
src/ImageProcessor.Web/Processors/RotateBounded.cs

@ -11,7 +11,10 @@
namespace ImageProcessor.Web.Processors
{
using System;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
@ -23,7 +26,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"rotatebounded=[^&]+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"rotatebounded=[^&]", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search for.
@ -75,28 +78,17 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
float angle = CommonParameterParserUtility.ParseAngle(match.Value);
bool keepSize = BoundRegex.Match(queryString).Success;
Tuple<float, bool> rotateParams = new Tuple<float, bool>(angle, keepSize);
this.Processor.DynamicParameter = rotateParams;
}
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
float angle = QueryParamParser.Instance.ParseValue<float>(queryCollection["rotatebounded"]);
bool keepSize = BoundRegex.Match(queryString).Success;
index += 1;
}
this.Processor.DynamicParameter = new Tuple<float, bool>(angle, keepSize);
}
return this.SortOrder;

112
src/ImageProcessor.Web/Processors/RoundedCorners.cs

@ -10,10 +10,13 @@
namespace ImageProcessor.Web.Processors
{
using System.Globalization;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Imaging;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
/// <summary>
/// Encapsulates methods to add rounded corners to an image.
@ -23,32 +26,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"roundedcorners=[^&]+", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the angle attribute.
/// </summary>
private static readonly Regex RadiusRegex = new Regex(@"(roundedcorners|radius)(=|-)(\d+)", 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);
private static readonly Regex QueryRegex = new Regex(@"roundedcorners=\d+", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="RoundedCorners"/> class.
@ -88,86 +66,42 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
RoundedCornerLayer roundedCornerLayer = new RoundedCornerLayer(
this.ParseRadius(queryString),
this.ParseCorner(TopLeftRegex, queryString),
this.ParseCorner(TopRightRegex, queryString),
this.ParseCorner(BottomLeftRegex, queryString),
this.ParseCorner(BottomRightRegex, queryString));
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
this.Processor.DynamicParameter = roundedCornerLayer;
}
RoundedCornerLayer roundedCornerLayer = new RoundedCornerLayer(
QueryParamParser.Instance.ParseValue<int>(queryCollection["roundedcorners"]),
this.ParseCorner(queryCollection, "tl"),
this.ParseCorner(queryCollection, "tr"),
this.ParseCorner(queryCollection, "bl"),
this.ParseCorner(queryCollection, "br"));
index += 1;
}
this.Processor.DynamicParameter = roundedCornerLayer;
}
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(new[] { '=', '-' })[1], NumberStyles.Any, CultureInfo.InvariantCulture, out radius);
return radius;
}
// No corners - matches the RoundedCorner default.
return 0;
}
/// <summary>
/// Returns a <see cref="T:System.Boolean"/> either true or false.
/// Returns a value indicating whether to round the given corner.
/// </summary>
/// <param name="corner">
/// The corner.
/// <param name="queryCollection">
/// The collection of query parameters.
/// </param>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="key">
/// The parameter key.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Boolean"/> true or false.
/// </returns>
private bool ParseCorner(Regex corner, string input)
private bool ParseCorner(NameValueCollection queryCollection, string key)
{
foreach (Match match in corner.Matches(input))
{
// Split on corner-
bool cornerRound;
bool.TryParse(match.Value.Split(new[] { '=', '-' })[1], out cornerRound);
return cornerRound;
}
// No corners - matches the RoundedCorner default.
return true;
return queryCollection[key] == null || QueryParamParser.Instance.ParseValue<bool>(queryCollection[key]);
}
#endregion
}
}

32
src/ImageProcessor.Web/Processors/Saturation.cs

@ -10,22 +10,23 @@
namespace ImageProcessor.Web.Processors
{
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Imaging.Helpers;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
/// <summary>
/// Encapsulates methods to change the saturation component of the image.
/// </summary>
/// <remarks>
/// <see href="http://www.bobpowell.net/imagesaturation.htm"/>
/// </remarks>
public class Saturation : IWebGraphicsProcessor
{
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"saturation=[^&|,]+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"saturation=(-)?\d+", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Saturation"/> class.
@ -65,25 +66,16 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
int percentage = CommonParameterParserUtility.ParseIn100Range(match.Value);
this.Processor.DynamicParameter = percentage;
}
index += 1;
}
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
int percentage = QueryParamParser.Instance.ParseValue<int>(queryCollection["saturation"]);
percentage = ImageMaths.Clamp(percentage, -100, 100);
this.Processor.DynamicParameter = percentage;
}
return this.SortOrder;

26
src/ImageProcessor.Web/Processors/Tint.cs

@ -10,7 +10,11 @@
namespace ImageProcessor.Web.Processors
{
using System.Collections.Specialized;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
@ -22,7 +26,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"tint=[^&]+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"tint=[^&]", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Tint"/> class.
@ -59,24 +63,14 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
this.Processor.DynamicParameter = CommonParameterParserUtility.ParseColor(match.Value.Split('=')[1]);
}
index += 1;
}
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
this.Processor.DynamicParameter = QueryParamParser.Instance.ParseValue<Color>(queryCollection["tint"]);
}
return this.SortOrder;

34
src/ImageProcessor.Web/Processors/Vignette.cs

@ -10,8 +10,11 @@
namespace ImageProcessor.Web.Processors
{
using System.Collections.Specialized;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
@ -65,31 +68,20 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
Color color = CommonParameterParserUtility.ParseColor(match.Value.Split('=')[1]);
if (color.Equals(Color.Transparent))
{
color = Color.Black;
}
this.Processor.DynamicParameter = color;
}
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
string vignette = queryCollection["vignette"];
bool doVignette = QueryParamParser.Instance.ParseValue<bool>(vignette);
Color color = doVignette
? Color.Black
: QueryParamParser.Instance.ParseValue<Color>(vignette);
index += 1;
}
this.Processor.DynamicParameter = color;
}
return this.SortOrder;

283
src/ImageProcessor.Web/Processors/Watermark.cs

@ -10,15 +10,14 @@
namespace ImageProcessor.Web.Processors
{
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Text;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using ImageProcessor.Imaging;
using ImageProcessor.Processors;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
/// <summary>
@ -29,47 +28,7 @@ namespace ImageProcessor.Web.Processors
/// <summary>
/// The regular expression to search strings for.
/// </summary>
private static readonly Regex QueryRegex = new Regex(@"watermark=[^&]+", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the text attribute.
/// </summary>
private static readonly Regex TextRegex = new Regex(@"(watermark=[^text-]|text-)[^/:?#\[\]@!$&'()*%\|,;=&]+", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the position attribute.
/// </summary>
private static readonly Regex PositionRegex = new Regex(@"(watermark.position|textposition|[^.](&,=)?position)(=|-)\d+[-,]\d+", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the font size attribute.
/// </summary>
private static readonly Regex FontSizeRegex = new Regex(@"((font)?)size(=|-)\d{1,3}", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the font style attribute.
/// </summary>
private static readonly Regex FontStyleRegex = new Regex(@"((font)?)style(=|-)(bold|italic|regular|strikeout|underline)", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the font family attribute.
/// </summary>
private static readonly Regex FontFamilyRegex = new Regex(@"font(family)?(=|-)[^/:?#\[\]@!$&'()*%\|,;=0-9]+", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the opacity attribute.
/// </summary>
private static readonly Regex OpacityRegex = new Regex(@"(watermark.opacity|fontopacity|[^.](&,=)?opacity)(=|-)(?:100|[1-9]?[0-9])", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the shadow attribute.
/// </summary>
private static readonly Regex ShadowRegex = new Regex(@"((text|font|drop)?)shadow(=|-)true", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for the color attribute.
/// </summary>
private static readonly Regex ColorRegex = new Regex(@"color(=|-)[^&]+", RegexOptions.Compiled);
private static readonly Regex QueryRegex = new Regex(@"watermark=", RegexOptions.Compiled);
/// <summary>
/// Initializes a new instance of the <see cref="Watermark"/> class.
@ -111,38 +70,27 @@ namespace ImageProcessor.Web.Processors
/// </returns>
public int MatchRegexIndex(string queryString)
{
int index = 0;
// Set the sort order to max to allow filtering.
this.SortOrder = int.MaxValue;
Match match = this.RegexPattern.Match(queryString);
foreach (Match match in this.RegexPattern.Matches(queryString))
if (match.Success)
{
if (match.Success)
this.SortOrder = match.Index;
NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString);
TextLayer textLayer = new TextLayer
{
if (index == 0)
{
// Set the index on the first instance only.
this.SortOrder = match.Index;
TextLayer textLayer = new TextLayer
{
Text = this.ParseText(queryString),
Position = this.ParsePosition(queryString),
FontColor = this.ParseColor(queryString),
FontSize = this.ParseFontSize(queryString),
FontFamily = this.ParseFontFamily(queryString),
Style = this.ParseFontStyle(queryString),
DropShadow = this.ParseDropShadow(queryString)
};
textLayer.Opacity = this.ParseOpacity(queryString, textLayer.FontColor);
this.Processor.DynamicParameter = textLayer;
}
index += 1;
}
Text = this.ParseText(queryCollection),
Position = this.ParsePosition(queryCollection),
FontColor = this.ParseColor(queryCollection),
FontSize = this.ParseFontSize(queryCollection),
FontFamily = this.ParseFontFamily(queryCollection),
Style = this.ParseFontStyle(queryCollection),
DropShadow = this.ParseDropShadow(queryCollection)
};
textLayer.Opacity = this.ParseOpacity(queryCollection, textLayer.FontColor);
this.Processor.DynamicParameter = textLayer;
}
return this.SortOrder;
@ -150,200 +98,135 @@ namespace ImageProcessor.Web.Processors
#region Private Methods
/// <summary>
/// Returns the correct <see cref="T:System.String"/> for the given string.
/// Returns the correct <see cref="T:System.String"/> for the given parameter collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The correct <see cref="T:System.String"/> for the given string.
/// The correct <see cref="T:System.String"/>.
/// </returns>
private string ParseText(string input)
private string ParseText(NameValueCollection queryCollection)
{
foreach (Match match in TextRegex.Matches(input))
{
// split on text-
return match.Value.Split(new[] { '=', '-' })[1].Replace("+", " ");
}
return string.Empty;
return QueryParamParser.Instance.ParseValue<string>(queryCollection["watermark"]);
}
/// <summary>
/// Returns the correct <see cref="T:System.Drawing.Point"/> for the given string.
/// Returns the correct <see cref="T:System.Drawing.Point"/> for the given parameter collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Drawing.Point"/>
/// </returns>
private Point? ParsePosition(string input)
private Point? ParsePosition(NameValueCollection queryCollection)
{
foreach (Match match in PositionRegex.Matches(input))
{
// Chop off the leading legacy support '='
int[] position = match.Value.TrimStart('=').ToPositiveIntegerArray();
if (position != null)
{
int x = position[0];
int y = position[1];
return new Point(x, y);
}
}
return null;
return queryCollection["textposition"] != null
? QueryParamParser.Instance.ParseValue<Point>(queryCollection["textposition"])
: (Point?)null;
}
/// <summary>
/// Returns the correct <see cref="T:System.Drawing.Color"/> for the given string.
/// Returns the correct <see cref="T:System.Drawing.Color"/> for the given parameter collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Drawing.Color"/>
/// </returns>
private Color ParseColor(string input)
private Color ParseColor(NameValueCollection queryCollection)
{
foreach (Match match in ColorRegex.Matches(input))
{
string value = match.Value.Split(new[] { '=', '-' })[1];
Color textColor = CommonParameterParserUtility.ParseColor(value);
if (!textColor.Equals(Color.Transparent))
{
return textColor;
}
}
return Color.Black;
return queryCollection["color"] != null
? QueryParamParser.Instance.ParseValue<Color>(queryCollection["color"])
: Color.Black;
}
/// <summary>
/// Returns the correct <see cref="T:System.Int32"/> for the given string.
/// Returns the correct <see cref="T:System.Int32"/> for the given parameter collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Int32"/>
/// </returns>
private int ParseFontSize(string input)
private int ParseFontSize(NameValueCollection queryCollection)
{
foreach (Match match in FontSizeRegex.Matches(input))
{
// split on size-value
return int.Parse(match.Value.Split(new[] { '=', '-' })[1], CultureInfo.InvariantCulture);
}
// Matches the default number in TextLayer.
return 48;
return queryCollection["fontsize"] != null
? QueryParamParser.Instance.ParseValue<int>(queryCollection["fontsize"])
: 48;
}
/// <summary>
/// Returns the correct <see cref="T:System.Drawing.FontStyle"/> for the given string.
/// Returns the correct <see cref="T:System.Drawing.FontStyle"/> for the given parameter collection.
/// </summary>
/// <param name="input">
/// The string containing the respective font style.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Drawing.FontStyle"/>
/// </returns>
private FontStyle ParseFontStyle(string input)
private FontStyle ParseFontStyle(NameValueCollection queryCollection)
{
FontStyle fontStyle = FontStyle.Bold;
foreach (Match match in FontStyleRegex.Matches(input))
{
// split on style-
switch (match.Value.Split(new[]
{
'=', '-'
})[1])
{
case "italic":
fontStyle = FontStyle.Italic;
break;
case "regular":
fontStyle = FontStyle.Regular;
break;
case "strikeout":
fontStyle = FontStyle.Strikeout;
break;
case "underline":
fontStyle = FontStyle.Underline;
break;
}
}
return fontStyle;
return queryCollection["fontstyle"] != null
? QueryParamParser.Instance.ParseValue<FontStyle>(queryCollection["fontstyle"])
: FontStyle.Bold;
}
/// <summary>
/// Returns the correct <see cref="T:System.String"/> containing the font family for the given string.
/// Returns the correct <see cref="FontFamily"/> for the given parameter collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The correct <see cref="T:System.String"/> containing the font family for the given string.
/// The correct <see cref="FontFamily"/>.
/// </returns>
private FontFamily ParseFontFamily(string input)
private FontFamily ParseFontFamily(NameValueCollection queryCollection)
{
foreach (Match match in FontFamilyRegex.Matches(input))
{
// split on font-
string font = match.Value.Split(new[] { '=', '-' })[1].Replace("+", " ");
return new FontFamily(font);
}
return queryCollection["fontfamily"] != null
? QueryParamParser.Instance.ParseValue<FontFamily>(queryCollection["fontfamily"])
: new FontFamily(GenericFontFamilies.SansSerif);
}
return new FontFamily(GenericFontFamilies.SansSerif);
/// <summary>
/// Returns a value indicating whether the watermark is to have a shadow.
/// </summary>
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <returns>
/// The true if the watermark is to have a shadow; otherwise false.
/// </returns>
private bool ParseDropShadow(NameValueCollection queryCollection)
{
return QueryParamParser.Instance.ParseValue<bool>(queryCollection["dropshadow"]);
}
/// <summary>
/// Returns the correct <see cref="T:System.Int32"/> containing the opacity for the given string.
/// Returns the correct <see cref="T:System.Int32"/> containing the opacity for the parameter collection.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// <param name="queryCollection">
/// The <see cref="NameValueCollection"/> of query parameters.
/// </param>
/// <param name="color">
/// The <see cref="T:System.Drawing.Color"/> of the current <see cref="TextLayer"/>.
/// </param>
/// <returns>
/// The correct <see cref="T:System.Int32"/> containing the opacity for the given string.
/// The correct <see cref="T:System.Int32"/>.
/// </returns>
private int ParseOpacity(string input, Color color)
private int ParseOpacity(NameValueCollection queryCollection, Color color)
{
if (color.A < 255)
{
return (color.A / 255) * 100;
}
foreach (Match match in OpacityRegex.Matches(input))
{
// Split on opacity-
return int.Parse(match.Value.Split(new[] { '=', '-' })[1], CultureInfo.InvariantCulture);
}
// Full opacity - matches the TextLayer default.
return 100;
}
/// <summary>
/// Returns a value indicating whether the watermark is to have a shadow.
/// </summary>
/// <param name="input">
/// The input string containing the value to parse.
/// </param>
/// <returns>
/// The true if the watermark is to have a shadow; otherwise false.
/// </returns>
private bool ParseDropShadow(string input)
{
return ShadowRegex.Matches(input).Cast<Match>().Any();
return queryCollection["fontopacity"] != null
? QueryParamParser.Instance.ParseValue<int>(queryCollection["fontopacity"])
: 100;
}
#endregion

9
src/TestWebsites/MVC/Views/Home/External.cshtml

@ -5,15 +5,24 @@
<section>
<div class="row">
<div class="col-s-6">
<h4>Current</h4>
<img src="/remote.axd/images.mymovies.net/images/film/cin/500x377/fid11707.jpg?width=399" />
<h4>Legacy</h4>
<img src="/remote.axd?http://images.mymovies.net/images/film/cin/500x377/fid11707.jpg?width=399" />
</div>
<div class="col-s-6">
<h4>Current</h4>
<img src="/remote.axd/maps.googleapis.com/maps/api/staticmap?center=Albany,+NY&zoom=13&scale=false&size=800x500&maptype=roadmap&sensor=false&format=png&visual_refresh=true?width=401" />
<h4>Legacy</h4>
<img src="/remote.axd?http://maps.googleapis.com/maps/api/staticmap?center=Albany,+NY&zoom=13&scale=false&size=800x500&maptype=roadmap&sensor=false&format=png&visual_refresh=true?width=401" />
</div>
</div>
<div class="row">
<div class="col-s-6">
<h4>Current</h4>
<img src="/remote.axd?http://images.hanselminutes.com/images/255.jpg?width=201" />
<h4>Legacy</h4>
<img src="/remote.axd/images.hanselminutes.com/images/255.jpg?width=201" />
</div>
</div>
</section>

9
src/TestWebsites/MVC/Web.config

@ -25,6 +25,15 @@
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TextWriterOutput.log" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
<system.web>
<httpRuntime targetFramework="4.5" requestPathInvalidCharacters="&lt;,&gt;,*,%,&amp;,\,?" />

Loading…
Cancel
Save