mirror of https://github.com/SixLabors/ImageSharp
Browse Source
TODO: Test in Mono. Former-commit-id: eb546c441b703924596b4558f62e58596cdbca1apull/17/head
24 changed files with 282 additions and 419 deletions
@ -1,21 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<AvailableItemName Include="NativeBinaries" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<NativeBinaries Include="$(MSBuildThisFileDirectory)native\lib\**\*" /> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<PrepareForRunDependsOn> |
|||
$(PrepareForRunDependsOn); |
|||
CopyNativeBinaries |
|||
</PrepareForRunDependsOn> |
|||
</PropertyGroup> |
|||
<Target Name="CopyNativeBinaries" DependsOnTargets="CopyFilesToOutputDirectory"> |
|||
<Copy SourceFiles="@(NativeBinaries)" |
|||
DestinationFiles="@(NativeBinaries->'$(OutDir)\%(RecursiveDir)\%(Filename)%(Extension)')"> |
|||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" /> |
|||
</Copy> |
|||
</Target> |
|||
</Project> |
|||
@ -1,161 +0,0 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <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); |
|||
Assembly assembly = Assembly.GetExecutingAssembly(); |
|||
string targetBasePath = new Uri(assembly.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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="NativeBinaryFactory.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// Controls the loading and unloading of any native binaries required by ImageProcessor.
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Configuration |
|||
{ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
/// <summary>
|
|||
/// Controls the loading and unloading of any native binaries required by ImageProcessor.
|
|||
/// </summary>
|
|||
public class NativeBinaryFactory : IDisposable |
|||
{ |
|||
/// <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 native binaries.
|
|||
/// </summary>
|
|||
private static ConcurrentDictionary<string, IntPtr> nativeBinaries; |
|||
|
|||
/// <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>
|
|||
/// Initializes a new instance of the <see cref="NativeBinaryFactory"/> class.
|
|||
/// </summary>
|
|||
public NativeBinaryFactory() |
|||
{ |
|||
nativeBinaries = new ConcurrentDictionary<string, IntPtr>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finalizes an instance of the <see cref="T:ImageProcessor.Configuration.NativeBinaryFactory">ImageFactory</see> class.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Use C# destructor syntax for finalization code.
|
|||
/// This destructor will run only if the Dispose method
|
|||
/// does not get called.
|
|||
/// It gives your base class the opportunity to finalize.
|
|||
/// Do not provide destructors in types derived from this class.
|
|||
/// </remarks>
|
|||
~NativeBinaryFactory() |
|||
{ |
|||
// Do not re-create Dispose clean-up code here.
|
|||
// Calling Dispose(false) is optimal in terms of
|
|||
// readability and maintainability.
|
|||
this.Dispose(false); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers any embedded native (unmanaged) binaries required by ImageProcessor.
|
|||
/// </summary>
|
|||
/// <param name="name">
|
|||
/// The name of the native binary.
|
|||
/// </param>
|
|||
/// <param name="resourceBytes">
|
|||
/// The resource bytes containing the native binary.
|
|||
/// </param>
|
|||
/// <exception cref="ApplicationException">
|
|||
/// Thrown if the binary cannot be registered.
|
|||
/// </exception>
|
|||
public void RegisterNativeBinary(string name, byte[] resourceBytes) |
|||
{ |
|||
nativeBinaries.GetOrAdd( |
|||
name, |
|||
b => |
|||
{ |
|||
IntPtr pointer; |
|||
string folder = Is64Bit ? "x64" : "x86"; |
|||
Assembly assembly = Assembly.GetExecutingAssembly(); |
|||
string targetBasePath = new Uri(assembly.Location).LocalPath; |
|||
string targetPath = Path.GetFullPath(Path.Combine(targetBasePath, "..\\" + folder + "\\" + name)); |
|||
|
|||
// Copy the file across if necessary.
|
|||
FileInfo fileInfo = new FileInfo(targetPath); |
|||
bool rewrite = true; |
|||
if (fileInfo.Exists) |
|||
{ |
|||
byte[] existing = File.ReadAllBytes(targetPath); |
|||
|
|||
if (resourceBytes.SequenceEqual(existing)) |
|||
{ |
|||
rewrite = false; |
|||
} |
|||
} |
|||
|
|||
if (rewrite) |
|||
{ |
|||
// ReSharper disable once AssignNullToNotNullAttribute
|
|||
DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(targetPath)); |
|||
if (!directoryInfo.Exists) |
|||
{ |
|||
directoryInfo.Create(); |
|||
} |
|||
|
|||
File.WriteAllBytes(targetPath, resourceBytes); |
|||
} |
|||
|
|||
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 " + name); |
|||
} |
|||
|
|||
return pointer; |
|||
}); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the object and frees resources for the Garbage Collector.
|
|||
/// </summary>
|
|||
public void Dispose() |
|||
{ |
|||
this.Dispose(true); |
|||
|
|||
// This object will be cleaned up by the Dispose method.
|
|||
// Therefore, you should call GC.SupressFinalize to
|
|||
// take this object off the finalization queue
|
|||
// and prevent finalization code for this object
|
|||
// from executing a second time.
|
|||
GC.SuppressFinalize(this); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the object and frees resources for the Garbage Collector.
|
|||
/// </summary>
|
|||
/// <param name="disposing">If true, the object gets disposed.</param>
|
|||
protected virtual void Dispose(bool disposing) |
|||
{ |
|||
if (this.isDisposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (disposing) |
|||
{ |
|||
// Dispose of any managed resources here.
|
|||
} |
|||
|
|||
// Call the appropriate methods to clean up
|
|||
// unmanaged resources here.
|
|||
this.FreeNativeBinaries(); |
|||
|
|||
// Note disposing is done.
|
|||
this.isDisposed = true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Frees the reference to the native binaries.
|
|||
/// </summary>
|
|||
private void FreeNativeBinaries() |
|||
{ |
|||
foreach (KeyValuePair<string, IntPtr> nativeBinary in nativeBinaries) |
|||
{ |
|||
IntPtr pointer = nativeBinary.Value; |
|||
|
|||
// According to http://stackoverflow.com/a/2445558/427899 you need to call this twice.
|
|||
NativeMethods.FreeLibrary(pointer); |
|||
NativeMethods.FreeLibrary(pointer); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
// <copyright file="NativeMethods.cs" company="James South">
|
|||
// Copyright (c) James South.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
// <summary>
|
|||
// Provides access to unmanaged native methods.
|
|||
// </summary>
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Configuration |
|||
{ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
/// <summary>
|
|||
/// Provides access to unmanaged native methods.
|
|||
/// </summary>
|
|||
internal class NativeMethods |
|||
{ |
|||
/// <summary>
|
|||
/// Loads the specified module into the address space of the calling process.
|
|||
/// The specified module may cause other modules to be loaded.
|
|||
/// </summary>
|
|||
/// <param name="libname">
|
|||
/// The name of the module. This can be either a library module or
|
|||
/// an executable module.
|
|||
/// </param>
|
|||
/// <returns>If the function succeeds, the return value is a handle to the module; otherwise null.</returns>
|
|||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] |
|||
public static extern IntPtr LoadLibrary(string libname); |
|||
|
|||
/// <summary>
|
|||
/// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count.
|
|||
/// When the reference count reaches zero, the module is unloaded from the address space of the calling
|
|||
/// process and the handle is no longer valid.
|
|||
/// </summary>
|
|||
/// <param name="hModule">A handle to the loaded library module.
|
|||
/// The LoadLibrary, LoadLibraryEx, GetModuleHandle, or GetModuleHandleEx function returns this handle.</param>
|
|||
/// <returns>If the function succeeds, the return value is nonzero; otherwise zero.</returns>
|
|||
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] |
|||
public static extern bool FreeLibrary(IntPtr hModule); |
|||
} |
|||
} |
|||
@ -1 +0,0 @@ |
|||
6f3f997e323adb1fce142930d86338efacffc3fd |
|||
@ -1 +0,0 @@ |
|||
3ab082661fc5d88f88643c47409e196d66e26d4b |
|||
|
Before Width: | Height: | Size: 2.8 KiB |
@ -1 +0,0 @@ |
|||
e2c2fbac64987ad26e19f5d2721fcaa60fee843d |
|||
|
Before Width: | Height: | Size: 22 KiB |
Loading…
Reference in new issue