diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs
index 6b2dfaf1e..32a818284 100644
--- a/Greenshot/Drawing/Surface.cs
+++ b/Greenshot/Drawing/Surface.cs
@@ -797,7 +797,7 @@ namespace Greenshot.Drawing {
break;
case Effects.TornEdge:
using (Bitmap tmpImage = ImageHelper.CreateTornEdge((Bitmap)Image)) {
- newImage = ImageHelper.CreateShadow(tmpImage, 1f, 6, ref offset, PixelFormat.Format32bppArgb); //Image.PixelFormat);
+ newImage = ImageHelper.CreateShadow(tmpImage, 1f, 7, ref offset, PixelFormat.Format32bppArgb); //Image.PixelFormat);
}
break;
case Effects.Border:
diff --git a/GreenshotPlugin/Core/BitmapBuffer.cs b/GreenshotPlugin/Core/BitmapBuffer.cs
index 4aa42ad37..3ff4a4476 100644
--- a/GreenshotPlugin/Core/BitmapBuffer.cs
+++ b/GreenshotPlugin/Core/BitmapBuffer.cs
@@ -62,6 +62,12 @@ namespace GreenshotPlugin.Core {
}
}
+ public PixelFormat PixelFormat {
+ get {
+ return bitmap.PixelFormat;
+ }
+ }
+
[NonSerialized]
private BitmapData bmData;
[NonSerialized]
@@ -69,6 +75,8 @@ namespace GreenshotPlugin.Core {
[NonSerialized]
private byte* pointer;
[NonSerialized]
+ private int* intPointer;
+ [NonSerialized]
private int stride; /* bytes per pixel row */
[NonSerialized]
private int aIndex = -1;
@@ -219,7 +227,8 @@ namespace GreenshotPlugin.Core {
bitsLocked = true;
IntPtr Scan0 = bmData.Scan0;
- pointer = (byte*)(void*)Scan0;
+ pointer = (byte*)(void*)Scan0;
+ intPointer = (int*)(void*)Scan0;
PrepareForPixelFormat();
stride = bmData.Stride;
@@ -300,6 +309,28 @@ namespace GreenshotPlugin.Core {
pointer[offset] = color;
}
+ ///
+ /// Use only when 32-bit bitmap!
+ ///
+ /// x
+ /// y
+ /// int with argb value
+ public int GetARGB(int x, int y) {
+ int offset = (y * (stride >> 2)) + x;
+ return intPointer[offset];
+ }
+
+ ///
+ /// Use only when 32-bit bitmap!
+ ///
+ /// x
+ /// y
+ /// argb value
+ public void SetARGB(int x, int y, int argb) {
+ int offset = (y * (stride>>2)) + x;
+ intPointer[offset] = argb;
+ }
+
///
/// Retrieve the color at location x,y
/// Before the first time this is called the Lock() should be called once!
@@ -372,6 +403,18 @@ namespace GreenshotPlugin.Core {
}
}
+ /**
+ * Retrieve the color at location x,y to a byte[]
+ * Before the first time this is called the Lock() should be called once!
+ */
+ public void GetUncheckedColorIn(int x, int y, byte[] color) {
+ int offset = x * bytesPerPixel + y * stride;
+ color[0] = (aIndex == -1) ? (byte)255 : (byte)pointer[aIndex + offset];
+ color[1] = pointer[rIndex + offset];
+ color[2] = pointer[gIndex + offset];
+ color[3] = pointer[bIndex + offset];
+ }
+
/**
* Retrieve the color at location x,y to a byte[]
* Before the first time this is called the Lock() should be called once!
diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs
index 71c1c9777..08466b402 100644
--- a/GreenshotPlugin/Core/ImageHelper.cs
+++ b/GreenshotPlugin/Core/ImageHelper.cs
@@ -593,6 +593,130 @@ namespace GreenshotPlugin.Core {
}
}
+ ///
+ /// Create a new Bitmap with the BoxBlur result of the sourceBitmap
+ ///
+ /// Bitmap to blur
+ /// Must be ODD!
+ /// Bitmap
+ public static Bitmap BoxBlur(Bitmap sourceBitmap, int range) {
+ if ((range & 1) == 0) {
+ throw new InvalidOperationException("Range must be odd!");
+ }
+ using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, true)) {
+ bbbDest.Lock();
+ using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, false)) {
+ bbbSrc.Lock();
+ BoxBlurHorizontal(bbbSrc, bbbDest, range);
+ }
+ BoxBlurVertical(bbbDest, range);
+ bbbDest.Unlock();
+ return bbbDest.Bitmap;
+ }
+ }
+
+ ///
+ /// BoxBlurHorizontal is a private helper method for the BoxBlur
+ ///
+ /// Source BitmapBuffer
+ /// Target BitmapBuffer
+ /// Range must be odd!
+ private static void BoxBlurHorizontal(BitmapBuffer bbbSrc, BitmapBuffer bbbDest, int range) {
+ int w = bbbSrc.Width;
+ int h = bbbSrc.Height;
+ int halfRange = range / 2;
+ int[] newColors = new int[w];
+ byte[] tmpColor = new byte[4];
+ for (int y = 0; y < h; y++) {
+ int hits = 0;
+ int a = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (int x = -halfRange; x < w; x++) {
+ int oldPixel = x - halfRange - 1;
+ if (oldPixel >= 0) {
+ bbbSrc.GetUncheckedColorIn(oldPixel, y, tmpColor);
+ a -= tmpColor[0];
+ r -= tmpColor[1];
+ g -= tmpColor[2];
+ b -= tmpColor[3];
+ hits--;
+ }
+
+ int newPixel = x + halfRange;
+ if (newPixel < w) {
+ bbbSrc.GetUncheckedColorIn(newPixel, y, tmpColor);
+ a += tmpColor[0];
+ r += tmpColor[1];
+ g += tmpColor[2];
+ b += tmpColor[3];
+ hits++;
+ }
+
+ if (x >= 0) {
+ newColors[x] = ((byte)(a / hits)) << 24 | ((byte)(r / hits) << 16) | ((byte)(g / hits) << 8 ) | ((byte)(b / hits));
+ }
+ }
+ for (int x = 0; x < w; x++) {
+ bbbDest.SetARGB(x, y, newColors[x]);
+ }
+ }
+ }
+
+ ///
+ /// BoxBlurVertical is a private helper method for the BoxBlur
+ ///
+ /// BitmapBuffer which previously was created with BoxBlurHorizontal
+ /// Range must be odd!
+ private static void BoxBlurVertical(BitmapBuffer bbbDest, int range) {
+ int w = bbbDest.Width;
+ int h = bbbDest.Height;
+ int halfRange = range / 2;
+ int[] newColors = new int[h];
+ int oldPixelOffset = -(halfRange + 1) * w;
+ int newPixelOffset = (halfRange) * w;
+ byte[] tmpColor = new byte[4];
+ for (int x = 0; x < w; x++) {
+ int hits = 0;
+ int a = 0;
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (int y = -halfRange; y < h; y++) {
+ int oldPixel = y - halfRange - 1;
+ if (oldPixel >= 0) {
+ //int colorg = pixels[index + oldPixelOffset];
+ bbbDest.GetUncheckedColorIn(x, oldPixel, tmpColor);
+ a -= tmpColor[0];
+ r -= tmpColor[1];
+ g -= tmpColor[2];
+ b -= tmpColor[3];
+ hits--;
+ }
+
+ int newPixel = y + halfRange;
+ if (newPixel < h) {
+ //int colorg = pixels[index + newPixelOffset];
+ bbbDest.GetUncheckedColorIn(x, newPixel, tmpColor);
+ a += tmpColor[0];
+ r += tmpColor[1];
+ g += tmpColor[2];
+ b += tmpColor[3];
+ hits++;
+ }
+
+ if (y >= 0) {
+ newColors[y] = ((byte)(a / hits)) << 24 | ((byte)(r / hits) << 16) | ((byte)(g / hits) << 8) | ((byte)(b / hits));
+ }
+ }
+
+ for (int y = 0; y < h; y++) {
+ bbbDest.SetARGB(x, y, newColors[y]);
+ }
+ }
+ }
+
public static Bitmap FastBlur(Bitmap sourceBitmap, int radius) {
if (radius < 1) return null;
@@ -747,6 +871,7 @@ namespace GreenshotPlugin.Core {
Rectangle newImageRectangle = new Rectangle(0, 0, tmpImage.Width, tmpImage.Height);
//using (Bitmap blurImage = FastBlur(newImage, shadowSize-1)) {
returnImage = CreateBlur(tmpImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle);
+ //returnImage = BoxBlur(tmpImage, shadowSize);
}
if (returnImage != null) {
using (Graphics graphics = Graphics.FromImage(returnImage)) {
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index aa1098e6b..bacf49bd9 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -776,32 +776,25 @@ namespace GreenshotPlugin.Core {
Size borderSize = new Size();
if (!Maximised) {
- Screen displayScreen = null;
-
- // Find the screen where the window is and check if it fits
- foreach(Screen screen in Screen.AllScreens) {
- if (screen.WorkingArea.Contains(windowRectangle)) {
- displayScreen = screen;
- break;
+ // Assume using it's own location
+ formLocation = windowRectangle.Location;
+ using (Region workingArea = new Region(Screen.PrimaryScreen.WorkingArea)) {
+ // Find the screen where the window is and check if it fits
+ foreach (Screen screen in Screen.AllScreens) {
+ workingArea.Union(screen.WorkingArea);
}
- }
- if (displayScreen == null) {
- // If none found we find the biggest screen
- foreach(Screen screen in Screen.AllScreens) {
- if (displayScreen == null || (screen.Bounds.Width >= displayScreen.Bounds.Width && screen.Bounds.Height >= displayScreen.Bounds.Height)) {
- displayScreen = screen;
+
+ // If the formLocation is not inside the visible area
+ if (!workingArea.AreRectangleCornersVisisble(windowRectangle)) {
+ // If none found we find the biggest screen
+ foreach (Screen screen in Screen.AllScreens) {
+ Rectangle newWindowRectangle = new Rectangle(screen.WorkingArea.Location, windowRectangle.Size);
+ if (workingArea.AreRectangleCornersVisisble(newWindowRectangle)) {
+ formLocation = screen.WorkingArea.Location;
+ break;
+ }
}
}
- // check if the window will fit
- if (displayScreen != null && displayScreen.Bounds.Contains(new Rectangle(Point.Empty, windowRectangle.Size))) {
- formLocation = new Point(displayScreen.Bounds.X, displayScreen.Bounds.Y);
- } else {
- // No, just use the primary screen
- formLocation = new Point(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y);
- }
- } else {
- // The window actually fits, so while capturing create the copy over the original
- formLocation = new Point(windowRectangle.X, windowRectangle.Y);
}
} else {
//GetClientRect(out windowRectangle);
diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs
index ec8422584..cecb70d72 100644
--- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs
+++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs
@@ -23,6 +23,20 @@ using System.Drawing;
using System.Runtime.InteropServices;
namespace GreenshotPlugin.UnmanagedHelpers {
+ public static class GDIExtensions {
+ public static bool AreRectangleCornersVisisble(this Region region, Rectangle rectangle) {
+ Point topLeft = new Point(rectangle.X, rectangle.Y);
+ Point topRight = new Point(rectangle.X + rectangle.Width, rectangle.Y);
+ Point bottomLeft = new Point(rectangle.X, rectangle.Y + rectangle.Height);
+ Point bottomRight = new Point(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);
+ bool topLeftVisible = region.IsVisible(topLeft);
+ bool topRightVisible = region.IsVisible(topRight);
+ bool bottomLeftVisible = region.IsVisible(bottomLeft);
+ bool bottomRightVisible = region.IsVisible(bottomRight);
+
+ return topLeftVisible && topRightVisible && bottomLeftVisible && bottomRightVisible;
+ }
+ }
///
/// GDI32 Helpers
///