mirror of
https://github.com/greenshot/greenshot
synced 2025-08-19 21:13:23 -07:00
Added DrawWithBlur to the GDIplus. P.S. all blur logic seems to be broken on Windows 8 when having a radius < 20
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2495 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
203479ee4d
commit
9d1b0e5dc4
2 changed files with 256 additions and 6 deletions
|
@ -24,6 +24,8 @@ using System.Runtime.InteropServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
namespace GreenshotPlugin.UnmanagedHelpers {
|
namespace GreenshotPlugin.UnmanagedHelpers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -47,6 +49,46 @@ namespace GreenshotPlugin.UnmanagedHelpers {
|
||||||
public bool ExpandEdges;
|
public bool ExpandEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GDI Plus unit description.
|
||||||
|
/// </summary>
|
||||||
|
public enum GpUnit {
|
||||||
|
/// <summary>
|
||||||
|
/// World coordinate (non-physical unit).
|
||||||
|
/// </summary>
|
||||||
|
UnitWorld,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Variable - for PageTransform only.
|
||||||
|
/// </summary>
|
||||||
|
UnitDisplay,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each unit is one device pixel.
|
||||||
|
/// </summary>
|
||||||
|
UnitPixel,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each unit is a printer's point, or 1/72 inch.
|
||||||
|
/// </summary>
|
||||||
|
UnitPoint,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each unit is 1 inch.
|
||||||
|
/// </summary>
|
||||||
|
UnitInch,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each unit is 1/300 inch.
|
||||||
|
/// </summary>
|
||||||
|
UnitDocument,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each unit is 1 millimeter.
|
||||||
|
/// </summary>
|
||||||
|
UnitMillimeter
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GDIplus Helpers
|
/// GDIplus Helpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -55,6 +97,9 @@ namespace GreenshotPlugin.UnmanagedHelpers {
|
||||||
|
|
||||||
[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)]
|
||||||
|
private static extern int GdipDrawImageFX(IntPtr graphics, IntPtr bitmap, ref RECTF source, IntPtr matrix, IntPtr effect, IntPtr imageAttributes, GpUnit srcUnit);
|
||||||
[DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
[DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||||
private static extern int GdipSetEffectParameters(IntPtr effect, IntPtr parameters, uint size);
|
private static extern int GdipSetEffectParameters(IntPtr effect, IntPtr parameters, uint size);
|
||||||
[DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
[DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||||
|
@ -63,26 +108,72 @@ 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}");
|
||||||
|
|
||||||
// Constant "FieldInfo" for getting the nativeImage from the image
|
// Constant "FieldInfo" for getting the nativeImage from the Bitmap
|
||||||
private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGE = typeof(Bitmap).GetField("nativeImage", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
|
private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGE = typeof(Bitmap).GetField("nativeImage", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
// Constant "FieldInfo" for getting the NativeGraphics from the Graphics
|
||||||
|
private static readonly FieldInfo FIELD_INFO_NATIVE_GRAPHICS = typeof(Graphics).GetField("nativeGraphics", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
// Constant "FieldInfo" for getting the nativeMatrix from the Matrix
|
||||||
|
private static readonly FieldInfo FIELD_INFO_NATIVE_MATRIX = typeof(Matrix).GetField("nativeMatrix", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
// Constant "FieldInfo" for getting the nativeImageAttributes from the ImageAttributes
|
||||||
|
private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGEATTRIBUTES = typeof(ImageAttributes).GetField("nativeImageAttributes", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the nativeImage field from the bitmap
|
/// Get the nativeImage field from the bitmap
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bitmap"></param>
|
/// <param name="bitmap"></param>
|
||||||
/// <returns></returns>
|
/// <returns>IntPtr</returns>
|
||||||
private static IntPtr GetNativeImage(Bitmap bitmap) {
|
private static IntPtr GetNativeImage(Bitmap bitmap) {
|
||||||
|
if (bitmap == null) {
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
return (IntPtr)FIELD_INFO_NATIVE_IMAGE.GetValue(bitmap);
|
return (IntPtr)FIELD_INFO_NATIVE_IMAGE.GetValue(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the NativeGraphics field from the graphics
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="graphics"></param>
|
||||||
|
/// <returns>IntPtr</returns>
|
||||||
|
private static IntPtr GetNativeGraphics(Graphics graphics) {
|
||||||
|
if (graphics == null) {
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
return (IntPtr)FIELD_INFO_NATIVE_GRAPHICS.GetValue(graphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the nativeMatrix field from the matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="matrix"></param>
|
||||||
|
/// <returns>IntPtr</returns>
|
||||||
|
private static IntPtr GetNativeMatrix(Matrix matrix) {
|
||||||
|
if (matrix == null) {
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
return (IntPtr)FIELD_INFO_NATIVE_MATRIX.GetValue(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the nativeImageAttributes field from the ImageAttributes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imageAttributes"></param>
|
||||||
|
/// <returns>IntPtr</returns>
|
||||||
|
private static IntPtr GetNativeImageAttributes(ImageAttributes imageAttributes) {
|
||||||
|
if (imageAttributes == null) {
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
return (IntPtr)FIELD_INFO_NATIVE_IMAGEATTRIBUTES.GetValue(imageAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use the GDI+ blur effect on the bitmap
|
/// Use the GDI+ blur effect on the bitmap
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="destinationBitmap">Bitmap to apply the effect to</param>
|
/// <param name="destinationBitmap">Bitmap to apply the effect to</param>
|
||||||
/// <param name="area">Rectangle to apply the blur effect to</param>
|
/// <param name="area">Rectangle to apply the blur effect to</param>
|
||||||
/// <param name="radius">0-255</param>
|
/// <param name="radius">0-255</param>
|
||||||
|
/// <param name="expandEdges">bool true if the edges are expanded with the radius</param>
|
||||||
/// <returns>false if there is no GDI+ available or an exception occured</returns>
|
/// <returns>false if there is no GDI+ available or an exception occured</returns>
|
||||||
public static bool ApplyBlur(Bitmap destinationBitmap, Rectangle area, float radius) {
|
public static bool ApplyBlur(Bitmap destinationBitmap, Rectangle area, int radius, bool expandEdges) {
|
||||||
if (Environment.OSVersion.Version.Major < 6) {
|
if (Environment.OSVersion.Version.Major < 6) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -93,12 +184,12 @@ namespace GreenshotPlugin.UnmanagedHelpers {
|
||||||
// Create a BlurParams struct and set the values
|
// 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 = expandEdges;
|
||||||
|
|
||||||
// Allocate space in unmanaged memory
|
// Allocate space in unmanaged memory
|
||||||
hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams));
|
hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams));
|
||||||
// Copy the structure to the unmanaged memory
|
// Copy the structure to the unmanaged memory
|
||||||
Marshal.StructureToPtr(blurParams, hBlurParams, true);
|
Marshal.StructureToPtr(blurParams, hBlurParams, false);
|
||||||
|
|
||||||
// Create the GDI+ BlurEffect, using the Guid
|
// Create the GDI+ BlurEffect, using the Guid
|
||||||
int status = GdipCreateEffect(BlurEffectGuid, out hEffect);
|
int status = GdipCreateEffect(BlurEffectGuid, out hEffect);
|
||||||
|
@ -131,5 +222,66 @@ namespace GreenshotPlugin.UnmanagedHelpers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw the image on the graphics with GDI+ blur effect
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>false if there is no GDI+ available or an exception occured</returns>
|
||||||
|
public static bool DrawWithBlur(Graphics graphics, Bitmap image, Rectangle source, Matrix transform, ImageAttributes imageAttributes, int radius, bool expandEdges) {
|
||||||
|
if (Environment.OSVersion.Version.Major < 6) {
|
||||||
|
return false;
|
||||||
|
} else if ((Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2) && radius < 20) {
|
||||||
|
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.Padding = radius;
|
||||||
|
blurParams.ExpandEdges = false;
|
||||||
|
|
||||||
|
// Allocate space in unmanaged memory
|
||||||
|
hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams));
|
||||||
|
// Copy the structure to the unmanaged memory
|
||||||
|
Marshal.StructureToPtr(blurParams, hBlurParams, true);
|
||||||
|
|
||||||
|
// Create the GDI+ BlurEffect, using the Guid
|
||||||
|
int status = GdipCreateEffect(BlurEffectGuid, out hEffect);
|
||||||
|
|
||||||
|
// 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(image);
|
||||||
|
IntPtr hGraphics = GetNativeGraphics(graphics);
|
||||||
|
IntPtr hMatrix = GetNativeMatrix(transform);
|
||||||
|
IntPtr hAttributes = GetNativeImageAttributes(imageAttributes);
|
||||||
|
|
||||||
|
// Create a RECT from the Rectangle
|
||||||
|
RECTF sourceRECF = new RECTF(source);
|
||||||
|
// Apply the effect to the bitmap in the specified area
|
||||||
|
GdipDrawImageFX(hGraphics, hBitmap, ref sourceRECF, hMatrix, hEffect, hAttributes, GpUnit.UnitPixel);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,104 @@ namespace GreenshotPlugin.UnmanagedHelpers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A floating point GDI Plus width/hight based rectangle.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct RECTF {
|
||||||
|
/// <summary>
|
||||||
|
/// The X corner location of the rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public float X;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Y corner location of the rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public float Y;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The width of the rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public float Width;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The height of the rectangle.
|
||||||
|
/// </summary>
|
||||||
|
public float Height;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new GDI Plus rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The X corner location of the rectangle.</param>
|
||||||
|
/// <param name="y">The Y corner location of the rectangle.</param>
|
||||||
|
/// <param name="width">The width of the rectangle.</param>
|
||||||
|
/// <param name="height">The height of the rectangle.</param>
|
||||||
|
public RECTF(float x, float y, float width, float height) {
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new GDI Plus rectangle from a System.Drawing.RectangleF.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The rectangle to base this GDI Plus rectangle on.</param>
|
||||||
|
public RECTF(RectangleF rect) {
|
||||||
|
X = rect.X;
|
||||||
|
Y = rect.Y;
|
||||||
|
Width = rect.Width;
|
||||||
|
Height = rect.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new GDI Plus rectangle from a System.Drawing.Rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The rectangle to base this GDI Plus rectangle on.</param>
|
||||||
|
public RECTF(Rectangle rect) {
|
||||||
|
X = rect.X;
|
||||||
|
Y = rect.Y;
|
||||||
|
Width = rect.Width;
|
||||||
|
Height = rect.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a RectangleF for this GDI Plus rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A System.Drawing.RectangleF structure.</returns>
|
||||||
|
public RectangleF ToRectangle() {
|
||||||
|
return new RectangleF(X, Y, Width, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a RectangleF for a GDI Plus rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The GDI Plus rectangle to get the RectangleF for.</param>
|
||||||
|
/// <returns>A System.Drawing.RectangleF structure.</returns>
|
||||||
|
public static RectangleF ToRectangle(RECTF rect) {
|
||||||
|
return rect.ToRectangle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a GDI Plus rectangle for a RectangleF structure.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The RectangleF to get the GDI Plus rectangle for.</param>
|
||||||
|
/// <returns>A GDI Plus rectangle structure.</returns>
|
||||||
|
public static RECTF FromRectangle(RectangleF rect) {
|
||||||
|
return new RECTF(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a GDI Plus rectangle for a Rectangle structure.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rect">The Rectangle to get the GDI Plus rectangle for.</param>
|
||||||
|
/// <returns>A GDI Plus rectangle structure.</returns>
|
||||||
|
public static RECTF FromRectangle(Rectangle rect) {
|
||||||
|
return new RECTF(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The structure for the WindowInfo
|
/// The structure for the WindowInfo
|
||||||
/// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632610%28v=vs.85%29.aspx
|
/// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632610%28v=vs.85%29.aspx
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue