From 9f86db682800b613ea6022361eaf5d2bc74f759d Mon Sep 17 00:00:00 2001 From: RKrom Date: Fri, 15 Feb 2013 13:35:15 +0000 Subject: [PATCH] Improved "speed" of the ApplyBlur by using "static final readonly" for the FieldInfo to get the private field and improved stability by using finally to cleanup. (as it should be) git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2490 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- GreenshotPlugin/UnmanagedHelpers/GDIplus.cs | 63 ++++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs b/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs index a5aa02872..2d94b397b 100644 --- a/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs +++ b/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs @@ -51,6 +51,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { /// GDIplus Helpers /// public static class GDIplus { + private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(GDIplus)); + [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] private static extern int GdipBitmapApplyEffect(IntPtr bitmap, IntPtr effect, ref RECT rectOfInterest, bool useAuxData, IntPtr auxData, int auxDataSize); [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] @@ -61,17 +63,16 @@ namespace GreenshotPlugin.UnmanagedHelpers { private static extern int GdipDeleteEffect(IntPtr effect); private static Guid BlurEffectGuid = new Guid("{633C80A4-1843-482B-9EF2-BE2834C5FDD4}"); - internal static TResult GetPrivateField(object obj, string fieldName) { - if (obj == null) { - return default(TResult); - } - Type ltType = obj.GetType(); - FieldInfo lfiFieldInfo = ltType.GetField( fieldName,System.Reflection.BindingFlags.GetField |System.Reflection.BindingFlags.Instance |System.Reflection.BindingFlags.NonPublic); - if (lfiFieldInfo != null) { - return (TResult)lfiFieldInfo.GetValue(obj); - } else { - throw new InvalidOperationException(string.Format("Instance field '{0}' could not be located in object of type '{1}'.",fieldName, obj.GetType().FullName)); - } + // Constant "FieldInfo" for getting the nativeImage from the image + private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGE = typeof(Bitmap).GetField("nativeImage", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); + + /// + /// Get the nativeImage field from the bitmap + /// + /// + /// + private static IntPtr GetNativeImage(Bitmap bitmap) { + return (IntPtr)FIELD_INFO_NATIVE_IMAGE.GetValue(bitmap); } /// @@ -85,29 +86,49 @@ namespace GreenshotPlugin.UnmanagedHelpers { if (Environment.OSVersion.Version.Major < 6) { return false; } + IntPtr hBlurParams = IntPtr.Zero; + IntPtr hEffect = IntPtr.Zero; + try { + // Create a BlurParams struct and set the values BlurParams blurParams = new BlurParams(); blurParams.Radius = radius; blurParams.ExpandEdges = false; - IntPtr hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams)); + + // Allocate space in unmanaged memory + hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams)); + // Copy the structure to the unmanaged memory Marshal.StructureToPtr(blurParams, hBlurParams, true); - uint paramsSize = (uint)Marshal.SizeOf(blurParams); - - IntPtr hEffect = IntPtr.Zero; - + // Create the GDI+ BlurEffect, using the Guid int status = GdipCreateEffect(BlurEffectGuid, out hEffect); - GdipSetEffectParameters(hEffect, hBlurParams, paramsSize); - //IntPtr hBitmap = destinationBitmap.GetHbitmap(); - IntPtr hBitmap = GetPrivateField(destinationBitmap, "nativeImage"); + // Set the blurParams to the effect + GdipSetEffectParameters(hEffect, hBlurParams, (uint)Marshal.SizeOf(blurParams)); + + // Somewhere it said we can use destinationBitmap.GetHbitmap(), this doesn't work!! + // Get the private nativeImage property from the Bitmap + IntPtr hBitmap = GetNativeImage(destinationBitmap); + + // Create a RECT from the Rectangle RECT rec = new RECT(area); + // Apply the effect to the bitmap in the specified area GdipBitmapApplyEffect(hBitmap, hEffect, ref rec, false, IntPtr.Zero, 0); - GdipDeleteEffect(hEffect); - Marshal.FreeHGlobal(hBlurParams); + + // Everything worked, return true return true; } catch (Exception ex) { + LOG.Error("Problem using GdipBitmapApplyEffect: ", ex); return false; + } finally { + if (hEffect != null) { + // Delete the effect + GdipDeleteEffect(hEffect); + } + if (hBlurParams != IntPtr.Zero) { + // Free the memory + Marshal.FreeHGlobal(hBlurParams); + } } } }