Browse Source

Merge remote-tracking branch 'origin/dev' into V2

Former-commit-id: 97f38916cb9006e522143e03f8e49a94a27e6f83
pull/17/head
James South 12 years ago
parent
commit
d291881f50
  1. 36
      src/ImageProcessor.UnitTests/Extensions/DoubleExtensionsUnitTests.cs
  2. 4
      src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj
  3. 281
      src/ImageProcessor.Web.UnitTests/RegularExpressionUnitTests.cs
  4. 44
      src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs
  5. 41
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  6. 1
      src/ImageProcessor.Web/NET45/Processors/Format.cs
  7. 17
      src/ImageProcessor.sln
  8. 79
      src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs
  9. 6
      src/ImageProcessor/ImageProcessor.csproj
  10. 4
      src/ImageProcessorConsole/ImageProcessorConsole.csproj
  11. BIN
      src/ImageProcessorConsole/images/output/4.sm.webp
  12. BIN
      src/ImageProcessorConsole/images/output/test.webp
  13. 67
      src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/ImageProcessor.Plugins.WebP.csproj
  14. 6
      src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs
  15. 3
      src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs
  16. 36
      src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Properties/AssemblyInfo.cs
  17. 0
      src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id
  18. 0
      src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id
  19. 5
      src/TestWebsites/NET45/Test_Website_NET45/Controllers/HomeController.cs
  20. 7
      src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj
  21. 100
      src/TestWebsites/NET45/Test_Website_NET45/Views/Home/WebP.cshtml
  22. 1
      src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml

36
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
{
/// <summary>
/// Stores the values to test for the ToByte() extension method
/// </summary>
private Dictionary<double, byte> doubleToByteTests;
/// <summary>
/// Sets up the values for the tests
/// </summary>
[TestFixtureSetUp]
public void Init()
{
this.doubleToByteTests = new Dictionary<double, byte>
{
{ -10, 0x0 },
{ 1.5, 0x1 },
{ 25.7, 0x19 },
{ 1289047, 0xFF }
};
}
/// <summary>
/// Tests the double to byte conversion
/// </summary>
/// <param name="input">Double input</param>
/// <param name="expected">Expected result</param>
[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);
}
}
}

4
src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj

@ -69,6 +69,10 @@
<Project>{3b5dd734-fb7a-487d-8ce6-55e7af9aea7e}</Project>
<Name>ImageProcessor</Name>
</ProjectReference>
<ProjectReference Include="..\Plugins\ImageProcessor\ImageProcessor.Plugins.WebP\ImageProcessor.Plugins.WebP.csproj">
<Project>{2cf69699-959a-44dc-a281-4e2596c25043}</Project>
<Name>ImageProcessor.Plugins.WebP</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">

