Browse Source

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

Conflicts:
	src/ImageProcessor/Imaging/Formats/GifEncoder.cs
	src/ImageProcessorConsole/Program.cs
	src/ImageProcessorConsole/images/output/nLpfllv.gif

Former-commit-id: 205a39fec955c7e11a238afa2dfa3eb1a5393ae4
pull/17/head
James South 12 years ago
parent
commit
a0420047be
  1. 4
      build/NuSpecs/ImageProcessor.nuspec
  2. 2
      build/content/ImageProcessor.Web/web.config.transform
  3. 1
      src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj
  4. 160
      src/ImageProcessor.Web.UnitTests/Extensions/StringExtensionsUnitTests.cs
  5. 1
      src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj
  6. 6
      src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj
  7. 3
      src/ImageProcessor.Web/NET45/Caching/DiskCache.cs
  8. 5
      src/ImageProcessor.Web/NET45/Configuration/ImageCacheSection.cs
  9. 29
      src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs
  10. 46
      src/ImageProcessor.Web/NET45/Extensions/StringExtensions.cs
  11. 1
      src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs
  12. 2
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  13. 159
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessorNativeBinaryModule.cs
  14. 2
      src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
  15. 2
      src/ImageProcessor.Web/NET45/Processors/Crop.cs
  16. 2
      src/ImageProcessor.Web/NET45/Processors/Resize.cs
  17. 2
      src/ImageProcessor.Web/NET45/Processors/Watermark.cs
  18. 1
      src/ImageProcessor.sln.DotSettings
  19. 13
      src/ImageProcessor/Common/Extensions/AssemblyExtensions.cs
  20. 6
      src/ImageProcessor/ImageProcessor.csproj
  21. 22
      src/ImageProcessor/Imaging/Formats/GifEncoder.cs
  22. 133
      src/ImageProcessor/Imaging/Formats/NativeMethods.cs
  23. 60
      src/ImageProcessor/Imaging/Formats/WebPFormat.cs
  24. 1
      src/ImageProcessor/Settings.StyleCop
  25. 0
      src/ImageProcessor/x64/imageprocessor.libwebp.dll.REMOVED.git-id
  26. 0
      src/ImageProcessor/x86/imageprocessor.libwebp.dll.REMOVED.git-id
  27. BIN
      src/ImageProcessorConsole/images/output/rotate.jpg
  28. 4
      src/TestWebsites/NET45/Test_Website_NET45/Web.config

4
build/NuSpecs/ImageProcessor.nuspec

@ -25,8 +25,8 @@ Feedback is always welcome.</description>
</metadata>
<files>
<file src="..\_BuildOutput\ImageProcessor\lib\ImageProcessor.dll" target="lib\ImageProcessor.dll" />
<file src="..\_BuildOutput\ImageProcessor\lib\libwebp32.dll" target="build\native\lib\libwebp32.dll" />
<file src="..\_BuildOutput\ImageProcessor\lib\libwebp64.dll" target="build\native\lib\libwebp64.dll" />
<file src="..\_BuildOutput\ImageProcessor\lib\x86\imageprocessor.libwebp.dll" target="build\native\lib\x86\imageprocessor.libwebp.dll" />
<file src="..\_BuildOutput\ImageProcessor\lib\x64\imageprocessor.libwebp.dll" target="build\native\lib\x64\imageprocessor.libwebp.dll" />
<file src="..\content\ImageProcessor\imageprocessor.targets" target="build\imageprocessor.targets" />
</files>
</package>

2
build/content/ImageProcessor.Web/web.config.transform

@ -3,6 +3,7 @@
<system.web>
<httpModules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
<add name="ImageProcessorNativeBinaryModule" type="ImageProcessor.Web.HttpModules.ImageProcessorNativeBinaryModule, ImageProcessor.Web"/>
</httpModules>
</system.web>
<system.webServer>
@ -13,6 +14,7 @@
</staticContent>
<modules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
<add name="ImageProcessorNativeBinaryModule" type="ImageProcessor.Web.HttpModules.ImageProcessorNativeBinaryModule, ImageProcessor.Web"/>
</modules>
</system.webServer>
</configuration>

1
src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj

@ -133,4 +133,5 @@
<ItemGroup>
<Folder Include="Extensions\" />
</ItemGroup>
<ItemGroup />
</Project>

160
src/ImageProcessor.Web.UnitTests/Extensions/StringExtensionsUnitTests.cs

