mirror of https://github.com/SixLabors/ImageSharp
Browse Source
TODO: Test in Mono. Former-commit-id: 5129a494c53e9cd67281a25cb2f1cebbbb4aa700af/merge-core
24 changed files with 282 additions and 425 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 |
|
||||
@ -1,3 +0,0 @@ |
|||||
version https://git-lfs.github.com/spec/v1 |
|
||||
oid sha256:f31110b7933864eff3b149371c962174a8855a1c65f4fee7cb3bc63a79b71467 |
|
||||
size 2905 |
|
||||
@ -1 +0,0 @@ |
|||||
e2c2fbac64987ad26e19f5d2721fcaa60fee843d |
|
||||
@ -1,3 +0,0 @@ |
|||||
version https://git-lfs.github.com/spec/v1 |
|
||||
oid sha256:5787cb5048c7e0eecccf1104594c3ad1aee6b142af5fe98435e4f9d49dc81f9b |
|
||||
size 22990 |
|
||||
Loading…
Reference in new issue