281
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;
/// <summary>
@ -25,52 +29,103 @@ namespace ImageProcessor.Web.UnitTests
/// <summary>
/// The alpha regex unit test.
/// </summary>
/// <param name="input">
/// The input string.
/// </param>
/// <param name="expected">
/// The expected result.
/// </param>
[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);
}
/// <summary>
/// The brightness regex unit test.
/// The contrast regex unit test.
/// </summary>
/// <param name="input">
/// The input string.
/// </param>
/// <param name="expected">
/// The expected result.
/// </param>
[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);
}
/// <summary>
/// The contrast regex unit test.
/// </summary>
/// <param name="input">
/// The input string.
/// </param>
/// <param name="expected">
/// The expected result.
/// </param>
[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);
/// <summary>
/// The saturation regex unit test.
/// </summary>
/// <param name="input">
/// The input string.
/// </param>
/// <param name="expected">
/// The expected result.
/// </param>
[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);
}
/// <summary>
@ -93,52 +148,102 @@ namespace ImageProcessor.Web.UnitTests
/// The filter regex unit test.
/// </summary>
[Test]
public void TestFilterRegex()
{
// Should really write more for the other filters.
const string Querystring = "filter=lomograph";
IMatrixFilter expected = MatrixFilters.Lomograph;
Dictionary<string, IMatrixFilter> data = new Dictionary<string, IMatrixFilter>
{
{
"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<string, IMatrixFilter> item in data)
{
filter.MatchRegexIndex(item.Key);
IMatrixFilter result = filter.Processor.DynamicParameter;
Assert.AreEqual(item.Value, result);
}
}
/// <summary>
/// The format regex unit test.
/// </summary>
/// <param name="input">
/// The input querystring.
/// </param>
/// <param name="expected">
/// The expected type.
/// </param>
[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);
}
/// <summary>
/// The quality regex unit test.
/// </summary>
/// <param name="input">
/// The input.
/// </param>
/// <param name="expected">
/// The expected result.
/// </param>
[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);
}
/// <summary>
@ -161,18 +266,25 @@ namespace ImageProcessor.Web.UnitTests
/// <summary>
/// The rotate regex unit test.
/// </summary>
/// <param name="input">
/// The input string.
/// </param>
/// <param name="expected">
/// The expected result.
/// </param>
[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);
}
/// <summary>
@ -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<string, RoundedCornerLayer> data = new Dictionary<string, RoundedCornerLayer>
{
{
"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<string, RoundedCornerLayer> item in data)
{
roundedCorners.MatchRegexIndex(item.Key);
RoundedCornerLayer result = roundedCorners.Processor.DynamicParameter;
Assert.AreEqual(item.Value, result);
}
}
/// <summary>
@ -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<string, Color> data = new Dictionary<string, Color>
{
{
"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<string, Color> item in data)
{
tint.MatchRegexIndex(item.Key);
Color result = tint.Processor.DynamicParameter;
Assert.AreEqual(item.Value, result);
}
}
}
}

44
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
/// </summary>
public static class CommonParameterParserUtility
{
/// <summary>
/// The collection of known colors.
/// </summary>
private static readonly Dictionary<string, KnownColor> KnownColors = new Dictionary<string, KnownColor>();
/// <summary>
/// The regular expression to search strings for colors.
/// </summary>
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();
/// <summary>
/// The regular expression to search strings for angles.
@ -37,7 +44,7 @@ namespace ImageProcessor.Web.Helpers
/// <summary>
/// The regular expression to search strings for values between 1 and 100.
/// </summary>
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);
/// <summary>
/// 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;
}
/// <summary>
/// Builds a regular expression for the three main colour types.
/// </summary>
/// <returns>
/// The <see cref="Regex"/> to match colors.
/// </returns>
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);
}
}
}

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

@ -43,6 +43,11 @@ namespace ImageProcessor.Web.HttpModules
/// </summary>
private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE_054F217C-11CF-49FF-8D2F-698E8E6EB58F";
/// <summary>
/// The key for storing the file dependency of the current image.
/// </summary>
private const string CachedResponseFileDependency = "CACHED_IMAGE_DEPENDENCY_054F217C-11CF-49FF-8D2F-698E8E6EB58F";
/// <summary>
/// The regular expression to search strings for.
/// </summary>
@ -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 <see cref="T:System.Web.HttpContext">HttpContext</see> object that provides
/// references to the intrinsic server objects
/// </param>
/// <param name="responseType">The HTTP MIME type to to send.</param>
private void SetHeaders(HttpContext context, string responseType)
/// <param name="responseType">
/// The HTTP MIME type to to send.
/// </param>
/// <param name="dependencyPath">
/// The dependency path for the cache dependency.
/// </param>
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;

1
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;

17
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

79
src/ImageProcessor/Configuration/ImageProcessorBootstrapper.cs