@ -0,0 +1,160 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StringExtensionsUnitTests.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Test harness for the string extensions
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.UnitTests.Extensions
{
using System;
using System.Collections.Generic;
using ImageProcessor.Web.Extensions;
using NUnit.Framework;
/// <summary>
/// Test harness for the string extensions
/// </summary>
[TestFixture]
public class StringExtensionsUnitTests
{
/// <summary>
/// Tests the passing to an integer array
/// </summary>
[Test]
public void TestToIntegerArray()
{
Dictionary<string, int[]> data = new Dictionary<string, int[]>
{
{
"123-456,78-90",
new[] { 123, 456, 78, 90 }
},
{
"87390174,741897498,74816,748297,57355",
new[]
{
87390174, 741897498, 74816,
748297, 57355
}
},
{ "1-2-3", new[] { 1, 2, 3 } }
};
foreach (KeyValuePair<string, int[]> item in data)
{
int[] result = item.Key.ToPositiveIntegerArray();
Assert.AreEqual(item.Value, result);
}
}
/// <summary>
/// Tests the passing to an float array
/// </summary>
[Test]
public void TestToFloatArray()
{
Dictionary<string, float[]> data = new Dictionary<string, float[]>
{
{
"12.3-4.56,78-9.0",
new[] { 12.3F, 4.56F, 78, 9 }
},
{
"87390.174,7.41897498,748.16,748297,5.7355",
new[]
{
87390.174F, 7.41897498F,
748.16F, 748297, 5.7355F
}
},
{ "1-2-3", new float[] { 1, 2, 3 } }
};
foreach (KeyValuePair<string, float[]> item in data)
{
float[] result = item.Key.ToPositiveFloatArray();
Assert.AreEqual(item.Value, result);
}
}
/// <summary>
/// Tests the MD5 fingerprint
/// </summary>
/// <param name="input">The input value</param>
/// <param name="expected">The expected output of the hash</param>
[Test]
[TestCase("test input", "2e7f7a62eabf0993239ca17c78c464d9")]
[TestCase("lorem ipsum dolor", "96ee002fee25e8b675a477c9750fa360")]
[TestCase("LoReM IpSuM DoLoR", "41e201da794c7fbdb8ce5526a71c8c83")]
[TestCase("1234567890", "e15e31c3d8898c92ab172a4311be9e84")]
public void TestToMd5Fingerprint(string input, string expected)
{
string result = input.ToMD5Fingerprint();
bool comparison = result.Equals(expected, StringComparison.InvariantCultureIgnoreCase);
Assert.True(comparison);
}
/// <summary>
/// Tests the SHA-1 fingerprint
/// </summary>
/// <param name="input">The input value</param>
/// <param name="expected">The expected output of the hash</param>
[Test]
[TestCase("test input", "49883b34e5a0f48224dd6230f471e9dc1bdbeaf5")]
[TestCase("lorem ipsum dolor", "75899ad8827a32493928903aecd6e931bf36f967")]
[TestCase("LoReM IpSuM DoLoR", "2f44519afae72fc0837b72c6b53cb11338a1f916")]
[TestCase("1234567890", "01b307acba4f54f55aafc33bb06bbbf6ca803e9a")]
public void TestToSHA1Fingerprint(string input, string expected)
{
string result = input.ToSHA1Fingerprint();
bool comparison = result.Equals(expected, StringComparison.InvariantCultureIgnoreCase);
Assert.True(comparison);
}
/// <summary>
/// Tests if the value is a valid URI path name. I.E the path part of a uri.
/// </summary>
/// <param name="input">The value to test</param>
/// <param name="expected">Whether the value is correct</param>
/// <remarks>
/// The full RFC3986 does not seem to pass the test with the square brackets
/// ':' is failing for some reason in VS but not elsewhere. Could be a build issue.
/// </remarks>
[Test]
[TestCase("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", true)]
[TestCase("-", true)]
[TestCase(".", true)]
[TestCase("_", true)]
[TestCase("~", true)]
[TestCase(":", true)]
[TestCase("/", true)]
[TestCase("?", true)]
[TestCase("#", false)]
[TestCase("[", false)]
[TestCase("]", false)]
[TestCase("@", true)]
[TestCase("!", true)]
[TestCase("$", true)]
[TestCase("&", true)]
[TestCase("'", true)]
[TestCase("(", true)]
[TestCase(")", true)]
[TestCase("*", true)]
[TestCase("+", true)]
[TestCase(",", true)]
[TestCase(";", true)]
[TestCase("=", true)]
[TestCase("lorem ipsum", false)]
[TestCase("é", false)]
public void TestIsValidUriPathName(string input, bool expected)
{
bool result = input.IsValidVirtualPathName();
Assert.AreEqual(expected, result);
}
}
}

