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
This commit is contained in:
RKrom 2013-02-15 13:35:15 +00:00
parent 0408c755d6
commit 9f86db6828

View file

@ -51,6 +51,8 @@ namespace GreenshotPlugin.UnmanagedHelpers {
/// GDIplus Helpers /// GDIplus Helpers
/// </summary> /// </summary>
public static class GDIplus { public static class GDIplus {
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(GDIplus));
[DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] [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); 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)] [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 extern int GdipDeleteEffect(IntPtr effect);
private static Guid BlurEffectGuid = new Guid("{633C80A4-1843-482B-9EF2-BE2834C5FDD4}"); private static Guid BlurEffectGuid = new Guid("{633C80A4-1843-482B-9EF2-BE2834C5FDD4}");
internal static TResult GetPrivateField<TResult>(object obj, string fieldName) { // Constant "FieldInfo" for getting the nativeImage from the image
if (obj == null) { private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGE = typeof(Bitmap).GetField("nativeImage", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
return default(TResult);
} /// <summary>
Type ltType = obj.GetType(); /// Get the nativeImage field from the bitmap
FieldInfo lfiFieldInfo = ltType.GetField( fieldName,System.Reflection.BindingFlags.GetField |System.Reflection.BindingFlags.Instance |System.Reflection.BindingFlags.NonPublic); /// </summary>
if (lfiFieldInfo != null) { /// <param name="bitmap"></param>
return (TResult)lfiFieldInfo.GetValue(obj); /// <returns></returns>
} else { private static IntPtr GetNativeImage(Bitmap bitmap) {
throw new InvalidOperationException(string.Format("Instance field '{0}' could not be located in object of type '{1}'.",fieldName, obj.GetType().FullName)); return (IntPtr)FIELD_INFO_NATIVE_IMAGE.GetValue(bitmap);
}
} }
/// <summary> /// <summary>
@ -85,29 +86,49 @@ namespace GreenshotPlugin.UnmanagedHelpers {
if (Environment.OSVersion.Version.Major < 6) { if (Environment.OSVersion.Version.Major < 6) {
return false; return false;
} }
IntPtr hBlurParams = IntPtr.Zero;
IntPtr hEffect = IntPtr.Zero;
try { try {
// Create a BlurParams struct and set the values
BlurParams blurParams = new BlurParams(); BlurParams blurParams = new BlurParams();
blurParams.Radius = radius; blurParams.Radius = radius;
blurParams.ExpandEdges = false; 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); Marshal.StructureToPtr(blurParams, hBlurParams, true);
uint paramsSize = (uint)Marshal.SizeOf(blurParams); // Create the GDI+ BlurEffect, using the Guid
IntPtr hEffect = IntPtr.Zero;
int status = GdipCreateEffect(BlurEffectGuid, out hEffect); int status = GdipCreateEffect(BlurEffectGuid, out hEffect);
GdipSetEffectParameters(hEffect, hBlurParams, paramsSize);
//IntPtr hBitmap = destinationBitmap.GetHbitmap(); // Set the blurParams to the effect
IntPtr hBitmap = GetPrivateField<IntPtr>(destinationBitmap, "nativeImage"); 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); RECT rec = new RECT(area);
// Apply the effect to the bitmap in the specified area
GdipBitmapApplyEffect(hBitmap, hEffect, ref rec, false, IntPtr.Zero, 0); GdipBitmapApplyEffect(hBitmap, hEffect, ref rec, false, IntPtr.Zero, 0);
GdipDeleteEffect(hEffect);
Marshal.FreeHGlobal(hBlurParams); // Everything worked, return true
return true; return true;
} catch (Exception ex) { } catch (Exception ex) {
LOG.Error("Problem using GdipBitmapApplyEffect: ", ex);
return false; return false;
} finally {
if (hEffect != null) {
// Delete the effect
GdipDeleteEffect(hEffect);
}
if (hBlurParams != IntPtr.Zero) {
// Free the memory
Marshal.FreeHGlobal(hBlurParams);
}
} }
} }
} }