diff --git a/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs b/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
index dd7d00563..87cd3d51d 100644
--- a/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
@@ -13,6 +13,7 @@ namespace ImageProcessor.UnitTests
using System.Linq;
using ImageProcessor.Imaging;
+ using ImageProcessor.Imaging.Filters.EdgeDetection;
using ImageProcessor.Imaging.Filters.Photo;
using NUnit.Framework;
@@ -246,9 +247,9 @@ namespace ImageProcessor.UnitTests
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Watermark(new TextLayer
{
- FontFamily = new FontFamily("Arial"),
- FontSize = 10,
- Position = new Point(10, 10),
+ FontFamily = new FontFamily("Arial"),
+ FontSize = 10,
+ Position = new Point(10, 10),
Text = "Lorem ipsum dolor"
});
Assert.AreNotEqual(original, imageFactory.Image);
@@ -546,6 +547,137 @@ namespace ImageProcessor.UnitTests
}
}
+ ///
+ /// Tests that the images hue has been altered.
+ ///
+ [Test]
+ public void TestHue()
+ {
+ foreach (FileInfo file in this.ListInputFiles())
+ {
+ using (ImageFactory imageFactory = new ImageFactory())
+ {
+ imageFactory.Load(file.FullName);
+ Image original = (Image)imageFactory.Image.Clone();
+ imageFactory.Hue(90);
+ Assert.AreNotEqual(original, imageFactory.Image);
+
+ imageFactory.Reset();
+
+ imageFactory.Hue(116, true);
+ Assert.AreNotEqual(original, imageFactory.Image);
+ }
+ }
+ }
+
+ ///
+ /// Tests that the image has been pixelated.
+ ///
+ [Test]
+ public void TestPixelate()
+ {
+ foreach (FileInfo file in this.ListInputFiles())
+ {
+ using (ImageFactory imageFactory = new ImageFactory())
+ {
+ imageFactory.Load(file.FullName);
+ Image original = (Image)imageFactory.Image.Clone();
+ imageFactory.Pixelate(8);
+ Assert.AreNotEqual(original, imageFactory.Image);
+ }
+ }
+ }
+
+ ///
+ /// Tests that the images quality has been set.
+ ///
+ [Test]
+ public void TestQuality()
+ {
+ foreach (FileInfo file in this.ListInputFiles())
+ {
+ using (ImageFactory imageFactory = new ImageFactory())
+ {
+ imageFactory.Load(file.FullName);
+ int original = imageFactory.CurrentImageFormat.Quality;
+ imageFactory.Quality(69);
+ int updated = imageFactory.CurrentImageFormat.Quality;
+
+ Assert.AreNotEqual(original, updated);
+ }
+ }
+ }
+
+ ///
+ /// Tests that the image has had a color replaced.
+ ///
+ [Test]
+ public void TestReplaceColor()
+ {
+ foreach (FileInfo file in this.ListInputFiles())
+ {
+ using (ImageFactory imageFactory = new ImageFactory())
+ {
+ imageFactory.Load(file.FullName);
+ Image original = (Image)imageFactory.Image.Clone();
+ imageFactory.ReplaceColor(Color.White, Color.Black, 90);
+ Assert.AreNotEqual(original, imageFactory.Image);
+ }
+ }
+ }
+
+ ///
+ /// Tests that the various edge detection algorithms are applied.
+ ///
+ [Test]
+ public void TestEdgeDetection()
+ {
+ foreach (FileInfo file in this.ListInputFiles())
+ {
+ using (ImageFactory imageFactory = new ImageFactory())
+ {
+ imageFactory.Load(file.FullName);
+ Image original = (Image)imageFactory.Image.Clone();
+
+ imageFactory.DetectEdges(new KayyaliEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new KirschEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new Laplacian3X3EdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new Laplacian5X5EdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new LaplacianOfGaussianEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new PrewittEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new RobertsCrossEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new ScharrEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+
+ imageFactory.DetectEdges(new SobelEdgeFilter());
+ Assert.AreNotEqual(original, imageFactory.Image);
+ imageFactory.Reset();
+ }
+ }
+ }
+
///
/// Gets the files matching the given extensions.
///
diff --git a/src/ImageProcessor.Web/Configuration/Resources/processing.config b/src/ImageProcessor.Web/Configuration/Resources/processing.config
index ce00ddffa..bbb28f6e8 100644
--- a/src/ImageProcessor.Web/Configuration/Resources/processing.config
+++ b/src/ImageProcessor.Web/Configuration/Resources/processing.config
@@ -7,6 +7,7 @@
+
diff --git a/src/ImageProcessor.Web/ImageProcessor.Web.csproj b/src/ImageProcessor.Web/ImageProcessor.Web.csproj
index 05b2299b1..e98b1ad50 100644
--- a/src/ImageProcessor.Web/ImageProcessor.Web.csproj
+++ b/src/ImageProcessor.Web/ImageProcessor.Web.csproj
@@ -46,6 +46,7 @@
+
diff --git a/src/ImageProcessor.Web/Processors/DetectEdges.cs b/src/ImageProcessor.Web/Processors/DetectEdges.cs
new file mode 100644
index 000000000..3a65730ad
--- /dev/null
+++ b/src/ImageProcessor.Web/Processors/DetectEdges.cs
@@ -0,0 +1,166 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// Produces an image with the detected edges highlighted.
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Web.Processors
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Web.Compilation;
+
+ using ImageProcessor.Common.Extensions;
+ using ImageProcessor.Imaging.Filters.EdgeDetection;
+ using ImageProcessor.Processors;
+
+ ///
+ /// Produces an image with the detected edges highlighted.
+ ///
+ public class DetectEdges : IWebGraphicsProcessor
+ {
+ ///
+ /// The regular expression to search strings for.
+ ///
+ private static readonly Regex QueryRegex = BuildRegex();
+
+ ///
+ /// The regular expression to search strings for the greyscale attribute.
+ ///
+ private static readonly Regex GreyscaleRegex = new Regex(@"greyscale=false", RegexOptions.Compiled);
+
+ ///
+ /// The edge detectors.
+ ///
+ private static Dictionary detectors;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DetectEdges()
+ {
+ this.Processor = new ImageProcessor.Processors.DetectEdges();
+ }
+
+ ///
+ /// Gets the regular expression to search strings for.
+ ///
+ public Regex RegexPattern
+ {
+ get
+ {
+ return QueryRegex;
+ }
+ }
+
+ ///
+ /// Gets the order in which this processor is to be used in a chain.
+ ///
+ public int SortOrder { get; private set; }
+
+ ///
+ /// Gets the processor.
+ ///
+ ///
+ /// The processor.
+ ///
+ public IGraphicsProcessor Processor { get; private set; }
+
+ ///
+ /// The position in the original string where the first character of the captured substring was found.
+ ///
+ ///
+ /// The query string to search.
+ ///
+ ///
+ /// The zero-based starting position in the original string where the captured substring was found.
+ ///
+ public int MatchRegexIndex(string queryString)
+ {
+ int index = 0;
+
+ // Set the sort order to max to allow filtering.
+ this.SortOrder = int.MaxValue;
+
+ // First merge the matches so we can parse .
+ StringBuilder stringBuilder = new StringBuilder();
+
+ 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;
+ stringBuilder.Append(queryString);
+ }
+
+ index += 1;
+ }
+ }
+
+ if (this.SortOrder < int.MaxValue)
+ {
+ // Match syntax
+ string toParse = stringBuilder.ToString();
+ IEdgeFilter filter = this.ParseFilter(toParse);
+ bool greyscale = !GreyscaleRegex.IsMatch(toParse);
+
+ this.Processor.DynamicParameter = new Tuple(filter, greyscale);
+ }
+
+ return this.SortOrder;
+ }
+
+ ///
+ /// Builds a regular expression from the type, this allows extensibility.
+ ///
+ ///
+ /// The to match matrix filters.
+ ///
+ private static Regex BuildRegex()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ stringBuilder.Append("detectedges=(");
+
+ Type type = typeof(IEdgeFilter);
+
+ // Build a list of native IEdgeFilter instances.
+ detectors = BuildManager.GetReferencedAssemblies()
+ .Cast()
+ .SelectMany(s => s.GetLoadableTypes())
+ .Where(t => type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract)
+ .ToDictionary(t => t.Name.ToLowerInvariant().Replace("edgefilter", string.Empty), Activator.CreateInstance);
+
+ stringBuilder.Append(string.Join("|", detectors.Keys.ToList()));
+
+ stringBuilder.Append(")");
+
+ return new Regex(stringBuilder.ToString(), RegexOptions.IgnoreCase);
+ }
+
+ ///
+ /// Parses the input string to return the correct .
+ ///
+ ///
+ /// The identifier.
+ ///
+ ///
+ /// The .
+ ///
+ private IEdgeFilter ParseFilter(string identifier)
+ {
+ return (IEdgeFilter)detectors[this.RegexPattern.Match(identifier).Value.Split('=')[1]];
+ }
+ }
+}
diff --git a/src/ImageProcessor.Web/Processors/Filter.cs b/src/ImageProcessor.Web/Processors/Filter.cs
index 533bf2e1d..f9c8fec7c 100644
--- a/src/ImageProcessor.Web/Processors/Filter.cs
+++ b/src/ImageProcessor.Web/Processors/Filter.cs
@@ -51,11 +51,7 @@ namespace ImageProcessor.Web.Processors
///
/// Gets the order in which this processor is to be used in a chain.
///
- public int SortOrder
- {
- get;
- private set;
- }
+ public int SortOrder { get; private set; }
///
/// Gets the processor.
diff --git a/src/ImageProcessor.Web/Processors/Resize.cs b/src/ImageProcessor.Web/Processors/Resize.cs
index ca980b232..207cd0b98 100644
--- a/src/ImageProcessor.Web/Processors/Resize.cs
+++ b/src/ImageProcessor.Web/Processors/Resize.cs
@@ -128,24 +128,29 @@ namespace ImageProcessor.Web.Processors
}
}
- // Match syntax
- string toParse = stringBuilder.ToString();
-
- Size size = this.ParseSize(toParse);
- ResizeLayer resizeLayer = new ResizeLayer(size)
+ if (this.SortOrder < int.MaxValue)
{
- ResizeMode = this.ParseMode(toParse),
- AnchorPosition = this.ParsePosition(toParse),
- Upscale = !UpscaleRegex.IsMatch(toParse),
- CenterCoordinates = this.ParseCoordinates(toParse),
- };
-
- this.Processor.DynamicParameter = resizeLayer;
-
- // Correctly parse any restrictions.
- string restrictions;
- this.Processor.Settings.TryGetValue("RestrictTo", out restrictions);
- ((ImageProcessor.Processors.Resize)this.Processor).RestrictedSizes = this.ParseRestrictions(restrictions);
+ // Match syntax
+ string toParse = stringBuilder.ToString();
+
+ 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),
+ };
+
+ this.Processor.DynamicParameter = resizeLayer;
+
+ // Correctly parse any restrictions.
+ string restrictions;
+ this.Processor.Settings.TryGetValue("RestrictTo", out restrictions);
+ ((ImageProcessor.Processors.Resize)this.Processor).RestrictedSizes = this.ParseRestrictions(
+ restrictions);
+ }
+
return this.SortOrder;
}
diff --git a/src/ImageProcessor.sln b/src/ImageProcessor.sln
index 335de55aa..52fa46752 100644
--- a/src/ImageProcessor.sln
+++ b/src/ImageProcessor.sln
@@ -22,7 +22,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web", "Image
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Plugins.WebP", "Plugins\ImageProcessor\ImageProcessor.Plugins.WebP\ImageProcessor.Plugins.WebP.csproj", "{2CF69699-959A-44DC-A281-4E2596C25043}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Playground", "ImageProcessor.Playground\ImageProcessor.Playground.csproj", "{7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Playground", "ImageProcessorConsole\ImageProcessor.Playground.csproj", "{7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web.UnitTests", "ImageProcessor.Web.UnitTests\ImageProcessor.Web.UnitTests.csproj", "{961340C8-8C93-401D-A0A2-FF9EC61E5260}"
EndProject
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index dd4fa8015..f234473a6 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -81,9 +81,9 @@
-
-
-
+
+
+
diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs
index e6568c19f..7e3fb9be8 100644
--- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs
+++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
-//
+//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3X3EdgeFilter.cs
similarity index 90%
rename from src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs
rename to src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3X3EdgeFilter.cs
index e4c694496..ccaa3d35e 100644
--- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs
+++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3X3EdgeFilter.cs
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
-//
+//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
@@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
/// The Laplacian 3 x 3 operator filter.
///
///
- public class Laplacian3X3Filter : IEdgeFilter
+ public class Laplacian3X3EdgeFilter : IEdgeFilter
{
///
/// Gets the horizontal gradient operator.
diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5EdgeFilter.cs
similarity index 90%
rename from src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs
rename to src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5EdgeFilter.cs
index 97bd90cf8..b25abbac7 100644
--- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs
+++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5EdgeFilter.cs
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
-//
+//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
@@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
/// The Laplacian 5 x 5 operator filter.
///
///
- public class Laplacian5X5Filter : IEdgeFilter
+ public class Laplacian5X5EdgeFilter : IEdgeFilter
{
///
/// Gets the horizontal gradient operator.
diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianEdgeFilter.cs
similarity index 90%
rename from src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs
rename to src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianEdgeFilter.cs
index b2c4cdd2d..947796a38 100644
--- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs
+++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianEdgeFilter.cs
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
-//
+//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
@@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
/// The Laplacian of Gaussian operator filter.
///
///
- public class LaplacianOfGaussianFilter : IEdgeFilter
+ public class LaplacianOfGaussianEdgeFilter : IEdgeFilter
{
///
/// Gets the horizontal gradient operator.
diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessorConsole/Program.cs
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/TestWebsites/MVC/config/imageprocessor/processing.config b/src/TestWebsites/MVC/config/imageprocessor/processing.config
index 2dc2d374e..33c9a5c65 100644
--- a/src/TestWebsites/MVC/config/imageprocessor/processing.config
+++ b/src/TestWebsites/MVC/config/imageprocessor/processing.config
@@ -8,6 +8,7 @@
+