1
src/ImageProcessor.Web.UnitTests/ImageProcessor.Web.UnitTests.csproj

@ -53,6 +53,7 @@
<Otherwise />
</Choose>
<ItemGroup>
<Compile Include="Extensions\StringExtensionsUnitTests.cs" />
<Compile Include="RegularExpressionUnitTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

6
src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj

@ -98,6 +98,9 @@
<Compile Include="..\NET45\Extensions\DirectoryInfoExtensions.cs">
<Link>DirectoryInfoExtensions.cs</Link>
</Compile>
<Compile Include="..\NET45\Extensions\StringExtensions.cs">
<Link>StringExtensions.cs</Link>
</Compile>
<Compile Include="..\NET45\Helpers\CommonParameterParserUtility.cs">
<Link>CommonParameterParserUtility.cs</Link>
</Compile>
@ -113,6 +116,9 @@
</Compile>
<Compile Include="..\NET45\Helpers\TaskHelpers.cs" />
<Compile Include="..\NET45\HttpModules\ImageProcessingModule.cs" />
<Compile Include="..\NET45\HttpModules\ImageProcessorNativeBinaryModule.cs">
<Link>ImageProcessorNativeBinaryModule.cs</Link>
</Compile>
<Compile Include="..\NET45\ImageFactoryExtensions.cs" />
<Compile Include="..\NET45\Processors\Alpha.cs">
<Link>Alpha.cs</Link>

3
src/ImageProcessor.Web/NET45/Caching/DiskCache.cs

