diff --git a/Greenshot/Drawing/Filters/BlurFilter.cs b/Greenshot/Drawing/Filters/BlurFilter.cs
index 3ad741eb3..952584520 100644
--- a/Greenshot/Drawing/Filters/BlurFilter.cs
+++ b/Greenshot/Drawing/Filters/BlurFilter.cs
@@ -39,8 +39,12 @@ namespace Greenshot.Drawing.Filters {
public unsafe override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
double previewQuality = GetFieldValueAsDouble(FieldType.PREVIEW_QUALITY);
-
- ImageHelper.ApplyBlur(graphics, applyBitmap, rect, renderMode == RenderMode.EXPORT, blurRadius, previewQuality, Invert, parent.Bounds);
+ Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
+ using (Bitmap blurImage = ImageHelper.CreateBlur(applyBitmap, applyRect, renderMode == RenderMode.EXPORT, blurRadius, previewQuality, Invert, parent.Bounds)) {
+ if (blurImage != null) {
+ graphics.DrawImageUnscaled(blurImage, applyRect.Location);
+ }
+ }
return;
}
}
diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs
index f08eb086d..8e7321f9d 100644
--- a/Greenshot/Drawing/Surface.cs
+++ b/Greenshot/Drawing/Surface.cs
@@ -36,6 +36,7 @@ using Greenshot.Memento;
using IniFile;
using Greenshot.Drawing.Filters;
using System.Drawing.Drawing2D;
+using GreenshotPlugin.Controls;
namespace Greenshot.Drawing {
public delegate void SurfaceElementEventHandler(object source, DrawableContainerList element);
@@ -546,39 +547,46 @@ namespace Greenshot.Drawing {
}
public void ApplyBitmapEffect(Effects effect) {
- Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
- Bitmap newImage = null;
-
- Point offset = Point.Empty;
- switch (effect) {
- case Effects.Shadow:
- offset = new Point(6, 6);
- newImage = ImageHelper.CreateShadow((Bitmap)Image, 1f, 7, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
- break;
- case Effects.TornEdge:
- offset = new Point(5, 5);
- using (Bitmap tmpImage = ImageHelper.CreateTornEdge((Bitmap)Image)) {
- newImage = ImageHelper.CreateShadow(tmpImage, 1f, 6, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
- }
- break;
- case Effects.Border:
- newImage = ImageHelper.CreateBorder((Bitmap)Image, 2, Color.Black, Image.PixelFormat, out offset);
- break;
- case Effects.Grayscale:
- newImage = ImageHelper.CreateGrayscale((Bitmap)Image);
- break;
- }
-
- if (newImage != null) {
- // Make sure the elements move according to the offset the effect made the bitmap move
- elements.MoveBy(offset.X, offset.Y);
- // Make undoable
- MakeUndoable(new SurfaceBackgroundChangeMemento(this, offset), false);
- SetImage(newImage, false);
- Invalidate();
- if (SurfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size))) {
- SurfaceSizeChanged(this);
+ BackgroundForm backgroundForm = new BackgroundForm("Effect", "Please wait");
+ backgroundForm.Show();
+ Application.DoEvents();
+ try {
+ Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
+ Bitmap newImage = null;
+ Point offset = Point.Empty;
+ switch (effect) {
+ case Effects.Shadow:
+ offset = new Point(6, 6);
+ newImage = ImageHelper.CreateShadow((Bitmap)Image, 1f, 7, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
+ break;
+ case Effects.TornEdge:
+ offset = new Point(5, 5);
+ using (Bitmap tmpImage = ImageHelper.CreateTornEdge((Bitmap)Image)) {
+ newImage = ImageHelper.CreateShadow(tmpImage, 1f, 6, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
+ }
+ break;
+ case Effects.Border:
+ newImage = ImageHelper.CreateBorder((Bitmap)Image, 2, Color.Black, Image.PixelFormat, out offset);
+ break;
+ case Effects.Grayscale:
+ newImage = ImageHelper.CreateGrayscale((Bitmap)Image);
+ break;
}
+
+ if (newImage != null) {
+ // Make sure the elements move according to the offset the effect made the bitmap move
+ elements.MoveBy(offset.X, offset.Y);
+ // Make undoable
+ MakeUndoable(new SurfaceBackgroundChangeMemento(this, offset), false);
+ SetImage(newImage, false);
+ Invalidate();
+ if (SurfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size))) {
+ SurfaceSizeChanged(this);
+ }
+ }
+ } finally {
+ // Always close the background form
+ backgroundForm.CloseDialog();
}
}
@@ -595,6 +603,12 @@ namespace Greenshot.Drawing {
return false;
}
+ ///
+ /// Use to send any registered SurfaceMessageEventHandler a message, e.g. used for the notification area
+ ///
+ /// Who send
+ /// Type of message
+ /// Message itself
public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message) {
if (SurfaceMessage != null) {
SurfaceMessageEventArgs eventArgs = new SurfaceMessageEventArgs();
diff --git a/Greenshot/Helpers/OfficeInterop/OutlookWrapper.cs b/Greenshot/Helpers/OfficeInterop/OutlookWrapper.cs
index a45fe09df..773e2fd27 100644
--- a/Greenshot/Helpers/OfficeInterop/OutlookWrapper.cs
+++ b/Greenshot/Helpers/OfficeInterop/OutlookWrapper.cs
@@ -149,11 +149,13 @@ namespace Greenshot.Helpers.OfficeInterop {
LOG.DebugFormat("Got {0} inspectors to check", inspectors.Count);
for(int i=1; i <= inspectors.Count; i++) {
Inspector inspector = outlookApplication.Inspectors[i];
- if (inspector.Caption.StartsWith(inspectorCaption)) {
+ string currentCaption = inspector.Caption;
+ if (currentCaption.StartsWith(inspectorCaption)) {
try {
Item currentMail = inspector.CurrentItem;
if (currentMail != null && OlObjectClass.olMail.Equals(currentMail.Class)) {
if (currentMail != null && !currentMail.Sent) {
+ LOG.InfoFormat("Export requested to {0} exporting to {1}", inspectorCaption, currentCaption);
return ExportToInspector(inspector, tmpFile, attachmentName);
}
}
@@ -348,11 +350,8 @@ namespace Greenshot.Helpers.OfficeInterop {
exported = ExportToMail(outlookApplication, tmpFile, subject, attachmentName);
}
}
- if (exported) {
- // Wait to make sure the system "imported" the file
- // TODO: this should be handled differently some time
- Thread.Sleep(600);
- }
+ // assuming that the file isn't deleted right away...
+ // there used to be a sleep here
return exported;
} catch(Exception e) {
LOG.Error("Error while creating an outlook mail item: ", e);
diff --git a/GreenshotPlugin/Core/BitmapBuffer.cs b/GreenshotPlugin/Core/BitmapBuffer.cs
index 79f6a3fdc..019be7ed9 100644
--- a/GreenshotPlugin/Core/BitmapBuffer.cs
+++ b/GreenshotPlugin/Core/BitmapBuffer.cs
@@ -314,21 +314,40 @@ namespace GreenshotPlugin.Core {
* Retrieve the color at location x,y as an array
* Before the first time this is called the Lock() should be called once!
*/
- public int[] GetColorArrayAt(int x, int y) {
+ public byte[] GetColorArrayAt(int x, int y) {
if(x>=0 && y>=0 && x= 0 && y >= 0 && x < rect.Width && y < rect.Height) {
+ 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];
+ } else {
+ color[0] = 0;
+ color[1] = 0;
+ color[2] = 0;
+ color[3] = 0;
+ }
+ }
+
/**
* Set the color at location x,y as an array
* Before the first time this is called the Lock() should be called once!
*/
- public void SetColorArrayAt(int x, int y, int[] colors) {
+ public void SetColorArrayAt(int x, int y, byte[] colors) {
if(x>=0 && y>=0 && x
- /// Apply sourceBitmap with a blur to the targetGraphics
+ /// Create a new bitmap with the sourceBitmap blurred
///
- /// Target to draw to
/// Source to blur
- /// Area to blur
- /// Use full quality
+ /// Area to blur
+ /// Use best quality
/// Radius of the blur
/// Quality, use 1d for normal anything less skipps calculations
/// true if the blur needs to occur outside of the area
/// Rectangle limiting the area when using invert
- public static void ApplyBlur(Graphics targetGraphics, Bitmap sourceBitmap, Rectangle rect, bool export, int blurRadius, double previewQuality, bool invert, Rectangle parentBounds) {
- Rectangle applyRect = CreateIntersectRectangle(sourceBitmap.Size, rect, invert);
-
+ public static unsafe Bitmap CreateBlur(Bitmap sourceBitmap, Rectangle applyRect, bool useExportQuality, int blurRadius, double previewQuality, bool invert, Rectangle parentBounds) {
if (applyRect.Height <= 0 || applyRect.Width <= 0) {
- return;
+ return null;
}
// do nothing when nothing can be done!
if (blurRadius < 1) {
- return;
+ return null;
}
- Color nullColor = Color.White;
+
+ byte[] nullColor = new byte[] { 255, 255, 255, 255 };
if (sourceBitmap.PixelFormat == PixelFormat.Format32bppArgb) {
- nullColor = Color.Transparent;
+ nullColor = new byte[] { 0, 0, 0, 0 };
}
+ byte[] settingColor = new byte[4];
+ byte[] readingColor = new byte[4];
using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, applyRect, true)) {
bbbDest.Lock();
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, applyRect, false)) {
bbbSrc.Lock();
Random rand = new Random();
+ unchecked {
+ int r = blurRadius;
+ int[] w = CreateGaussianBlurRow(r);
+ int wlen = w.Length;
+ long* waSums = stackalloc long[wlen];
+ long* wcSums = stackalloc long[wlen];
+ long* aSums = stackalloc long[wlen];
+ long* rSums = stackalloc long[wlen];
+ long* gSums = stackalloc long[wlen];
+ long* bSums = stackalloc long[wlen];
+ for (int y = 0; y < applyRect.Height; ++y) {
+ long waSum = 0;
+ long wcSum = 0;
+ long aSum = 0;
+ long rSum = 0;
+ long gSum = 0;
+ long bSum = 0;
- int r = blurRadius;
- int[] w = CreateGaussianBlurRow(r);
- int wlen = w.Length;
- long[] waSums = new long[wlen];
- long[] wcSums = new long[wlen];
- long[] aSums = new long[wlen];
- long[] rSums = new long[wlen];
- long[] gSums = new long[wlen];
- long[] bSums = new long[wlen];
- for (int y = 0; y < applyRect.Height; ++y) {
- long waSum = 0;
- long wcSum = 0;
- long aSum = 0;
- long rSum = 0;
- long gSum = 0;
- long bSum = 0;
+ for (int wx = 0; wx < wlen; ++wx) {
+ int srcX = wx - r;
+ waSums[wx] = 0;
+ wcSums[wx] = 0;
+ aSums[wx] = 0;
+ rSums[wx] = 0;
+ gSums[wx] = 0;
+ bSums[wx] = 0;
- for (int wx = 0; wx < wlen; ++wx) {
- int srcX = wx - r;
- waSums[wx] = 0;
- wcSums[wx] = 0;
- aSums[wx] = 0;
- rSums[wx] = 0;
- gSums[wx] = 0;
- bSums[wx] = 0;
+ if (srcX >= 0 && srcX < bbbDest.Width) {
+ for (int wy = 0; wy < wlen; ++wy) {
+ int srcY = y + wy - r;
- if (srcX >= 0 && srcX < bbbDest.Width) {
- for (int wy = 0; wy < wlen; ++wy) {
- int srcY = y + wy - r;
+ if (srcY >= 0 && srcY < bbbDest.Height) {
+ bbbSrc.GetColorIn(srcX, srcY, readingColor);
+ int wp = w[wy];
- if (srcY >= 0 && srcY < bbbDest.Height) {
- int[] colors = bbbSrc.GetColorArrayAt(srcX, srcY);
- int wp = w[wy];
+ waSums[wx] += wp;
+ wp *= readingColor[0] + (readingColor[0] >> 7);
+ wcSums[wx] += wp;
+ wp >>= 8;
- waSums[wx] += wp;
- wp *= colors[0] + (colors[0] >> 7);
- wcSums[wx] += wp;
- wp >>= 8;
-
- aSums[wx] += wp * colors[0];
- rSums[wx] += wp * colors[1];
- gSums[wx] += wp * colors[2];
- bSums[wx] += wp * colors[3];
+ aSums[wx] += wp * readingColor[0];
+ rSums[wx] += wp * readingColor[1];
+ gSums[wx] += wp * readingColor[2];
+ bSums[wx] += wp * readingColor[3];
+ }
}
+
+ int wwx = w[wx];
+ waSum += wwx * waSums[wx];
+ wcSum += wwx * wcSums[wx];
+ aSum += wwx * aSums[wx];
+ rSum += wwx * rSums[wx];
+ gSum += wwx * gSums[wx];
+ bSum += wwx * bSums[wx];
}
-
- int wwx = w[wx];
- waSum += wwx * waSums[wx];
- wcSum += wwx * wcSums[wx];
- aSum += wwx * aSums[wx];
- rSum += wwx * rSums[wx];
- gSum += wwx * gSums[wx];
- bSum += wwx * bSums[wx];
- }
- }
-
- wcSum >>= 8;
-
- if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
- if (waSum == 0 || wcSum == 0) {
- bbbDest.SetColorAt(0, y, nullColor);
- } else {
- int alpha = (int)(aSum / waSum);
- int red = (int)(rSum / wcSum);
- int green = (int)(gSum / wcSum);
- int blue = (int)(bSum / wcSum);
- bbbDest.SetColorAt(0, y, Color.FromArgb(alpha, red, green, blue));
- }
- }
-
- for (int x = 1; x < applyRect.Width; ++x) {
- for (int i = 0; i < wlen - 1; ++i) {
- waSums[i] = waSums[i + 1];
- wcSums[i] = wcSums[i + 1];
- aSums[i] = aSums[i + 1];
- rSums[i] = rSums[i + 1];
- gSums[i] = gSums[i + 1];
- bSums[i] = bSums[i + 1];
- }
-
- waSum = 0;
- wcSum = 0;
- aSum = 0;
- rSum = 0;
- gSum = 0;
- bSum = 0;
-
- int wx;
- for (wx = 0; wx < wlen - 1; ++wx) {
- long wwx = (long)w[wx];
- waSum += wwx * waSums[wx];
- wcSum += wwx * wcSums[wx];
- aSum += wwx * aSums[wx];
- rSum += wwx * rSums[wx];
- gSum += wwx * gSums[wx];
- bSum += wwx * bSums[wx];
- }
-
- wx = wlen - 1;
-
- waSums[wx] = 0;
- wcSums[wx] = 0;
- aSums[wx] = 0;
- rSums[wx] = 0;
- gSums[wx] = 0;
- bSums[wx] = 0;
-
- int srcX = x + wx - r;
-
- if (srcX >= 0 && srcX < applyRect.Width) {
- for (int wy = 0; wy < wlen; ++wy) {
- int srcY = y + wy - r;
- // only when in EDIT mode, ignore some pixels depending on preview quality
- if ((export || rand.NextDouble() < previewQuality) && srcY >= 0 && srcY < applyRect.Height) {
- int[] colors = bbbSrc.GetColorArrayAt(srcX, srcY);
- int wp = w[wy];
-
- waSums[wx] += wp;
- wp *= colors[0] + (colors[0] >> 7);
- wcSums[wx] += wp;
- wp >>= 8;
-
- aSums[wx] += wp * (long)colors[0];
- rSums[wx] += wp * (long)colors[1];
- gSums[wx] += wp * (long)colors[2];
- bSums[wx] += wp * (long)colors[3];
- }
- }
-
- int wr = w[wx];
- waSum += (long)wr * waSums[wx];
- wcSum += (long)wr * wcSums[wx];
- aSum += (long)wr * aSums[wx];
- rSum += (long)wr * rSums[wx];
- gSum += (long)wr * gSums[wx];
- bSum += (long)wr * bSums[wx];
}
wcSum >>= 8;
+
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
if (waSum == 0 || wcSum == 0) {
- bbbDest.SetColorAt(x, y, nullColor);
+ bbbDest.SetUncheckedColorArrayAt(0, y, nullColor);
} else {
- int alpha = (int)(aSum / waSum);
- int red = (int)(rSum / wcSum);
- int green = (int)(gSum / wcSum);
- int blue = (int)(bSum / wcSum);
- bbbDest.SetColorAt(x, y, Color.FromArgb(alpha, red, green, blue));
+ settingColor[0] = (byte)(aSum / waSum);
+ settingColor[1] = (byte)(rSum / wcSum);
+ settingColor[2] = (byte)(gSum / wcSum);
+ settingColor[3] = (byte)(bSum / wcSum);
+ bbbDest.SetUncheckedColorArrayAt(0, y, settingColor);
+ }
+ }
+
+ for (int x = 1; x < applyRect.Width; ++x) {
+ for (int i = 0; i < wlen - 1; ++i) {
+ waSums[i] = waSums[i + 1];
+ wcSums[i] = wcSums[i + 1];
+ aSums[i] = aSums[i + 1];
+ rSums[i] = rSums[i + 1];
+ gSums[i] = gSums[i + 1];
+ bSums[i] = bSums[i + 1];
+ }
+
+ waSum = 0;
+ wcSum = 0;
+ aSum = 0;
+ rSum = 0;
+ gSum = 0;
+ bSum = 0;
+
+ int wx;
+ for (wx = 0; wx < wlen - 1; ++wx) {
+ long wwx = (long)w[wx];
+ waSum += wwx * waSums[wx];
+ wcSum += wwx * wcSums[wx];
+ aSum += wwx * aSums[wx];
+ rSum += wwx * rSums[wx];
+ gSum += wwx * gSums[wx];
+ bSum += wwx * bSums[wx];
+ }
+
+ wx = wlen - 1;
+
+ waSums[wx] = 0;
+ wcSums[wx] = 0;
+ aSums[wx] = 0;
+ rSums[wx] = 0;
+ gSums[wx] = 0;
+ bSums[wx] = 0;
+
+ int srcX = x + wx - r;
+
+ if (srcX >= 0 && srcX < applyRect.Width) {
+ for (int wy = 0; wy < wlen; ++wy) {
+ int srcY = y + wy - r;
+ // only when in EDIT mode, ignore some pixels depending on preview quality
+ if ((useExportQuality || rand.NextDouble() < previewQuality) && srcY >= 0 && srcY < applyRect.Height) {
+ int wp = w[wy];
+ waSums[wx] += wp;
+ bbbSrc.GetColorIn(srcX, srcY, readingColor);
+ wp *= readingColor[0] + (readingColor[0] >> 7);
+ wcSums[wx] += wp;
+ wp >>= 8;
+
+ aSums[wx] += wp * readingColor[0];
+ rSums[wx] += wp * readingColor[1];
+ gSums[wx] += wp * readingColor[2];
+ bSums[wx] += wp * readingColor[3];
+ }
+ }
+
+ int wr = w[wx];
+ waSum += wr * waSums[wx];
+ wcSum += wr * wcSums[wx];
+ aSum += wr * aSums[wx];
+ rSum += wr * rSums[wx];
+ gSum += wr * gSums[wx];
+ bSum += wr * bSums[wx];
+ }
+
+ wcSum >>= 8;
+ if (parentBounds.Contains(applyRect.Left + x, applyRect.Top + y) ^ invert) {
+ if (waSum == 0 || wcSum == 0) {
+ bbbDest.SetUncheckedColorArrayAt(x, y, nullColor);
+ } else {
+ settingColor[0] = (byte)(aSum / waSum);
+ settingColor[1] = (byte)(rSum / wcSum);
+ settingColor[2] = (byte)(gSum / wcSum);
+ settingColor[3] = (byte)(bSum / wcSum);
+ bbbDest.SetUncheckedColorArrayAt(x, y, settingColor);
+ }
}
}
}
}
}
- bbbDest.DrawTo(targetGraphics, applyRect.Location);
+ bbbDest.Unlock();
+ return bbbDest.Bitmap;
}
}
@@ -608,12 +609,24 @@ namespace GreenshotPlugin.Core {
cm.Matrix22 = 0;
cm.Matrix33 = darkness;
ia.SetColorMatrix(cm);
- Point shadowLocation = new Point(shadowSize, shadowSize);
- graphics.DrawImage(sourceBitmap, new Rectangle(shadowLocation, sourceBitmap.Size), 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia);
+ Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size);
+ graphics.DrawImage(sourceBitmap, shadowRectangle, 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia);
+
+ // Only do the blur on the edges
+ //Rectangle blurRectangle = new Rectangle(shadowSize + 30, shadowSize + 30, sourceBitmap.Width - 60, sourceBitmap.Height - 60);
+ //Rectangle applyRect = ImageHelper.CreateIntersectRectangle(newImage.Size, blurRectangle, true);
+ //LOG.DebugFormat("blurRect = {0} - applyRect = {1}", blurRectangle, applyRect);
+ //using (Bitmap blurImage = ImageHelper.CreateBlur(newImage, applyRect, true, shadowSize, 1d, true, blurRectangle)) {
+ // if (blurImage != null) {
+ // graphics.DrawImageUnscaled(blurImage, applyRect.Location);
+ // }
+ //}
// blur "shadow", apply to whole new image
- Rectangle applyRectangle = new Rectangle(Point.Empty, newImage.Size);
- ApplyBlur(graphics, newImage, applyRectangle, true, shadowSize, 1d, false, applyRectangle);
+ Rectangle newImageRectangle = new Rectangle(0, 0, newImage.Width, newImage.Height);
+ using (Bitmap blurImage = CreateBlur(newImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle)) {
+ graphics.DrawImageUnscaled(blurImage, newImageRectangle.Location);
+ }
// draw original with a TextureBrush so we have nice antialiasing!
using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) {
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index 53a66cc0f..5effc3244 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -669,7 +669,7 @@ namespace GreenshotPlugin.Core {
User32.BringWindowToTop(this.hWnd);
User32.SetForegroundWindow(this.hWnd);
// Make sure windows has time to perform the action
- Thread.Sleep(100);
+ Application.DoEvents();
}
public WindowStyleFlags WindowStyle {