@ -4,22 +4,25 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The image processor bootstrapper.
// The ImageProcessor bootstrapper.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
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;
/// <summary>
/// The image processor bootstrapper.
/// The ImageProcessor bootstrapper.
/// </summary>
public class ImageProcessorBootstrapper
{
@ -35,8 +38,8 @@ namespace ImageProcessor.Configuration
/// </summary>
private ImageProcessorBootstrapper()
{
this.LoadSupportedImageFormats();
this.NativeBinaryFactory = new NativeBinaryFactory();
this.LoadSupportedImageFormats();
}
/// <summary>
@ -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<string> found = new HashSet<string>();
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<Type> 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
}
}
}
/// <summary>
/// Loads any referenced assemblies into the current application domain.
/// </summary>
/// <param name="found">
/// The collection containing the name of already found assemblies.
/// </param>
/// <param name="assembly">
/// The assembly to load from.
/// </param>
private void LoadReferencedAssemblies(HashSet<string> 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());
}
}
}
}
}
}

6
src/ImageProcessor/ImageProcessor.csproj

@ -79,7 +79,6 @@
<Compile Include="Imaging\Filters\MatrixFilterBase.cs" />
<Compile Include="Imaging\Filters\MatrixFilters.cs" />
<Compile Include="Imaging\Formats\BitmapFormat.cs" />
<Compile Include="Imaging\Formats\NativeMethods.cs" />
<Compile Include="Imaging\Formats\TiffFormat.cs" />
<Compile Include="Imaging\Formats\PngFormat.cs" />
<Compile Include="Imaging\Formats\GifFormat.cs" />
@ -87,7 +86,6 @@
<Compile Include="Imaging\Formats\FormatUtilities.cs" />
<Compile Include="Imaging\Formats\FormatBase.cs" />
<Compile Include="Imaging\Formats\ISupportedImageFormat.cs" />
<Compile Include="Imaging\Formats\WebPFormat.cs" />
<Compile Include="Imaging\GaussianLayer.cs" />
<Compile Include="Imaging\Formats\GifEncoder.cs" />
<Compile Include="Imaging\Formats\GifFrame.cs" />
@ -131,10 +129,6 @@
<Compile Include="Processors\Watermark.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Unmanaged\x64\libwebp.dll" />
<EmbeddedResource Include="Resources\Unmanaged\x86\libwebp.dll" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />

4
src/ImageProcessorConsole/ImageProcessorConsole.csproj

@ -56,6 +56,10 @@
<Project>{3B5DD734-FB7A-487D-8CE6-55E7AF9AEA7E}</Project>
<Name>ImageProcessor</Name>
</ProjectReference>
<ProjectReference Include="..\Plugins\ImageProcessor\ImageProcessor.Plugins.WebP\ImageProcessor.Plugins.WebP.csproj">
<Project>{2cf69699-959a-44dc-a281-4e2596c25043}</Project>
<Name>ImageProcessor.Plugins.WebP</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

BIN
src/ImageProcessorConsole/images/output/4.sm.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
src/ImageProcessorConsole/images/output/test.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

67
src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/ImageProcessor.Plugins.WebP.csproj

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2CF69699-959A-44DC-A281-4E2596C25043}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ImageProcessor.Plugins.WebP</RootNamespace>
<AssemblyName>ImageProcessor.Plugins.WebP</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Imaging\Formats\WebPFormat.cs" />
<Compile Include="Imaging\Formats\NativeMethods.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="Resources\Unmanaged\x64\libwebp.dll" />
<EmbeddedResource Include="Resources\Unmanaged\x86\libwebp.dll" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\ImageProcessor\ImageProcessor.csproj">
<Project>{3b5dd734-fb7a-487d-8ce6-55e7af9aea7e}</Project>
<Name>ImageProcessor</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

6
src/ImageProcessor/Imaging/Formats/NativeMethods.cs → src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/NativeMethods.cs

@ -8,7 +8,7 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
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
{
/// <summary>
/// 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.
/// </summary>
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())

3
src/ImageProcessor/Imaging/Formats/WebPFormat.cs → src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Imaging/Formats/WebPFormat.cs

@ -10,7 +10,7 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
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;
/// <summary>
/// Provides the necessary information to support webp images.

36
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")]

0
src/ImageProcessor/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id → src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x64/libwebp.dll.REMOVED.git-id

