// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
//
// Encapsulates methods to correctly parse querystring parameters.
//
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Helpers
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Web.Extensions;
///
/// Encapsulates methods to correctly parse querystring parameters.
///
public static class CommonParameterParserUtility
{
///
/// The collection of known colors.
///
private static readonly Dictionary KnownColors = new Dictionary();
///
/// The regular expression to search strings for colors.
///
private static readonly Regex ColorRegex = BuildColorRegex();
///
/// The regular expression to search strings for angles.
///
private static readonly Regex AngleRegex = new Regex(@"(rotate|angle)(=|-)(?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)", RegexOptions.Compiled);
///
/// The regular expression to search strings for values between 1 and 100.
///
private static readonly Regex In100RangeRegex = new Regex(@"(-?0*(?:100|[1-9][0-9]?))", RegexOptions.Compiled);
///
/// The sharpen regex.
///
private static readonly Regex BlurSharpenRegex = new Regex(@"(blur|sharpen)=\d+", RegexOptions.Compiled);
///
/// The sigma regex.
///
private static readonly Regex SigmaRegex = new Regex(@"sigma(=|-)\d+(.?\d+)?", RegexOptions.Compiled);
///
/// The threshold regex.
///
private static readonly Regex ThresholdRegex = new Regex(@"threshold(=|-)\d+", RegexOptions.Compiled);
///
/// Returns the correct containing the angle for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The correct containing the angle for the given string.
///
public static int ParseAngle(string input)
{
foreach (Match match in AngleRegex.Matches(input))
{
// Split on angle
int angle;
string value = match.Value.Split(new[] { '=', '-' })[1];
int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out angle);
return angle;
}
// No rotate - matches the RotateLayer default.
return 0;
}
///
/// Returns the correct for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The correct
///
public static Color ParseColor(string input)
{
foreach (Match match in ColorRegex.Matches(input))
{
string value = match.Value.Split(new[] { '=', '-' })[1];
if (KnownColors.ContainsKey(value))
{
return Color.FromKnownColor(KnownColors[value]);
}
if (value.Contains(","))
{
int[] split = value.ToPositiveIntegerArray();
byte red = split[0].ToByte();
byte green = split[1].ToByte();
byte blue = split[2].ToByte();
byte alpha = split[3].ToByte();
return Color.FromArgb(alpha, red, green, blue);
}
// Split on color-hex
return ColorTranslator.FromHtml("#" + value);
}
return Color.Transparent;
}
///
/// Returns the correct for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The correct between -100 and 100.
///
public static int ParseIn100Range(string input)
{
int value = 0;
foreach (Match match in In100RangeRegex.Matches(input))
{
value = int.Parse(match.Value, CultureInfo.InvariantCulture);
}
return value;
}
///
/// Returns the correct for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The maximum size to set the Gaussian kernel to.
///
///
/// The maximum Sigma value (standard deviation) for Gaussian function used to calculate the kernel.
///
///
/// The maximum threshold value, which is added to each weighted sum of pixels.
///
///
/// The correct .
///
public static GaussianLayer ParseGaussianLayer(string input, int maxSize, double maxSigma, int maxThreshold)
{
int size = ParseBlurSharpen(input);
double sigma = ParseSigma(input);
int threshold = ParseThreshold(input);
size = maxSize < size ? maxSize : size;
sigma = maxSigma < sigma ? maxSigma : sigma;
threshold = maxThreshold < threshold ? maxThreshold : threshold;
return new GaussianLayer(size, sigma, threshold);
}
///
/// Returns the correct containing the blur value
/// for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The correct for the given string.
///
private static int ParseBlurSharpen(string input)
{
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (Match match in BlurSharpenRegex.Matches(input))
{
return Convert.ToInt32(match.Value.Split('=')[1]);
}
return 0;
}
///
/// Returns the correct containing the sigma value
/// for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The correct for the given string.
///
private static double ParseSigma(string input)
{
foreach (Match match in SigmaRegex.Matches(input))
{
// split on text-
return Convert.ToDouble(match.Value.Split(new[] { '=', '-' })[1]);
}
return 1.4d;
}
///
/// Returns the correct containing the threshold value
/// for the given string.
///
///
/// The input string containing the value to parse.
///
///
/// The correct for the given string.
///
private static int ParseThreshold(string input)
{
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (Match match in ThresholdRegex.Matches(input))
{
return Convert.ToInt32(match.Value.Split(new[] { '=', '-' })[1]);
}
return 0;
}
///
/// Builds a regular expression for the three main colour types.
///
///
/// The to match colors.
///
private static Regex BuildColorRegex()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(@"(bgcolor|color|tint|vignette)(=|-)(\d+,\d+,\d+,\d+|([0-9a-fA-F]{3}){1,2}|(");
KnownColor[] knownColors = (KnownColor[])Enum.GetValues(typeof(KnownColor));
for (int i = 0; i < knownColors.Length; i++)
{
KnownColor knownColor = knownColors[i];
string name = knownColor.ToString().ToLowerInvariant();
KnownColors.Add(name, knownColor);
stringBuilder.Append(i > 0 ? "|" + name : name);
}
stringBuilder.Append("))");
return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase);
}
}
}