@ -20,7 +20,6 @@ namespace ImageProcessor.Web.Caching
using System.Web;
using System.Web.Hosting;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Web.Configuration;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
@ -245,7 +244,7 @@ namespace ImageProcessor.Web.Caching
fileInfo.Delete();
count -= 1;
}
// ReSharper disable once EmptyGeneralCatchClause
// ReSharper disable once EmptyGeneralCatchClause
catch
{
// Do nothing; skip to the next file.

5
src/ImageProcessor.Web/NET45/Configuration/ImageCacheSection.cs

@ -10,16 +10,13 @@
namespace ImageProcessor.Web.Configuration
{
#region Using
using System.Configuration;
using System.IO;
using System.Xml;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
#endregion
/// <summary>
/// Represents an image cache section within a configuration file.
/// </summary>

29
src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs

@ -23,6 +23,7 @@ namespace ImageProcessor.Web.Configuration
using ImageProcessor.Common.Extensions;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
using ImageProcessor.Web.HttpModules;
using ImageProcessor.Web.Processors;
/// <summary>
@ -370,30 +371,14 @@ namespace ImageProcessor.Web.Configuration
/// </summary>
private void EnsureNativeBinariesLoaded()
{
string binary = Is64Bit ? "libwebp64.dll" : "libwebp32.dll";
string sourcePath = HttpContext.Current.Server.MapPath("~/bin");
string targetPath = new Uri(Assembly.GetExecutingAssembly().Location).LocalPath;
IntPtr pointer = IntPtr.Zero;
// Load the correct method from the native binary module.
// We do it here as on init will cause an UnauthorizedAccessException.
HttpModuleCollection modules = HttpContext.Current.ApplicationInstance.Modules;
ImageProcessorNativeBinaryModule nativeBinaryModule = modules.Get("ImageProcessorNativeBinaryModule") as ImageProcessorNativeBinaryModule;
// Shadow copy the native binaries.
sourcePath = Path.Combine(sourcePath, binary);
targetPath = Path.GetFullPath(Path.Combine(targetPath, "..\\" + binary));
File.Copy(sourcePath, targetPath, true);
try
{
// Load the binary into memory.
pointer = NativeMethods.LoadLibrary(targetPath);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
if (pointer == IntPtr.Zero)
if (nativeBinaryModule != null)
{
throw new ApplicationException("Cannot open " + binary);
nativeBinaryModule.LoadNativeBinaries();
}
}
#endregion

46
src/ImageProcessor/Common/Extensions/StringExtensions.cs → src/ImageProcessor.Web/NET45/Extensions/StringExtensions.cs

@ -8,7 +8,7 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Common.Extensions
namespace ImageProcessor.Web.Extensions
{
using System;
using System.Globalization;
@ -64,50 +64,8 @@ namespace ImageProcessor.Common.Extensions
.ToString().ToLowerInvariant();
}
}
/// <summary>
/// Creates an SHA256 fingerprint of the String.
/// </summary>
/// <param name="expression">The <see cref="T:System.String">String</see> instance that this method extends.</param>
/// <returns>An SHA256 fingerprint of the String.</returns>
public static string ToSHA256Fingerprint(this string expression)
{
byte[] bytes = Encoding.ASCII.GetBytes(expression.ToCharArray());
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
byte[] hash = sha256.ComputeHash(bytes);
// Concatenate the hash bytes into one long String.
return hash.Aggregate(
new StringBuilder(64),
(sb, b) => sb.Append(b.ToString("X2", CultureInfo.InvariantCulture)))
.ToString().ToLowerInvariant();
}
}
/// <summary>
/// Creates an SHA512 fingerprint of the String.
/// </summary>
/// <param name="expression">The <see cref="T:System.String">String</see> instance that this method extends.</param>
/// <returns>An SHA256 fingerprint of the String.</returns>
public static string ToSHA512Fingerprint(this string expression)
{
byte[] bytes = Encoding.ASCII.GetBytes(expression.ToCharArray());
using (SHA512CryptoServiceProvider sha512 = new SHA512CryptoServiceProvider())
{
byte[] hash = sha512.ComputeHash(bytes);
// Concatenate the hash bytes into one long String.
return hash.Aggregate(
new StringBuilder(70),
(sb, b) => sb.Append(b.ToString("X2", CultureInfo.InvariantCulture)))
.ToString().ToLowerInvariant();
}
}
#endregion
#region Numbers
/// <summary>
/// Creates an array of integers scraped from the String.

1
src/ImageProcessor.Web/NET45/Helpers/CommonParameterParserUtility.cs

@ -17,6 +17,7 @@ namespace ImageProcessor.Web.Helpers
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Web.Extensions;
/// <summary>
/// Encapsulates methods to correctly parse querystring parameters.

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

@ -29,9 +29,9 @@ namespace ImageProcessor.Web.HttpModules
using System.Web.Hosting;
using System.Web.Security;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Web.Caching;
using ImageProcessor.Web.Configuration;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
#endregion

159
src/ImageProcessor.Web/NET45/HttpModules/ImageProcessorNativeBinaryModule.cs

@ -0,0 +1,159 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageProcessorNativeBinaryModule.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The image processing native binary module.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.HttpModules
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using ImageProcessor.Web.Helpers;
/// <summary>
/// Controls the loading and unloading of any native binaries required by ImageProcessor.Web.
/// </summary>
public sealed class ImageProcessorNativeBinaryModule : IHttpModule
{
/// <summary>
/// Whether the process is running in 64bit mode. Used for calling the correct dllimport method.
/// </summary>
private static readonly bool Is64Bit = Environment.Is64BitProcess;
/// <summary>
/// The object to lock against.
/// </summary>
private static readonly object SyncRoot = new object();
/// <summary>
/// The native binaries.
/// </summary>
private static readonly List<IntPtr> NativeBinaries = new List<IntPtr>();
/// <summary>
/// A value indicating whether this instance of the given entity has been disposed.
/// </summary>
/// <value><see langword="true"/> if this instance has been disposed; otherwise, <see langword="false"/>.</value>
/// <remarks>
/// If the entity is disposed, it must not be disposed a second
/// time. The isDisposed field is set the first time the entity
/// is disposed. If the isDisposed field is true, then the Dispose()
/// method will not dispose again. This help not to prolong the entity's
/// life in the Garbage Collector.
/// </remarks>
private bool isDisposed;
/// <summary>
/// Disposes of the resources (other than memory) used by the module that implements
/// <see cref="T:System.Web.IHttpModule" />.
/// </summary>
public void Dispose()
{
if (this.isDisposed)
{
return;
}
// Call the appropriate methods to clean up
// unmanaged resources here.
lock (SyncRoot)
{
this.FreeNativeBinaries();
}
// Note disposing is done.
this.isDisposed = true;
}
/// <summary>
/// Initializes a module and prepares it to handle requests.
/// </summary>
/// <param name="context">An <see cref="T:System.Web.HttpApplication" /> that provides access to
/// the methods, properties, and events common to all application objects within an ASP.NET application</param>
public void Init(HttpApplication context)
{
}
/// <summary>
/// Loads any native ImageProcessor binaries.
/// </summary>
public void LoadNativeBinaries()
{
lock (SyncRoot)
{
this.RegisterNativeBinaries();
}
}
/// <summary>
/// Registers any native binaries.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown when a native binary cannot be loaded.
/// </exception>
private void RegisterNativeBinaries()
{
if (NativeBinaries.Any())
{
return;
}
string folder = Is64Bit ? "x64" : "x86";
string sourcePath = HttpContext.Current.Server.MapPath("~/bin/" + folder);
string targetBasePath = new Uri(Assembly.GetExecutingAssembly().Location).LocalPath;
DirectoryInfo directoryInfo = new DirectoryInfo(sourcePath);
if (directoryInfo.Exists)
{
foreach (FileInfo fileInfo in directoryInfo.EnumerateFiles("*.dll"))
{
if (fileInfo.Name.ToUpperInvariant().StartsWith("IMAGEPROCESSOR"))
{
IntPtr pointer;
string targetPath = Path.GetFullPath(Path.Combine(targetBasePath, "..\\" + folder + "\\" + fileInfo.Name));
File.Copy(sourcePath, targetPath, true);
try
{
// Load the binary into memory.
pointer = NativeMethods.LoadLibrary(targetPath);
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message);
}
if (pointer == IntPtr.Zero)
{
throw new ApplicationException("Cannot load " + fileInfo.Name);
}
NativeBinaries.Add(pointer);
}
}
}
}
/// <summary>
/// Frees the reference to the native binaries.
/// </summary>
private void FreeNativeBinaries()
{
foreach (IntPtr nativeBinary in NativeBinaries)
{
// According to http://stackoverflow.com/a/2445558/427899 you need to call this twice.
NativeMethods.FreeLibrary(nativeBinary);
NativeMethods.FreeLibrary(nativeBinary);
}
}
}
}

