diff --git a/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs b/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs
index cba1c07bc..91b62d74f 100644
--- a/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs
@@ -10,7 +10,6 @@
namespace ImageProcessor.UnitTests.Extensions
{
- using System.Collections.Generic;
using Common.Extensions;
using NUnit.Framework;
@@ -20,37 +19,20 @@ namespace ImageProcessor.UnitTests.Extensions
[TestFixture]
public class DoubleExtensionsUnitTests
{
- ///
- /// Stores the values to test for the ToByte() extension method
- ///
- private Dictionary doubleToByteTests;
-
- ///
- /// Sets up the values for the tests
- ///
- [TestFixtureSetUp]
- public void Init()
- {
- this.doubleToByteTests = new Dictionary
- {
- { -10, 0x0 },
- { 1.5, 0x1 },
- { 25.7, 0x19 },
- { 1289047, 0xFF }
- };
- }
-
///
/// Tests the double to byte conversion
///
+ /// Double input
+ /// Expected result
[Test]
- public void TestDoubleToByte()
+ [TestCase(-10, 0x0)]
+ [TestCase(1.5, 0x1)]
+ [TestCase(25.7, 0x19)]
+ [TestCase(1289047, 0xFF)]
+ public void TestDoubleToByte(double input, byte expected)
{
- foreach (var item in this.doubleToByteTests)
- {
- var result = item.Key.ToByte();
- Assert.AreEqual(item.Value, result);
- }
+ byte result = input.ToByte();
+ Assert.AreEqual(expected, result);
}
}
}
\ No newline at end of file
diff --git a/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj b/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj
index 460e329b9..357f3b11d 100644
--- a/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj
+++ b/src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj
@@ -69,6 +69,10 @@
{3b5dd734-fb7a-487d-8ce6-55e7af9aea7e}
ImageProcessor
+
+ {2cf69699-959a-44dc-a281-4e2596c25043}
+ ImageProcessor.Plugins.WebP
+
diff --git a/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs b/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
index c41454563..db81f4533 100644
--- a/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
+++ b/src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
@@ -10,10 +10,14 @@
namespace ImageProcessor.Web.UnitTests
{
+ using System;
+ using System.Collections.Generic;
using System.Drawing;
using ImageProcessor.Imaging;
using ImageProcessor.Imaging.Filters;
using ImageProcessor.Imaging.Formats;
+ using ImageProcessor.Plugins.WebP.Imaging.Formats;
+
using NUnit.Framework;
///
@@ -25,52 +29,103 @@ namespace ImageProcessor.Web.UnitTests
///
/// The alpha regex unit test.
///
+ ///
+ /// The input string.
+ ///
+ ///
+ /// The expected result.
+ ///
[Test]
- public void TestAlphaRegex()
+ [TestCase("alpha=66", 66)]
+ [TestCase("alpha=-66", 66)]
+ [TestCase("alpha=101", 1)]
+ [TestCase("alpha=-101", 1)]
+ [TestCase("alpha=000053", 53)]
+ public void TestAlphaRegex(string input, int expected)
{
- const string Querystring = "alpha=56";
- const int Expected = 56;
-
Processors.Alpha alpha = new Processors.Alpha();
- alpha.MatchRegexIndex(Querystring);
+ alpha.MatchRegexIndex(input);
+ int result = alpha.Processor.DynamicParameter;
- int actual = alpha.Processor.DynamicParameter;
-
- Assert.AreEqual(Expected, actual);
+ Assert.AreEqual(expected, result);
}
///
- /// The brightness regex unit test.
+ /// The contrast regex unit test.
///
+ ///
+ /// The input string.
+ ///
+ ///
+ /// The expected result.
+ ///
[Test]
- public void TestBrightnessRegex()
+ [TestCase("brightness=56", 56)]
+ [TestCase("brightness=84", 84)]
+ [TestCase("brightness=66", 66)]
+ [TestCase("brightness=101", 1)]
+ [TestCase("brightness=00001", 1)]
+ [TestCase("brightness=-50", -50)]
+ [TestCase("brightness=0", 0)]
+ public void TestBrightnesstRegex(string input, int expected)
{
- const string Querystring = "brightness=56";
- const int Expected = 56;
-
Processors.Brightness brightness = new Processors.Brightness();
- brightness.MatchRegexIndex(Querystring);
-
- int actual = brightness.Processor.DynamicParameter;
+ brightness.MatchRegexIndex(input);
+ int result = brightness.Processor.DynamicParameter;
- Assert.AreEqual(Expected, actual);
+ Assert.AreEqual(expected, result);
}
///
/// The contrast regex unit test.
///
+ ///
+ /// The input string.
+ ///
+ ///
+ /// The expected result.
+ ///
[Test]
- public void TestContrastRegex()
+ [TestCase("contrast=56", 56)]
+ [TestCase("contrast=84", 84)]
+ [TestCase("contrast=66", 66)]
+ [TestCase("contrast=101", 1)]
+ [TestCase("contrast=00001", 1)]
+ [TestCase("contrast=-50", -50)]
+ [TestCase("contrast=0", 0)]
+ public void TestContrastRegex(string input, int expected)
{
- const string Querystring = "contrast=56";
- const int Expected = 56;
-
Processors.Contrast contrast = new Processors.Contrast();
- contrast.MatchRegexIndex(Querystring);
+ contrast.MatchRegexIndex(input);
+ int result = contrast.Processor.DynamicParameter;
- int actual = contrast.Processor.DynamicParameter;
+ Assert.AreEqual(expected, result);
+ }
- Assert.AreEqual(Expected, actual);
+ ///
+ /// The saturation regex unit test.
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ /// The expected result.
+ ///
+ [Test]
+ [TestCase("saturation=56", 56)]
+ [TestCase("saturation=84", 84)]
+ [TestCase("saturation=66", 66)]
+ [TestCase("saturation=101", 1)]
+ [TestCase("saturation=00001", 1)]
+ [TestCase("saturation=-50", -50)]
+ [TestCase("saturation=0", 0)]
+ public void TestSaturationRegex(string input, int expected)
+ {
+ Processors.Saturation saturation = new Processors.Saturation();
+ saturation.MatchRegexIndex(input);
+ int result = saturation.Processor.DynamicParameter;
+
+ Assert.AreEqual(expected, result);
}
///
@@ -93,52 +148,102 @@ namespace ImageProcessor.Web.UnitTests
/// The filter regex unit test.
///
[Test]
+
public void TestFilterRegex()
{
- // Should really write more for the other filters.
- const string Querystring = "filter=lomograph";
- IMatrixFilter expected = MatrixFilters.Lomograph;
+ Dictionary data = new Dictionary
+ {
+ {
+ "filter=lomograph", MatrixFilters.Lomograph
+ },
+ {
+ "filter=polaroid", MatrixFilters.Polaroid
+ },
+ {
+ "filter=comic", MatrixFilters.Comic
+ },
+ {
+ "filter=greyscale", MatrixFilters.GreyScale
+ },
+ {
+ "filter=blackwhite", MatrixFilters.BlackWhite
+ },
+ {
+ "filter=invert", MatrixFilters.Invert
+ },
+ {
+ "filter=gotham", MatrixFilters.Gotham
+ },
+ {
+ "filter=hisatch", MatrixFilters.HiSatch
+ },
+ {
+ "filter=losatch", MatrixFilters.LoSatch
+ },
+ {
+ "filter=sepia", MatrixFilters.Sepia
+ }
+ };
Processors.Filter filter = new Processors.Filter();
- filter.MatchRegexIndex(Querystring);
-
- IMatrixFilter actual = filter.Processor.DynamicParameter;
-
- Assert.AreEqual(expected, actual);
+ foreach (KeyValuePair item in data)
+ {
+ filter.MatchRegexIndex(item.Key);
+ IMatrixFilter result = filter.Processor.DynamicParameter;
+ Assert.AreEqual(item.Value, result);
+ }
}
///
/// The format regex unit test.
///
+ ///
+ /// The input querystring.
+ ///
+ ///
+ /// The expected type.
+ ///
[Test]
- public void TestFormatRegex()
+ [TestCase("format=bmp", typeof(BitmapFormat))]
+ [TestCase("format=png", typeof(PngFormat))]
+ [TestCase("format=png8", typeof(PngFormat))]
+ [TestCase("format=jpeg", typeof(JpegFormat))]
+ [TestCase("format=jpg", typeof(JpegFormat))]
+ [TestCase("format=gif", typeof(GifFormat))]
+ [TestCase("format=webp", typeof(WebPFormat))]
+ public void TestFormatRegex(string input, Type expected)
{
- const string Querystring = "format=gif";
- ISupportedImageFormat expected = new GifFormat();
-
Processors.Format format = new Processors.Format();
- format.MatchRegexIndex(Querystring);
+ format.MatchRegexIndex(input);
+ Type result = format.Processor.DynamicParameter.GetType();
- ISupportedImageFormat actual = format.Processor.DynamicParameter;
-
- Assert.AreEqual(expected, actual);
+ Assert.AreEqual(expected, result);
}
///
/// The quality regex unit test.
///
+ ///
+ /// The input.
+ ///
+ ///
+ /// The expected result.
+ ///
[Test]
- public void TestQualityRegex()
+ [TestCase("quality=56", 56)]
+ [TestCase("quality=84", 84)]
+ [TestCase("quality=66", 66)]
+ [TestCase("quality=101", 1)]
+ [TestCase("quality=00001", 1)]
+ [TestCase("quality=-50", 50)]
+ [TestCase("quality=0", 0)]
+ public void TestQualityRegex(string input, int expected)
{
- const string Querystring = "quality=56";
- const int Expected = 56;
-
Processors.Quality quality = new Processors.Quality();
- quality.MatchRegexIndex(Querystring);
+ quality.MatchRegexIndex(input);
+ int result = quality.Processor.DynamicParameter;
- int actual = quality.Processor.DynamicParameter;
-
- Assert.AreEqual(Expected, actual);
+ Assert.AreEqual(expected, result);
}
///
@@ -161,18 +266,25 @@ namespace ImageProcessor.Web.UnitTests
///
/// The rotate regex unit test.
///
+ ///
+ /// The input string.
+ ///
+ ///
+ /// The expected result.
+ ///
[Test]
- public void TestRotateRegex()
+ [TestCase("rotate=0", 0)]
+ [TestCase("rotate=270", 270)]
+ [TestCase("rotate=-270", 0)]
+ [TestCase("rotate=angle-28", 28)]
+ public void TestRotateRegex(string input, int expected)
{
- const string Querystring = "rotate=270";
- const int Expected = 270;
-
Processors.Rotate rotate = new Processors.Rotate();
- rotate.MatchRegexIndex(Querystring);
+ rotate.MatchRegexIndex(input);
- int actual = rotate.Processor.DynamicParameter;
+ int result = rotate.Processor.DynamicParameter;
- Assert.AreEqual(Expected, actual);
+ Assert.AreEqual(expected, result);
}
///
@@ -181,14 +293,26 @@ namespace ImageProcessor.Web.UnitTests
[Test]
public void TestRoundedCornersRegex()
{
- const string Querystring = "roundedcorners=30";
- RoundedCornerLayer expected = new RoundedCornerLayer(30, true, true, true, true);
- Processors.RoundedCorners roundedCorners = new Processors.RoundedCorners();
- roundedCorners.MatchRegexIndex(Querystring);
+ Dictionary data = new Dictionary
+ {
+ {
+ "roundedcorners=30", new RoundedCornerLayer(30, true, true, true, true)
+ },
+ {
+ "roundedcorners=radius-26|tl-true|tr-false|bl-true|br-false", new RoundedCornerLayer(26, true, false, true, false)
+ },
+ {
+ "roundedcorners=26,tl=true,tr=false,bl=true,br=false", new RoundedCornerLayer(26, true, false, true, false)
+ }
+ };
- RoundedCornerLayer actual = roundedCorners.Processor.DynamicParameter;
-
- Assert.AreEqual(expected, actual);
+ Processors.RoundedCorners roundedCorners = new Processors.RoundedCorners();
+ foreach (KeyValuePair item in data)
+ {
+ roundedCorners.MatchRegexIndex(item.Key);
+ RoundedCornerLayer result = roundedCorners.Processor.DynamicParameter;
+ Assert.AreEqual(item.Value, result);
+ }
}
///
@@ -197,20 +321,29 @@ namespace ImageProcessor.Web.UnitTests
[Test]
public void TestTintRegex()
{
- const string HexQuerystring = "tint=6aa6cc";
- const string RgbaQuerystring = "tint=106,166,204,255";
- Color expectedHex = ColorTranslator.FromHtml("#" + "6aa6cc");
- Color expectedRgba = Color.FromArgb(255, 106, 166, 204);
+ Dictionary data = new Dictionary
+ {
+ {
+ "tint=6aa6cc", ColorTranslator.FromHtml("#" + "6aa6cc")
+ },
+ {
+ "tint=106,166,204,255", Color.FromArgb(255, 106, 166, 204)
+ },
+ {
+ "tint=fff", Color.FromArgb(255, 255, 255, 255)
+ },
+ {
+ "tint=white", Color.White
+ }
+ };
Processors.Tint tint = new Processors.Tint();
- tint.MatchRegexIndex(HexQuerystring);
- Color actualHex = tint.Processor.DynamicParameter;
- Assert.AreEqual(expectedHex, actualHex);
-
- tint = new Processors.Tint();
- tint.MatchRegexIndex(RgbaQuerystring);
- Color actualRgba = tint.Processor.DynamicParameter;
- Assert.AreEqual(expectedRgba, actualRgba);
+ foreach (KeyValuePair item in data)
+ {
+ tint.MatchRegexIndex(item.Key);
+ Color result = tint.Processor.DynamicParameter;
+ Assert.AreEqual(item.Value, result);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs b/src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs
index 505d80d99..3e8362d08 100644
--- a/src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs
+++ b/src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs
@@ -11,8 +11,10 @@
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;
@@ -24,10 +26,15 @@ namespace ImageProcessor.Web.Helpers
///
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 = new Regex(@"(bgcolor|color|tint|vignette)(=|-)(\d+,\d+,\d+,\d+|([0-9a-fA-F]{3}){1,2})", RegexOptions.Compiled);
+ private static readonly Regex ColorRegex = BuildColorRegex();
///
/// The regular expression to search strings for angles.
@@ -37,7 +44,7 @@ namespace ImageProcessor.Web.Helpers
///
/// The regular expression to search strings for values between 1 and 100.
///
- private static readonly Regex In100RangeRegex = new Regex(@"(-?(?:100)|-?([1-9]?[0-9]))", RegexOptions.Compiled);
+ private static readonly Regex In100RangeRegex = new Regex(@"(-?(0*(?:[1-9][0-9]?|100)))", RegexOptions.Compiled);
///
/// The sharpen regex.
@@ -93,6 +100,11 @@ namespace ImageProcessor.Web.Helpers
{
string value = match.Value.Split(new[] { '=', '-' })[1];
+ if (KnownColors.ContainsKey(value))
+ {
+ return Color.FromKnownColor(KnownColors[value]);
+ }
+
if (value.Contains(","))
{
int[] split = value.ToPositiveIntegerArray();
@@ -224,5 +236,33 @@ namespace ImageProcessor.Web.Helpers
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);
+ }
}
}
diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
index 2fe0a275d..d7b15e7e1 100644
--- a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
+++ b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
@@ -43,6 +43,11 @@ namespace ImageProcessor.Web.HttpModules
///
private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE_054F217C-11CF-49FF-8D2F-698E8E6EB58F";
+ ///
+ /// The key for storing the file dependency of the current image.
+ ///
+ private const string CachedResponseFileDependency = "CACHED_IMAGE_DEPENDENCY_054F217C-11CF-49FF-8D2F-698E8E6EB58F";
+
///
/// The regular expression to search strings for.
///
@@ -215,15 +220,18 @@ namespace ImageProcessor.Web.HttpModules
HttpContext context = ((HttpApplication)sender).Context;
object responseTypeObject = context.Items[CachedResponseTypeKey];
+ object dependencyFileObject = context.Items[CachedResponseFileDependency];
- if (responseTypeObject != null)
+ if (responseTypeObject != null && dependencyFileObject != null)
{
string responseType = (string)responseTypeObject;
+ string dependencyFile = (string)dependencyFileObject;
// Set the headers
- this.SetHeaders(context, responseType);
+ this.SetHeaders(context, responseType, dependencyFile);
context.Items[CachedResponseTypeKey] = null;
+ context.Items[CachedResponseFileDependency] = null;
}
}
@@ -440,7 +448,15 @@ namespace ImageProcessor.Web.HttpModules
}
}
- string incomingEtag = context.Request.Headers["If-None-Match"];
+ // Image is from the cache so the mime-type will need to be set.
+ if (context.Items[CachedResponseTypeKey] == null)
+ {
+ context.Items[CachedResponseTypeKey] = ImageHelpers.GetExtension(cachedPath).Replace(".", "image/");
+ }
+
+ context.Items[CachedResponseFileDependency] = cachedPath;
+
+ string incomingEtag = context.Request.Headers["If" + "-None-Match"];
if (incomingEtag != null && !isNewOrUpdated)
{
@@ -449,8 +465,7 @@ namespace ImageProcessor.Web.HttpModules
context.Response.AddHeader("Content-Length", "0");
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
context.Response.SuppressContent = true;
- context.Response.AddFileDependency(context.Server.MapPath(virtualCachedPath));
- this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey]);
+ this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], cachedPath);
if (!isRemote)
{
@@ -482,18 +497,28 @@ namespace ImageProcessor.Web.HttpModules
/// the HttpContext object that provides
/// references to the intrinsic server objects
///
- /// The HTTP MIME type to to send.
- private void SetHeaders(HttpContext context, string responseType)
+ ///
+ /// The HTTP MIME type to to send.
+ ///
+ ///
+ /// The dependency path for the cache dependency.
+ ///
+ private void SetHeaders(HttpContext context, string responseType, string dependencyPath)
{
HttpResponse response = context.Response;
response.ContentType = responseType;
- response.AddHeader("Image-Served-By", "ImageProcessor.Web/" + AssemblyVersion);
+ if (response.Headers["Image-Served-By"] == null)
+ {
+ response.AddHeader("Image-Served-By", "ImageProcessor.Web/" + AssemblyVersion);
+ }
HttpCachePolicy cache = response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.VaryByHeaders["Accept-Encoding"] = true;
+
+ context.Response.AddFileDependency(dependencyPath);
cache.SetLastModifiedFromFileDependencies();
int maxDays = DiskCache.MaxFileCachedDuration;
diff --git a/src/ImageProcessor.Web/NET45/Processors/Format.cs b/src/ImageProcessor.Web/NET45/Processors/Format.cs
index b419f211f..7b57d7ddd 100644
--- a/src/ImageProcessor.Web/NET45/Processors/Format.cs
+++ b/src/ImageProcessor.Web/NET45/Processors/Format.cs
@@ -15,7 +15,6 @@ namespace ImageProcessor.Web.Processors
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
- using System.Web;
using ImageProcessor.Configuration;
using ImageProcessor.Imaging.Formats;
diff --git a/src/ImageProcessor.sln b/src/ImageProcessor.sln
index a12d17c68..8ad0ed4e9 100644
--- a/src/ImageProcessor.sln
+++ b/src/ImageProcessor.sln
@@ -36,6 +36,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web.UnitTest
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.UnitTests", "ImageProcessor.UnitTests\ImageProcessor.UnitTests.csproj", "{633B1C4C-4823-47BE-9A01-A665F3118C8C}"
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Any CPU = All|Any CPU
@@ -201,6 +203,21 @@ Global
{633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{633B1C4C-4823-47BE-9A01-A665F3118C8C}.Release|x86.ActiveCfg = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.All|Any CPU.ActiveCfg = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.All|Any CPU.Build.0 = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.All|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.All|Mixed Platforms.Build.0 = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.All|x86.ActiveCfg = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {2CF69699-959A-44DC-A281-4E2596C25043}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs b/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs
index 09b772455..4cffe51eb 100644
--- a/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs
+++ b/src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs
@@ -4,22 +4,25 @@
// Licensed under the Apache License, Version 2.0.
//
//
-// The image processor bootstrapper.
+// The ImageProcessor bootstrapper.
//
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Configuration
{
using System;
+ using System.Collections;
using System.Collections.Generic;
+ using System.IO;
using System.Linq;
+ using System.Reflection;
using ImageProcessor.Common.Exceptions;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging.Formats;
///
- /// The image processor bootstrapper.
+ /// The ImageProcessor bootstrapper.
///
public class ImageProcessorBootstrapper
{
@@ -35,8 +38,8 @@ namespace ImageProcessor.Configuration
///
private ImageProcessorBootstrapper()
{
- this.LoadSupportedImageFormats();
this.NativeBinaryFactory = new NativeBinaryFactory();
+ this.LoadSupportedImageFormats();
}
///
@@ -70,14 +73,36 @@ namespace ImageProcessor.Configuration
try
{
Type type = typeof(ISupportedImageFormat);
+
+ // Get any referenced but not used assemblies.
+ Assembly executingAssembly = Assembly.GetExecutingAssembly();
+ string targetBasePath = Path.GetDirectoryName(new Uri(executingAssembly.Location).LocalPath);
+
+ // ReSharper disable once AssignNullToNotNullAttribute
+ FileInfo[] files = new DirectoryInfo(targetBasePath).GetFiles("*.dll", SearchOption.AllDirectories);
+
+ HashSet found = new HashSet();
+ foreach (FileInfo fileInfo in files)
+ {
+ AssemblyName assemblyName = AssemblyName.GetAssemblyName(fileInfo.FullName);
+
+ if (!AppDomain.CurrentDomain.GetAssemblies()
+ .Any(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.GetName())))
+ {
+ // In a web app, this assembly will automatically be bound from the
+ // Asp.Net Temporary folder from where the site actually runs.
+ this.LoadReferencedAssemblies(found, Assembly.Load(assemblyName));
+ }
+ }
+
List availableTypes = AppDomain.CurrentDomain
.GetAssemblies()
- .SelectMany(s => s.GetLoadableTypes())
+ .SelectMany(a => a.GetLoadableTypes())
.Where(t => type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract)
.ToList();
this.SupportedImageFormats = availableTypes
- .Select(x => (Activator.CreateInstance(x) as ISupportedImageFormat)).ToList();
+ .Select(f => (Activator.CreateInstance(f) as ISupportedImageFormat)).ToList();
}
catch (Exception ex)
{
@@ -85,5 +110,49 @@ namespace ImageProcessor.Configuration
}
}
}
+
+ ///
+ /// Loads any referenced assemblies into the current application domain.
+ ///
+ ///
+ /// The collection containing the name of already found assemblies.
+ ///
+ ///
+ /// The assembly to load from.
+ ///
+ private void LoadReferencedAssemblies(HashSet found, Assembly assembly)
+ {
+ // Used to avoid duplicates
+ ArrayList results = new ArrayList();
+
+ // Resulting info
+ Stack stack = new Stack();
+
+ // Stack of names
+ // Store root assembly (level 0) directly into results list
+ stack.Push(assembly.ToString());
+
+ // Do a preorder, non-recursive traversal
+ while (stack.Count > 0)
+ {
+ string info = (string)stack.Pop();
+
+ // Get next assembly
+ if (!found.Contains(info))
+ {
+ found.Add(info);
+ results.Add(info);
+
+ // Store it to results ArrayList
+ Assembly child = Assembly.Load(info);
+ AssemblyName[] subchild = child.GetReferencedAssemblies();
+
+ for (int i = subchild.Length - 1; i >= 0; --i)
+ {
+ stack.Push(subchild[i].ToString());
+ }
+ }
+ }
+ }
}
}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index ad69d127b..ed1aa9c64 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -79,7 +79,6 @@
-
@@ -87,7 +86,6 @@
-
@@ -131,10 +129,6 @@
-
-
-
-
diff --git a/src/ImageProcessorConsole/ImageProcessorConsole.csproj b/src/ImageProcessorConsole/ImageProcessorConsole.csproj
index fba366b0c..1afd8ef0e 100644
--- a/src/ImageProcessorConsole/ImageProcessorConsole.csproj
+++ b/src/ImageProcessorConsole/ImageProcessorConsole.csproj
@@ -56,6 +56,10 @@
{3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}
ImageProcessor
+
+ {2cf69699-959a-44dc-a281-4e2596c25043}
+ ImageProcessor.Plugins.WebP
+
+
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Formats/NativeMethods.cs b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs
similarity index 96%
rename from src/ImageProcessor/Imaging/Formats/NativeMethods.cs
rename to src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs
index 0c42710b0..936b58256 100644
--- a/src/ImageProcessor/Imaging/Formats/NativeMethods.cs
+++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs
@@ -8,7 +8,7 @@
//
// --------------------------------------------------------------------------------------------------------------------
-namespace ImageProcessor.Imaging.Formats
+namespace ImageProcessor.Plugins.WebP.Imaging.Formats
{
using System;
using System.IO;
@@ -23,7 +23,7 @@ namespace ImageProcessor.Imaging.Formats
internal static class NativeMethods
{
///
- /// Whether the process is running in 64bit mode. Used for calling the correct dllimport method.
+ /// Whether the process is running in 64bit mode. Used for calling the correct method.
/// Clunky I know but I couldn't get dynamic methods to work.
///
private static readonly bool Is64Bit = Environment.Is64BitProcess;
@@ -34,7 +34,7 @@ namespace ImageProcessor.Imaging.Formats
static NativeMethods()
{
string folder = Is64Bit ? "x64" : "x86";
- string name = string.Format("ImageProcessor.Resources.Unmanaged.{0}.libwebp.dll", folder);
+ string name = string.Format("ImageProcessor.Plugins.WebP.Resources.Unmanaged.{0}.libwebp.dll", folder);
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
using (MemoryStream memoryStream = new MemoryStream())
diff --git a/src/ImageProcessor/Imaging/Formats/WebPFormat.cs b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs
similarity index 98%
rename from src/ImageProcessor/Imaging/Formats/WebPFormat.cs
rename to src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs
index 9f350c5c0..0bc2e2b7b 100644
--- a/src/ImageProcessor/Imaging/Formats/WebPFormat.cs
+++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs
@@ -10,7 +10,7 @@
//
// --------------------------------------------------------------------------------------------------------------------
-namespace ImageProcessor.Imaging.Formats
+namespace ImageProcessor.Plugins.WebP.Imaging.Formats
{
using System;
using System.Collections.Generic;
@@ -22,6 +22,7 @@ namespace ImageProcessor.Imaging.Formats
using System.Text;
using ImageProcessor.Common.Exceptions;
+ using ImageProcessor.Imaging.Formats;
///
/// Provides the necessary information to support webp images.
diff --git a/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..d9aa6f985
--- /dev/null
+++ b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ImageProcessor.Plugins.WebP")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("James South")]
+[assembly: AssemblyProduct("ImageProcessor.Plugins.WebP")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("bf160db5-2ea7-4c85-9b0e-f1ddf2595e37")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/ImageProcessor/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id
similarity index 100%
rename from src/ImageProcessor/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id
rename to src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id
diff --git a/src/ImageProcessor/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id b/src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id
similarity index 100%
rename from src/ImageProcessor/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id
rename to src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id
diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs b/src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs
index 02fc35575..1eae92d44 100644
--- a/src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs
+++ b/src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs
@@ -41,6 +41,11 @@ namespace Test_Website_NET45.Controllers
return View();
}
+ public ActionResult WebP()
+ {
+ return View();
+ }
+
public ActionResult External()
{
return this.View();
diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj b/src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj
index 96f09d69b..c2118914f 100644
--- a/src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj
+++ b/src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj
@@ -159,6 +159,10 @@
{3b5dd734-fb7a-487d-8ce6-55e7af9aea7e}
ImageProcessor
+
+ {2cf69699-959a-44dc-a281-4e2596c25043}
+ ImageProcessor.Plugins.WebP
+
@@ -191,6 +195,9 @@
+
+
+
10.0
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/WebP.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/WebP.cshtml
new file mode 100644
index 000000000..ff03d1240
--- /dev/null
+++ b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/WebP.cshtml
@@ -0,0 +1,100 @@
+@{
+ ViewBag.Title = "WebP";
+}
+
+
+ WebP
+
+
+
+
Resized
+

+
+
+
Cropped
+

+
+
+
+
+ Filter
+
+
+
blackwhite
+

+
+
+
comic
+

+
+
+
+
+
lomograph
+

+
+
+
greyscale
+

+
+
+
+
+
polaroid
+

+
+
+
sepia
+

+
+
+
+
+
gotham
+

+
+
+
hisatch
+

+
+
+
+
+
losatch
+

+
+
+
+
+
+
+
Watermark
+

+
+
+
Format
+

+
+
+
+
+
+
+
Rotate
+

+
+
+
Quality
+

+
+
+
+
+
+
+
Alpha
+

+
+
+
+
diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml
index 74af019a2..5f8255ea4 100644
--- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml
+++ b/src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml
@@ -29,6 +29,7 @@
@Html.ActionLink("Png8", "Png8")
@Html.ActionLink("Bmp", "Bmp")
@Html.ActionLink("Tiff", "Tiff")
+ @Html.ActionLink("WebP", "WebP")
@Html.ActionLink("External", "External")