Browse Source

Adding improved plugin and preset handling

Former-commit-id: ba6f9656a899c9e75427c47922c6aa0810531153
af/merge-core
James South 12 years ago
parent
commit
5e72f9a975
  1. 171
      src/ImageProcessor.Web/NET45/Config/ImageProcessingSection.cs
  2. 106
      src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs
  3. 11
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  4. 37
      src/TestWebsites/NET4/config/imageprocessor/processing.config
  5. 8
      src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config
  6. 33
      src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/processing.config

171
src/ImageProcessor.Web/NET45/Config/ImageProcessingSection.cs

@ -1,9 +1,13 @@
// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageProcessingSection.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
// <summary>
// Represents an image processing section within a configuration file.
// Nested syntax adapted from <see cref="http://tneustaedter.blogspot.co.uk/2011/09/how-to-create-one-or-more-nested.html" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Config
{
@ -19,6 +23,21 @@ namespace ImageProcessor.Web.Config
public sealed class ImageProcessingSection : ConfigurationSection
{
#region Properties
/// <summary>
/// Gets the <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.PresetElementCollection"/>.
/// </summary>
/// <value>
/// The <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.PresetElementCollection"/>.
/// </value>
[ConfigurationProperty("presets", IsRequired = true)]
public PresetElementCollection Presets
{
get
{
return this["presets"] as PresetElementCollection;
}
}
/// <summary>
/// Gets the <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.PluginElementCollection"/>.
/// </summary>
@ -54,6 +73,115 @@ namespace ImageProcessor.Web.Config
}
#endregion
/// <summary>
/// Represents a PresetElement configuration element within the configuration.
/// </summary>
public class PresetElement : ConfigurationElement
{
/// <summary>
/// Gets or sets the name of the preset.
/// </summary>
/// <value>The name of the plugin.</value>
[ConfigurationProperty("name", DefaultValue = "", IsRequired = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
/// <summary>
/// Gets or sets the value of the preset.
/// </summary>
/// <value>The full Type definition of the plugin</value>
[ConfigurationProperty("value", DefaultValue = "", IsRequired = true)]
public string Value
{
get { return (string)this["value"]; }
set { this["value"] = value; }
}
}
/// <summary>
/// Represents a PresetElementCollection collection configuration element within the configuration.
/// </summary>
public class PresetElementCollection : ConfigurationElementCollection
{
/// <summary>
/// Gets the type of the <see cref="T:System.Configuration.ConfigurationElementCollection"/>.
/// </summary>
/// <value>
/// The <see cref="T:System.Configuration.ConfigurationElementCollectionType"/> of this collection.
/// </value>
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMap; }
}
/// <summary>
/// Gets the name used to identify this collection of elements in the configuration file when overridden in a derived class.
/// </summary>
/// <value>
/// The name of the collection; otherwise, an empty string. The default is an empty string.
/// </value>
protected override string ElementName
{
get { return "preset"; }
}
/// <summary>
/// Gets or sets the <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.PresetElement"/>
/// at the specified index within the collection.
/// </summary>
/// <param name="index">The index at which to get the specified object.</param>
/// <returns>
/// The the <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.PresetElement"/>
/// at the specified index within the collection.
/// </returns>
public PresetElement this[int index]
{
get
{
return (PresetElement)BaseGet(index);
}
set
{
if (this.BaseGet(index) != null)
{
this.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
}
}
/// <summary>
/// Creates a new Preset configuration element.
/// </summary>
/// <returns>
/// A new PluginConfig configuration element.
/// </returns>
protected override ConfigurationElement CreateNewElement()
{
return new PresetElement();
}
/// <summary>
/// Gets the element key for a specified PluginElement configuration element.
/// </summary>
/// <param name="element">
/// The <see cref="T:System.Configuration.ConfigurationElement">ConfigurationElement</see>
/// to return the key for.
/// </param>
/// <returns>The element key for a specified PluginElement configuration element.</returns>
protected override object GetElementKey(ConfigurationElement element)
{
return ((PresetElement)element).Name;
}
}
/// <summary>
/// Represents a PluginElement configuration element within the configuration.
/// </summary>
@ -104,6 +232,19 @@ namespace ImageProcessor.Web.Config
/// </summary>
public class PluginElementCollection : ConfigurationElementCollection
{
/// <summary>
/// Gets or sets a value indicating whether to auto load all plugins.
/// <remarks>Defaults to <value>True</value>.</remarks>
/// </summary>
/// <value>If True plugins are auto discovered and loaded from all assemblies otherwise they must be defined in the configuration file</value>
[ConfigurationProperty("autoLoadPlugins", DefaultValue = true, IsRequired = false)]
public bool AutoLoadPlugins
{
get { return (bool)this["autoLoadPlugins"]; }
set { this["autoLoadPlugins"] = value; }
}
/// <summary>
/// Gets the type of the <see cref="T:System.Configuration.ConfigurationElementCollection"/>.
/// </summary>
@ -126,18 +267,6 @@ namespace ImageProcessor.Web.Config
get { return "plugin"; }
}
/// <summary>
/// Gets or sets the autoLoadPlugins of the plugin file.
/// </summary>
/// <value>If True plugins are auto discovered and loaded from all assemblies otherwise they must be defined in the configuration file</value>
[ConfigurationProperty("autoLoadPlugins", DefaultValue = true, IsRequired = false)]
public bool AutoLoadPlugins
{
get { return (bool)this["autoLoadPlugins"]; }
set { this["autoLoadPlugins"] = value; }
}
/// <summary>
/// Gets or sets the <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.PluginElement"/>
/// at the specified index within the collection.
@ -161,15 +290,15 @@ namespace ImageProcessor.Web.Config
this.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
this.BaseAdd(index, value);
}
}
/// <summary>
/// Creates a new PluginConfig configuration element.
/// Creates a new Plugin configuration element.
/// </summary>
/// <returns>
/// A new PluginConfig configuration element.
/// A new Plugin configuration element.
/// </returns>
protected override ConfigurationElement CreateNewElement()
{
@ -279,10 +408,10 @@ namespace ImageProcessor.Web.Config
{
if (this.BaseGet(index) != null)
{
this.BaseRemoveAt(index);
this.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
this.BaseAdd(index, value);
}
}

106
src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs

@ -8,9 +8,6 @@
// <see cref="http://csharpindepth.com/Articles/General/Singleton.aspx" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections;
namespace ImageProcessor.Web.Config
{
#region Using
@ -45,6 +42,12 @@ namespace ImageProcessor.Web.Config
private static readonly Dictionary<string, Dictionary<string, string>> PluginSettings =
new Dictionary<string, Dictionary<string, string>>();
/// <summary>
/// A collection of the processing presets defined in the configuration.
/// for available plugins.
/// </summary>
private static readonly Dictionary<string, string> PresetSettings = new Dictionary<string, string>();
/// <summary>
/// The processing configuration section from the current application configuration.
/// </summary>
@ -183,6 +186,36 @@ namespace ImageProcessor.Web.Config
#endregion
#region Methods
/// <summary>
/// Returns the collection of the processing presets defined in the configuration.
/// </summary>
/// <param name="name">
/// The name of the plugin to get the settings for.
/// </param>
/// <returns>
/// The <see cref="T:Systems.Collections.Generic.Dictionary{string, string}"/> containing the processing presets defined in the configuration.
/// </returns>
public string GetPresetSettings(string name)
{
if (!PresetSettings.ContainsKey(name))
{
var presetElement =
GetImageProcessingSection().Presets
.Cast<ImageProcessingSection.PresetElement>()
.FirstOrDefault(x => x.Name == name);
if (presetElement != null)
{
PresetSettings.Add(presetElement.Name, presetElement.Value);
}
}
string preset;
PresetSettings.TryGetValue(name, out preset);
return preset;
}
/// <summary>
/// Returns the <see cref="T:ImageProcessor.Web.Config.ImageProcessingSection.SettingElementCollection"/> for the given plugin.
/// </summary>
@ -255,12 +288,12 @@ namespace ImageProcessor.Web.Config
{
if (this.GraphicsProcessors == null)
{
if (GetImageProcessingSection().Plugins.AutoLoadPlugins)
try
{
try
if (GetImageProcessingSection().Plugins.AutoLoadPlugins)
{
// Build a list of native IGraphicsProcessor instances.
Type type = typeof (IGraphicsProcessor);
Type type = typeof(IGraphicsProcessor);
IEnumerable<Type> types =
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
@ -277,51 +310,52 @@ namespace ImageProcessor.Web.Config
processor.Settings = this.GetPluginSettings(processor.GetType().Name);
}
}
catch (ReflectionTypeLoadException ex)
else
{
StringBuilder sb = new StringBuilder();
foreach (Exception exception in ex.LoaderExceptions)
ImageProcessingSection.PluginElementCollection pluginConfigs = imageProcessingSection.Plugins;
this.GraphicsProcessors = new List<IGraphicsProcessor>();
foreach (ImageProcessingSection.PluginElement pluginConfig in pluginConfigs)
{
sb.AppendLine(exception.Message);
if (exception is FileNotFoundException)
Type type = Type.GetType(pluginConfig.Type);
if (type == null)
{
FileNotFoundException fileNotFoundException = exception as FileNotFoundException;
if (!string.IsNullOrEmpty(fileNotFoundException.FusionLog))
{
sb.AppendLine("Fusion Log:");
sb.AppendLine(fileNotFoundException.FusionLog);
}
throw new ArgumentException("Couldn't load IGraphicsProcessor: " + pluginConfig.Type);
}
sb.AppendLine();
this.GraphicsProcessors.Add(Activator.CreateInstance(type) as IGraphicsProcessor);
}
string errorMessage = sb.ToString();
// Display or log the error based on your application.
throw new Exception(errorMessage);
// Add the available settings.
foreach (IGraphicsProcessor processor in this.GraphicsProcessors)
{
processor.Settings = this.GetPluginSettings(processor.GetType().Name);
}
}
}
else
catch (ReflectionTypeLoadException ex)
{
var pluginConfigs = imageProcessingSection.Plugins;
this.GraphicsProcessors = new List<IGraphicsProcessor>();
foreach (ImageProcessingSection.PluginElement pluginConfig in pluginConfigs)
StringBuilder stringBuilder = new StringBuilder();
foreach (Exception exception in ex.LoaderExceptions)
{
var type = Type.GetType(pluginConfig.Type);
if (type == null)
stringBuilder.AppendLine(exception.Message);
if (exception is FileNotFoundException)
{
throw new ArgumentException("Couldn't load IGraphicsProcessor: " + pluginConfig.Type);
FileNotFoundException fileNotFoundException = exception as FileNotFoundException;
if (!string.IsNullOrEmpty(fileNotFoundException.FusionLog))
{
stringBuilder.AppendLine("Fusion Log:");
stringBuilder.AppendLine(fileNotFoundException.FusionLog);
}
}
this.GraphicsProcessors.Add((Activator.CreateInstance(type) as IGraphicsProcessor));
}
// Add the available settings.
foreach (IGraphicsProcessor processor in this.GraphicsProcessors)
{
processor.Settings = this.GetPluginSettings(processor.GetType().Name);
stringBuilder.AppendLine();
}
string errorMessage = stringBuilder.ToString();
// Display or log the error based on your application.
throw new Exception(errorMessage);
}
}
}

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

@ -542,17 +542,14 @@ namespace ImageProcessor.Web.HttpModules
/// </returns>
private string ReplacePresetsInQueryString(string queryString)
{
// We use the processor config system to store the preset values.
Dictionary<string, string> presets = ImageProcessorConfig.Instance.GetPluginSettings("Preset");
foreach (Match match in PresetRegex.Matches(queryString))
{
if (match.Success)
{
// Set the index on the first instance only.
string preset = match.Value;
string replacements;
presets.TryGetValue(preset.Split('=')[1], out replacements);
string preset = match.Value.Split('=')[1];
// We use the processor config system to store the preset values.
string replacements = ImageProcessorConfig.Instance.GetPresetSettings(preset);
queryString = Regex.Replace(queryString, preset, replacements ?? string.Empty);
}
}

37
src/TestWebsites/NET4/config/imageprocessor/processing.config

@ -1,17 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<processing>
<plugins>
<plugin name="Resize">
<presets>
<preset name="demo" value="width=300&#038;height=150&#038;bgcolor=transparent"/>
</presets>
<plugins autoLoadPlugins="false">
<plugin name="Alpha" type="ImageProcessor.Processors.Alpha, ImageProcessor"/>
<plugin name="Brightness" type="ImageProcessor.Processors.Brightness, ImageProcessor"/>
<plugin name="Contrast" type="ImageProcessor.Processors.Contrast, ImageProcessor"/>
<plugin name="Crop" type="ImageProcessor.Processors.Crop, ImageProcessor"/>
<plugin name="Filter" type="ImageProcessor.Processors.Filter, ImageProcessor"/>
<plugin name="Flip" type="ImageProcessor.Processors.Flip, ImageProcessor"/>
<plugin name="Format" type="ImageProcessor.Processors.Format, ImageProcessor"/>
<plugin name="GaussianBlur" type="ImageProcessor.Processors.GaussianBlur, ImageProcessor">
<settings>
<setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/>
<setting key="MaxSize" value="22"/>
<setting key="MaxSigma" value="5.1"/>
<setting key="MaxThreshold" value="100"/>
</settings>
</plugin>
<plugin name="Preset">
<plugin name="GaussianSharpen" type="ImageProcessor.Processors.GaussianSharpen, ImageProcessor">
<settings>
<setting key="a" value="width=300&#038;height=150"/>
<setting key="MaxSize" value="22"/>
<setting key="MaxSigma" value="5.1"/>
<setting key="MaxThreshold" value="100"/>
</settings>
</plugin>
<plugin name="Quality" type="ImageProcessor.Processors.Quality, ImageProcessor"/>
<plugin name="Resize" type="ImageProcessor.Processors.Resize, ImageProcessor">
<settings>
<setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/>
</settings>
</plugin>
<plugin name="Rotate" type="ImageProcessor.Processors.Rotate, ImageProcessor"/>
<plugin name="RoundedCorners" type="ImageProcessor.Processors.RoundedCorners, ImageProcessor"/>
<plugin name="Saturation" type="ImageProcessor.Processors.Saturation, ImageProcessor"/>
<plugin name="Vignette" type="ImageProcessor.Processors.Vignette, ImageProcessor"/>
<plugin name="Watermark" type="ImageProcessor.Processors.Watermark, ImageProcessor"/>
</plugins>
</processing>

8
src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<processing>
<presets>
<preset name="demo" value="width=300&#038;height=150&#038;bgcolor=transparent"/>
</presets>
<plugins autoLoadPlugins="false">
<plugin name="Alpha" type="ImageProcessor.Processors.Alpha, ImageProcessor"/>
<plugin name="Brightness" type="ImageProcessor.Processors.Brightness, ImageProcessor"/>
@ -34,11 +37,6 @@
<plugin name="Saturation" type="ImageProcessor.Processors.Saturation, ImageProcessor"/>
<plugin name="Vignette" type="ImageProcessor.Processors.Vignette, ImageProcessor"/>
<plugin name="Watermark" type="ImageProcessor.Processors.Watermark, ImageProcessor"/>
<plugin name="Preset" type="ImageProcessor.Web.Preset, ImageProcessor">
<settings>
<setting key="demo" value="width=300&#038;height=150&#038;&#038;bgcolor=transparent"/>
</settings>
</plugin>
</plugins>
</processing>

33
src/TestWebsites/NET45/Test_Website_Webforms_NET45/config/imageprocessor/processing.config

@ -1,31 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<processing>
<plugins>
<plugin name="Resize">
<settings>
<setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/>
</settings>
</plugin>
<plugin name="GaussianBlur">
<presets>
<preset name="demo" value="width=300&#038;height=150&#038;bgcolor=transparent"/>
</presets>
<plugins autoLoadPlugins="false">
<plugin name="Alpha" type="ImageProcessor.Processors.Alpha, ImageProcessor"/>
<plugin name="Brightness" type="ImageProcessor.Processors.Brightness, ImageProcessor"/>
<plugin name="Contrast" type="ImageProcessor.Processors.Contrast, ImageProcessor"/>
<plugin name="Crop" type="ImageProcessor.Processors.Crop, ImageProcessor"/>
<plugin name="Filter" type="ImageProcessor.Processors.Filter, ImageProcessor"/>
<plugin name="Flip" type="ImageProcessor.Processors.Flip, ImageProcessor"/>
<plugin name="Format" type="ImageProcessor.Processors.Format, ImageProcessor"/>
<plugin name="GaussianBlur" type="ImageProcessor.Processors.GaussianBlur, ImageProcessor">
<settings>
<setting key="MaxSize" value="22"/>
<setting key="MaxSigma" value="5.1"/>
<setting key="MaxThreshold" value="100"/>
</settings>
</plugin>
<plugin name="GaussianSharpen">
<plugin name="GaussianSharpen" type="ImageProcessor.Processors.GaussianSharpen, ImageProcessor">
<settings>
<setting key="MaxSize" value="22"/>
<setting key="MaxSigma" value="5.1"/>
<setting key="MaxThreshold" value="100"/>
</settings>
</plugin>
<plugin name="Preset">
<plugin name="Quality" type="ImageProcessor.Processors.Quality, ImageProcessor"/>
<plugin name="Resize" type="ImageProcessor.Processors.Resize, ImageProcessor">
<settings>
<setting key="demo" value="width=300&#038;height=150"/>
<setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="3000"/>
</settings>
</plugin>
<plugin name="Rotate" type="ImageProcessor.Processors.Rotate, ImageProcessor"/>
<plugin name="RoundedCorners" type="ImageProcessor.Processors.RoundedCorners, ImageProcessor"/>
<plugin name="Saturation" type="ImageProcessor.Processors.Saturation, ImageProcessor"/>
<plugin name="Vignette" type="ImageProcessor.Processors.Vignette, ImageProcessor"/>
<plugin name="Watermark" type="ImageProcessor.Processors.Watermark, ImageProcessor"/>
</plugins>
</processing>

Loading…
Cancel
Save