2
src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj

@ -54,6 +54,7 @@
<Compile Include="Configuration\ImageProcessorConfiguration.cs" />
<Compile Include="Configuration\ImageSecuritySection.cs" />
<Compile Include="Extensions\DirectoryInfoExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Helpers\CommonParameterParserUtility.cs" />
<Compile Include="Helpers\NativeMethods.cs" />
<Compile Include="Helpers\ResourceHelpers.cs" />
@ -61,6 +62,7 @@
<Compile Include="Helpers\RemoteFile.cs" />
<Compile Include="Helpers\TaskHelpers.cs" />
<Compile Include="HttpModules\ImageProcessingModule.cs" />
<Compile Include="HttpModules\ImageProcessorNativeBinaryModule.cs" />
<Compile Include="ImageFactoryExtensions.cs" />
<Compile Include="Processors\Alpha.cs" />
<Compile Include="Processors\AutoRotate.cs" />

2
src/ImageProcessor.Web/NET45/Processors/Crop.cs

@ -13,9 +13,9 @@ namespace ImageProcessor.Web.Processors
using System.Text;
using System.Text.RegularExpressions;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Processors;
using ImageProcessor.Web.Extensions;
/// <summary>
/// Crops an image to the given directions.

2
src/ImageProcessor.Web/NET45/Processors/Resize.cs

@ -17,9 +17,9 @@ namespace ImageProcessor.Web.Processors
using System.Text;
using System.Text.RegularExpressions;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Processors;
using ImageProcessor.Web.Extensions;
/// <summary>
/// Resizes an image to the given dimensions.

2
src/ImageProcessor.Web/NET45/Processors/Watermark.cs

@ -15,9 +15,9 @@ namespace ImageProcessor.Web.Processors
using System.Linq;
using System.Text.RegularExpressions;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Processors;
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
/// <summary>

1
src/ImageProcessor.sln.DotSettings

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BGRA/@EntryIndexedValue">BGRA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BPP/@EntryIndexedValue">BPP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DT/@EntryIndexedValue">DT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FPX/@EntryIndexedValue">FPX</s:String>

13
src/ImageProcessor/Common/Extensions/AssemblyExtensions.cs

@ -1,4 +1,13 @@

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AssemblyExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates a series of time saving extension methods to the <see cref="T:System.Reflection.Assembly" /> class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Common.Extensions
{
using System;
@ -38,4 +47,4 @@ namespace ImageProcessor.Common.Extensions
}
}
}
}
}

6
src/ImageProcessor/ImageProcessor.csproj

@ -66,7 +66,6 @@
<Compile Include="Common\Extensions\DoubleExtensions.cs" />
<Compile Include="Imaging\Formats\GifInfo.cs" />
<Compile Include="Common\Extensions\IntegerExtensions.cs" />
<Compile Include="Common\Extensions\StringExtensions.cs" />
<Compile Include="Common\Exceptions\ImageFormatException.cs" />
<Compile Include="ImageFactory.cs" />
<Compile Include="Imaging\AnchorPosition.cs" />
@ -131,13 +130,14 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="libwebp64.dll">
<Content Include="x64\imageprocessor.libwebp.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="libwebp32.dll">
<Content Include="x86\imageprocessor.libwebp.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

22
src/ImageProcessor/Imaging/Formats/GifEncoder.cs