0
src/ImageProcessor/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id → src/Plugins/ImageProcessor/ImageProcessor.Plugins.WebP/Resources/Unmanaged/x86/libwebp.dll.REMOVED.git-id

5
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();

7
src/TestWebsites/NET45/Test_Website_NET45/Test_Website_MVC_NET45.csproj

@ -159,6 +159,10 @@
<Project>{3b5dd734-fb7a-487d-8ce6-55e7af9aea7e}</Project>
<Name>ImageProcessor</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Plugins\ImageProcessor\ImageProcessor.Plugins.WebP\ImageProcessor.Plugins.WebP.csproj">
<Project>{2cf69699-959a-44dc-a281-4e2596c25043}</Project>
<Name>ImageProcessor.Plugins.WebP</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="config\imageprocessor\cache.config">
@ -191,6 +195,9 @@
<ItemGroup>
<Content Include="Views\Home\External.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Home\WebP.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

100
src/TestWebsites/NET45/Test_Website_NET45/Views/Home/WebP.cshtml

@ -0,0 +1,100 @@
@{
ViewBag.Title = "WebP";
}
<article>
<h1>WebP</h1>
<section>
<div class="row">
<div class="col-s-6">
<h2>Resized</h2>
<img src="/images/Penguins.bmp?format=webp&width=300" />
</div>
<div class="col-s-6">
<h2>Cropped </h2>
<img src="/images/Penguins.bmp?format=webp&crop=0-0-300-225" />
</div>
</div>
</section>
<section>
<h2>Filter</h2>
<div class="row">
<div class="col-s-6">
<h3>blackwhite</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=blackwhite" />
</div>
<div class="col-s-6">
<h3>comic</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=comic" />
</div>
</div>
<div class="row">
<div class="col-s-6">
<h3>lomograph</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=lomograph" />
</div>
<div class="col-s-6">
<h3>greyscale</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=greyscale" />
</div>
</div>
<div class="row">
<div class="col-s-6">
<h3>polaroid</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=polaroid" />
</div>
<div class="col-s-6">
<h3>sepia</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=sepia" />
</div>
</div>
<div class="row">
<div class="col-s-6">
<h3>gotham</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=gotham" />
</div>
<div class="col-s-6">
<h3>hisatch</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=hisatch" />
</div>
</div>
<div class="row">
<div class="col-s-6">
<h3>losatch</h3>
<img src="/images/Penguins.bmp?format=webp&width=300&filter=losatch" />
</div>
</div>
</section>
<section>
<div class="row">
<div class="col-s-6">
<h2>Watermark</h2>
<img src="/images/Penguins.bmp?format=webp&width=300&watermark=text-test|color-fff|size-48|style-italic|opacity-100|position-100-100|shadow-true|font-arial" />
</div>
<div class="col-s-6">
<h2>Format</h2>
<img src="/images/Penguins.bmp?format=webp&width=300" />
</div>
</div>
</section>
<section>
<div class="row">
<div class="col-s-6">
<h2>Rotate</h2>
<img src="/images/Penguins.bmp?format=webp&width=300&rotate=angle-54|bgcolor-fff" />
</div>
<div class="col-s-6">
<h2>Quality</h2>
<img src="/images/Penguins.bmp?format=webp&width=300&quality=5" />
</div>
</div>
</section>
<section>
<div class="row">
<div class="col-s-6">
<h2>Alpha</h2>
<img src="/images/Penguins.bmp?format=webp&width=300&alpha=50" />
</div>
</div>
</section>
</article>

1
src/TestWebsites/NET45/Test_Website_NET45/Views/Shared/_Layout.cshtml

@ -29,6 +29,7 @@
<li>@Html.ActionLink("Png8", "Png8")</li>
<li>@Html.ActionLink("Bmp", "Bmp")</li>
<li>@Html.ActionLink("Tiff", "Tiff")</li>
<li>@Html.ActionLink("WebP", "WebP")</li>
<li>@Html.ActionLink("External", "External")</li>
</ul>
</nav>

Loading…
Cancel
Save