@ -298,20 +298,14 @@ namespace ImageProcessor.Imaging.Formats
this.WriteByte(0); // Pixel aspect ratio
this.WriteColorTable(sourceGif);
// The different browsers interpret the spec differently when adding a loop.
// If the loop count is one IE and FF &lt; 3 (incorrectly) loop an extra number of times.
// Removing the Netscape header should fix this.
if (count > -1 && count != 1)
{
// Application Extension Header
this.WriteShort(ApplicationExtensionBlockIdentifier);
this.WriteByte(ApplicationBlockSize);
this.WriteString(ApplicationIdentification);
this.WriteByte(3); // Application block length
this.WriteByte(1);
this.WriteShort(count); // Repeat count for images.
this.WriteByte(0); // Terminator
}
// Application Extension Header
this.WriteShort(ApplicationExtensionBlockIdentifier);
this.WriteByte(ApplicationBlockSize);
this.WriteString(ApplicationIdentification);
this.WriteByte(3); // Application block length
this.WriteByte(1);
this.WriteShort(count); // Repeat count for images.
this.WriteByte(0); // Terminator
}
/// <summary>

133
src/ImageProcessor/Imaging/Formats/NativeMethods.cs

@ -18,6 +18,12 @@ namespace ImageProcessor.Imaging.Formats
/// </summary>
internal static class NativeMethods
{
/// <summary>
/// Whether the process is running in 64bit mode. Used for calling the correct dllimport method.
/// Clunky I know but I couldn't get dynamic methods to work.
/// </summary>
private static readonly bool Is64Bit = Environment.Is64BitProcess;
#region WebP
/// <summary>
/// Validate the WebP image header and retrieve the image height and width. Pointers *width and *height can be passed NULL if deemed irrelevant
@ -37,8 +43,103 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// 1 if success, otherwise error code returned in the case of (a) formatting error(s).
/// </returns>
[DllImport("libwebp32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
public static extern int WebPGetInfo86(IntPtr data, uint dataSize, out int width, out int height);
public static int WebPGetInfo(IntPtr data, uint dataSize, out int width, out int height)
{
return Is64Bit ? WebPGetInfo64(data, dataSize, out width, out height)
: WebPGetInfo86(data, dataSize, out width, out height);
}
/// <summary>
/// Decode WEBP image pointed to by *data and returns BGR samples into a pre-allocated buffer
/// </summary>
/// <param name="data">
/// Pointer to WebP image data
/// </param>
/// <param name="dataSize">
/// This is the size of the memory block pointed to by data containing the image data
/// </param>
/// <param name="outputBuffer">
/// Pointer to decoded WebP image
/// </param>
/// <param name="outputBufferSize">
/// Size of allocated buffer
/// </param>
/// <param name="outputStride">
/// Specifies the distance between scan-lines
/// </param>
/// <returns>
/// output_buffer if function succeeds; NULL otherwise
/// </returns>
public static IntPtr WebPDecodeBGRAInto(IntPtr data, uint dataSize, IntPtr outputBuffer, int outputBufferSize, int outputStride)
{
return Is64Bit ? WebPDecodeBGRAInto64(data, dataSize, outputBuffer, outputBufferSize, outputStride)
: WebPDecodeBGRAInto86(data, dataSize, outputBuffer, outputBufferSize, outputStride);
}
/// <summary>
/// Lossy encoding images pointed to by *data in WebP format
/// </summary>
/// <param name="rgb">
/// Pointer to RGB image data
/// </param>
/// <param name="width">
/// The width range is limited currently from 1 to 16383
/// </param>
/// <param name="height">
/// The height range is limited currently from 1 to 16383
/// </param>
/// <param name="stride">
/// The stride.
/// </param>
/// <param name="qualityFactor">
/// Ranges from 0 (lower quality) to 100 (highest quality). Controls the loss and quality during compression
/// </param>
/// <param name="output">
/// output_buffer with WebP image
/// </param>
/// <returns>
/// Size of WebP Image
/// </returns>
public static int WebPEncodeBGRA(IntPtr rgb, int width, int height, int stride, float qualityFactor, out IntPtr output)
{
return Is64Bit ? WebPEncodeBGRA64(rgb, width, height, stride, qualityFactor, out output)
: WebPEncodeBGRA86(rgb, width, height, stride, qualityFactor, out output);
}
/// <summary>
/// Frees the unmanaged memory.
/// </summary>
/// <param name="pointer">
/// The pointer.
/// </param>
/// <returns>
/// 1 if success, otherwise error code returned in the case of (a) error(s).
/// </returns>
public static int WebPFree(IntPtr pointer)
{
return Is64Bit ? WebPFree64(pointer) : WebPFree86(pointer);
}
/// <summary>
/// Validate the WebP image header and retrieve the image height and width. Pointers *width and *height can be passed NULL if deemed irrelevant
/// </summary>
/// <param name="data">
/// Pointer to WebP image data
/// </param>
/// <param name="dataSize">
/// This is the size of the memory block pointed to by data containing the image data
/// </param>
/// <param name="width">
/// The width range is limited currently from 1 to 16383
/// </param>
/// <param name="height">
/// The height range is limited currently from 1 to 16383
/// </param>
/// <returns>
/// 1 if success, otherwise error code returned in the case of (a) formatting error(s).
/// </returns>
[DllImport("x86\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
private static extern int WebPGetInfo86(IntPtr data, uint dataSize, out int width, out int height);
/// <summary>
/// Validate the WebP image header and retrieve the image height and width. Pointers *width and *height can be passed NULL if deemed irrelevant
@ -58,8 +159,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// 1 if success, otherwise error code returned in the case of (a) formatting error(s).
/// </returns>
[DllImport("libwebp64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
public static extern int WebPGetInfo64(IntPtr data, uint dataSize, out int width, out int height);
[DllImport("x64\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
private static extern int WebPGetInfo64(IntPtr data, uint dataSize, out int width, out int height);
/// <summary>
/// Decode WEBP image pointed to by *data and returns BGR samples into a pre-allocated buffer
@ -82,8 +183,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// output_buffer if function succeeds; NULL otherwise
/// </returns>
[DllImport("libwebp32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
public static extern IntPtr WebPDecodeBGRAInto86(IntPtr data, uint dataSize, IntPtr outputBuffer, int outputBufferSize, int outputStride);
[DllImport("x86\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
private static extern IntPtr WebPDecodeBGRAInto86(IntPtr data, uint dataSize, IntPtr outputBuffer, int outputBufferSize, int outputStride);
/// <summary>
/// Decode WEBP image pointed to by *data and returns BGR samples into a pre-allocated buffer
@ -106,8 +207,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// output_buffer if function succeeds; NULL otherwise
/// </returns>
[DllImport("libwebp64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
public static extern IntPtr WebPDecodeBGRAInto64(IntPtr data, uint dataSize, IntPtr outputBuffer, int outputBufferSize, int outputStride);
[DllImport("x64\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
private static extern IntPtr WebPDecodeBGRAInto64(IntPtr data, uint dataSize, IntPtr outputBuffer, int outputBufferSize, int outputStride);
/// <summary>
/// Lossy encoding images pointed to by *data in WebP format
@ -133,8 +234,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// Size of WebP Image
/// </returns>
[DllImport("libwebp32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
public static extern int WebPEncodeBGRA86(IntPtr rgb, int width, int height, int stride, float qualityFactor, out IntPtr output);
[DllImport("x86\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
private static extern int WebPEncodeBGRA86(IntPtr rgb, int width, int height, int stride, float qualityFactor, out IntPtr output);
/// <summary>
/// Lossy encoding images pointed to by *data in WebP format
@ -160,8 +261,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// Size of WebP Image
/// </returns>
[DllImport("libwebp64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
public static extern int WebPEncodeBGRA64(IntPtr rgb, int width, int height, int stride, float qualityFactor, out IntPtr output);
[DllImport("x64\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
private static extern int WebPEncodeBGRA64(IntPtr rgb, int width, int height, int stride, float qualityFactor, out IntPtr output);
/// <summary>
/// Frees the unmanaged memory.
@ -172,8 +273,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// 1 if success, otherwise error code returned in the case of (a) error(s).
/// </returns>
[DllImport("libwebp32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
public static extern int WebPFree86(IntPtr pointer);
[DllImport("x86\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
private static extern int WebPFree86(IntPtr pointer);
/// <summary>
/// Frees the unmanaged memory.
@ -184,8 +285,8 @@ namespace ImageProcessor.Imaging.Formats
/// <returns>
/// 1 if success, otherwise error code returned in the case of (a) error(s).
/// </returns>
[DllImport("libwebp64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
public static extern int WebPFree64(IntPtr pointer);
[DllImport("x64\\imageprocessor.libwebp.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
private static extern int WebPFree64(IntPtr pointer);
#endregion
}
}

60
src/ImageProcessor/Imaging/Formats/WebPFormat.cs

@ -31,12 +31,6 @@ namespace ImageProcessor.Imaging.Formats
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")]
public class WebPFormat : FormatBase
{
/// <summary>
/// Whether the process is running in 64bit mode. Used for calling the correct dllimport method.
/// Clunky I know but I couldn't get dynamic methods to work.
/// </summary>
private static readonly bool Is64Bit = Environment.Is64BitProcess;
/// <summary>
/// Gets the file headers.
/// </summary>
@ -190,19 +184,9 @@ namespace ImageProcessor.Imaging.Formats
int width;
int height;
if (Is64Bit)
{
if (NativeMethods.WebPGetInfo64(ptrData, dataSize, out width, out height) != 1)
{
throw new ImageFormatException("WebP image header is corrupted.");
}
}
else
if (NativeMethods.WebPGetInfo(ptrData, dataSize, out width, out height) != 1)
{
if (NativeMethods.WebPGetInfo86(ptrData, dataSize, out width, out height) != 1)
{
throw new ImageFormatException("WebP image header is corrupted.");
}
throw new ImageFormatException("WebP image header is corrupted.");
}
try
@ -215,17 +199,8 @@ namespace ImageProcessor.Imaging.Formats
int outputBufferSize = bitmapData.Stride * height;
outputBuffer = Marshal.AllocHGlobal(outputBufferSize);
// ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
if (Is64Bit)
{
// Uncompress the image
outputBuffer = NativeMethods.WebPDecodeBGRAInto64(ptrData, dataSize, outputBuffer, outputBufferSize, bitmapData.Stride);
}
else
{
// Uncompress the image
outputBuffer = NativeMethods.WebPDecodeBGRAInto86(ptrData, dataSize, outputBuffer, outputBufferSize, bitmapData.Stride);
}
// Uncompress the image
outputBuffer = NativeMethods.WebPDecodeBGRAInto(ptrData, dataSize, outputBuffer, outputBufferSize, bitmapData.Stride);
// Write image to bitmap using Marshal
byte[] buffer = new byte[outputBufferSize];
@ -272,19 +247,8 @@ namespace ImageProcessor.Imaging.Formats
try
{
int size;
// ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
if (Is64Bit)
{
// Attempt to lossy encode the image.
size = NativeMethods.WebPEncodeBGRA64(bmpData.Scan0, bitmap.Width, bitmap.Height, bmpData.Stride, quality, out unmanagedData);
}
else
{
// Attempt to lossy encode the image.
size = NativeMethods.WebPEncodeBGRA86(bmpData.Scan0, bitmap.Width, bitmap.Height, bmpData.Stride, quality, out unmanagedData);
}
// Attempt to lossy encode the image.
int size = NativeMethods.WebPEncodeBGRA(bmpData.Scan0, bitmap.Width, bitmap.Height, bmpData.Stride, quality, out unmanagedData);
// Copy image compress data to output array
webpData = new byte[size];
@ -300,16 +264,8 @@ namespace ImageProcessor.Imaging.Formats
// Unlock the pixels
bitmap.UnlockBits(bmpData);
if (Is64Bit)
{
// Free memory
NativeMethods.WebPFree64(unmanagedData);
}
else
{
// Free memory
NativeMethods.WebPFree86(unmanagedData);
}
// Free memory
NativeMethods.WebPFree(unmanagedData);
}
return encoded;

1
src/ImageProcessor/Settings.StyleCop

@ -4,6 +4,7 @@
<Value>bitstream</Value>
<Value>dd</Value>
<Value>ddd</Value>
<Value>dllimport</Value>
<Value>gps</Value>
<Value>mmmm</Value>
<Value>orig</Value>

0
src/ImageProcessor/libwebp64.dll.REMOVED.git-id → src/ImageProcessor/x64/imageprocessor.libwebp.dll.REMOVED.git-id

0
src/ImageProcessor/libwebp32.dll.REMOVED.git-id → src/ImageProcessor/x86/imageprocessor.libwebp.dll.REMOVED.git-id

BIN
src/ImageProcessorConsole/images/output/rotate.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

4
src/TestWebsites/NET45/Test_Website_NET45/Web.config

@ -43,8 +43,9 @@
</pages>
<httpModules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
<add name="ImageProcessorNativeBinaryModule" type="ImageProcessor.Web.HttpModules.ImageProcessorNativeBinaryModule, ImageProcessor.Web"/>
</httpModules>
</system.web>
<system.webServer>
@ -63,6 +64,7 @@
</handlers>
<modules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
<add name="ImageProcessorNativeBinaryModule" type="ImageProcessor.Web.HttpModules.ImageProcessorNativeBinaryModule, ImageProcessor.Web"/>
</modules>
</system.webServer>
</configuration>

Loading…
Cancel
Save