mirror of
https://github.com/greenshot/greenshot
synced 2025-07-14 00:53:51 -07:00
Optimizations
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1650 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
cbf2fae360
commit
7591fa993b
6 changed files with 259 additions and 200 deletions
|
@ -39,8 +39,12 @@ namespace Greenshot.Drawing.Filters {
|
||||||
public unsafe override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
|
public unsafe override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) {
|
||||||
int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
|
int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
|
||||||
double previewQuality = GetFieldValueAsDouble(FieldType.PREVIEW_QUALITY);
|
double previewQuality = GetFieldValueAsDouble(FieldType.PREVIEW_QUALITY);
|
||||||
|
Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
|
||||||
ImageHelper.ApplyBlur(graphics, applyBitmap, rect, renderMode == RenderMode.EXPORT, blurRadius, previewQuality, Invert, parent.Bounds);
|
using (Bitmap blurImage = ImageHelper.CreateBlur(applyBitmap, applyRect, renderMode == RenderMode.EXPORT, blurRadius, previewQuality, Invert, parent.Bounds)) {
|
||||||
|
if (blurImage != null) {
|
||||||
|
graphics.DrawImageUnscaled(blurImage, applyRect.Location);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ using Greenshot.Memento;
|
||||||
using IniFile;
|
using IniFile;
|
||||||
using Greenshot.Drawing.Filters;
|
using Greenshot.Drawing.Filters;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
|
||||||
namespace Greenshot.Drawing {
|
namespace Greenshot.Drawing {
|
||||||
public delegate void SurfaceElementEventHandler(object source, DrawableContainerList element);
|
public delegate void SurfaceElementEventHandler(object source, DrawableContainerList element);
|
||||||
|
@ -546,39 +547,46 @@ namespace Greenshot.Drawing {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyBitmapEffect(Effects effect) {
|
public void ApplyBitmapEffect(Effects effect) {
|
||||||
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
|
BackgroundForm backgroundForm = new BackgroundForm("Effect", "Please wait");
|
||||||
Bitmap newImage = null;
|
backgroundForm.Show();
|
||||||
|
Application.DoEvents();
|
||||||
Point offset = Point.Empty;
|
try {
|
||||||
switch (effect) {
|
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
|
||||||
case Effects.Shadow:
|
Bitmap newImage = null;
|
||||||
offset = new Point(6, 6);
|
Point offset = Point.Empty;
|
||||||
newImage = ImageHelper.CreateShadow((Bitmap)Image, 1f, 7, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
|
switch (effect) {
|
||||||
break;
|
case Effects.Shadow:
|
||||||
case Effects.TornEdge:
|
offset = new Point(6, 6);
|
||||||
offset = new Point(5, 5);
|
newImage = ImageHelper.CreateShadow((Bitmap)Image, 1f, 7, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
|
||||||
using (Bitmap tmpImage = ImageHelper.CreateTornEdge((Bitmap)Image)) {
|
break;
|
||||||
newImage = ImageHelper.CreateShadow(tmpImage, 1f, 6, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
|
case Effects.TornEdge:
|
||||||
}
|
offset = new Point(5, 5);
|
||||||
break;
|
using (Bitmap tmpImage = ImageHelper.CreateTornEdge((Bitmap)Image)) {
|
||||||
case Effects.Border:
|
newImage = ImageHelper.CreateShadow(tmpImage, 1f, 6, offset, PixelFormat.Format24bppRgb); //Image.PixelFormat);
|
||||||
newImage = ImageHelper.CreateBorder((Bitmap)Image, 2, Color.Black, Image.PixelFormat, out offset);
|
}
|
||||||
break;
|
break;
|
||||||
case Effects.Grayscale:
|
case Effects.Border:
|
||||||
newImage = ImageHelper.CreateGrayscale((Bitmap)Image);
|
newImage = ImageHelper.CreateBorder((Bitmap)Image, 2, Color.Black, Image.PixelFormat, out offset);
|
||||||
break;
|
break;
|
||||||
}
|
case Effects.Grayscale:
|
||||||
|
newImage = ImageHelper.CreateGrayscale((Bitmap)Image);
|
||||||
if (newImage != null) {
|
break;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use to send any registered SurfaceMessageEventHandler a message, e.g. used for the notification area
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">Who send</param>
|
||||||
|
/// <param name="messageType">Type of message</param>
|
||||||
|
/// <param name="message">Message itself</param>
|
||||||
public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message) {
|
public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message) {
|
||||||
if (SurfaceMessage != null) {
|
if (SurfaceMessage != null) {
|
||||||
SurfaceMessageEventArgs eventArgs = new SurfaceMessageEventArgs();
|
SurfaceMessageEventArgs eventArgs = new SurfaceMessageEventArgs();
|
||||||
|
|
|
@ -149,11 +149,13 @@ namespace Greenshot.Helpers.OfficeInterop {
|
||||||
LOG.DebugFormat("Got {0} inspectors to check", inspectors.Count);
|
LOG.DebugFormat("Got {0} inspectors to check", inspectors.Count);
|
||||||
for(int i=1; i <= inspectors.Count; i++) {
|
for(int i=1; i <= inspectors.Count; i++) {
|
||||||
Inspector inspector = outlookApplication.Inspectors[i];
|
Inspector inspector = outlookApplication.Inspectors[i];
|
||||||
if (inspector.Caption.StartsWith(inspectorCaption)) {
|
string currentCaption = inspector.Caption;
|
||||||
|
if (currentCaption.StartsWith(inspectorCaption)) {
|
||||||
try {
|
try {
|
||||||
Item currentMail = inspector.CurrentItem;
|
Item currentMail = inspector.CurrentItem;
|
||||||
if (currentMail != null && OlObjectClass.olMail.Equals(currentMail.Class)) {
|
if (currentMail != null && OlObjectClass.olMail.Equals(currentMail.Class)) {
|
||||||
if (currentMail != null && !currentMail.Sent) {
|
if (currentMail != null && !currentMail.Sent) {
|
||||||
|
LOG.InfoFormat("Export requested to {0} exporting to {1}", inspectorCaption, currentCaption);
|
||||||
return ExportToInspector(inspector, tmpFile, attachmentName);
|
return ExportToInspector(inspector, tmpFile, attachmentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,11 +350,8 @@ namespace Greenshot.Helpers.OfficeInterop {
|
||||||
exported = ExportToMail(outlookApplication, tmpFile, subject, attachmentName);
|
exported = ExportToMail(outlookApplication, tmpFile, subject, attachmentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exported) {
|
// assuming that the file isn't deleted right away...
|
||||||
// Wait to make sure the system "imported" the file
|
// there used to be a sleep here
|
||||||
// TODO: this should be handled differently some time
|
|
||||||
Thread.Sleep(600);
|
|
||||||
}
|
|
||||||
return exported;
|
return exported;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
LOG.Error("Error while creating an outlook mail item: ", e);
|
LOG.Error("Error while creating an outlook mail item: ", e);
|
||||||
|
|
|
@ -314,21 +314,40 @@ namespace GreenshotPlugin.Core {
|
||||||
* Retrieve the color at location x,y as an array
|
* Retrieve the color at location x,y as an array
|
||||||
* Before the first time this is called the Lock() should be called once!
|
* 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<rect.Width && y<rect.Height) {
|
if(x>=0 && y>=0 && x<rect.Width && y<rect.Height) {
|
||||||
int offset = x*bytesPerPixel+y*stride;
|
int offset = x*bytesPerPixel+y*stride;
|
||||||
int a = (aIndex==-1) ? 255 : (int)pointer[aIndex+offset];
|
byte a = (aIndex==-1) ? (byte)255 : (byte)pointer[aIndex+offset];
|
||||||
return new int[]{a, pointer[rIndex+offset], pointer[gIndex+offset], pointer[bIndex+offset]};
|
return new byte[] { a, pointer[rIndex + offset], pointer[gIndex + offset], pointer[bIndex + offset] };
|
||||||
} else {
|
} else {
|
||||||
return new int[]{0,0,0,0};
|
return new byte[] { 0, 0, 0, 0 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 GetColorIn(int x, int y, byte[] color) {
|
||||||
|
if (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
|
* Set the color at location x,y as an array
|
||||||
* Before the first time this is called the Lock() should be called once!
|
* 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<rect.Width && y<rect.Height) {
|
if(x>=0 && y>=0 && x<rect.Width && y<rect.Height) {
|
||||||
int offset = x*bytesPerPixel+y*stride;
|
int offset = x*bytesPerPixel+y*stride;
|
||||||
if(aIndex!=-1) pointer[aIndex+offset] = (byte)colors[0];
|
if(aIndex!=-1) pointer[aIndex+offset] = (byte)colors[0];
|
||||||
|
@ -337,7 +356,17 @@ namespace GreenshotPlugin.Core {
|
||||||
pointer[bIndex+offset] = (byte)colors[3];
|
pointer[bIndex+offset] = (byte)colors[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 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 SetUncheckedColorArrayAt(int x, int y, byte[] colors) {
|
||||||
|
int offset = x * bytesPerPixel + y * stride;
|
||||||
|
if (aIndex != -1) pointer[aIndex + offset] = (byte)colors[0];
|
||||||
|
pointer[rIndex + offset] = (byte)colors[1];
|
||||||
|
pointer[gIndex + offset] = (byte)colors[2];
|
||||||
|
pointer[bIndex + offset] = (byte)colors[3];
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Set some internal values for accessing the bitmap according to the PixelFormat
|
* Set some internal values for accessing the bitmap according to the PixelFormat
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -368,191 +368,192 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply sourceBitmap with a blur to the targetGraphics
|
/// Create a new bitmap with the sourceBitmap blurred
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="targetGraphics">Target to draw to</param>
|
|
||||||
/// <param name="sourceBitmap">Source to blur</param>
|
/// <param name="sourceBitmap">Source to blur</param>
|
||||||
/// <param name="rect">Area to blur</param>
|
/// <param name="applyRect">Area to blur</param>
|
||||||
/// <param name="export">Use full quality</param>
|
/// <param name="useExportQuality">Use best quality</param>
|
||||||
/// <param name="blurRadius">Radius of the blur</param>
|
/// <param name="blurRadius">Radius of the blur</param>
|
||||||
/// <param name="previewQuality">Quality, use 1d for normal anything less skipps calculations</param>
|
/// <param name="previewQuality">Quality, use 1d for normal anything less skipps calculations</param>
|
||||||
/// <param name="invert">true if the blur needs to occur outside of the area</param>
|
/// <param name="invert">true if the blur needs to occur outside of the area</param>
|
||||||
/// <param name="parentBounds">Rectangle limiting the area when using invert</param>
|
/// <param name="parentBounds">Rectangle limiting the area when using invert</param>
|
||||||
public static void ApplyBlur(Graphics targetGraphics, Bitmap sourceBitmap, Rectangle rect, bool export, int blurRadius, double previewQuality, bool invert, Rectangle parentBounds) {
|
public static unsafe Bitmap CreateBlur(Bitmap sourceBitmap, Rectangle applyRect, bool useExportQuality, int blurRadius, double previewQuality, bool invert, Rectangle parentBounds) {
|
||||||
Rectangle applyRect = CreateIntersectRectangle(sourceBitmap.Size, rect, invert);
|
|
||||||
|
|
||||||
if (applyRect.Height <= 0 || applyRect.Width <= 0) {
|
if (applyRect.Height <= 0 || applyRect.Width <= 0) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
// do nothing when nothing can be done!
|
// do nothing when nothing can be done!
|
||||||
if (blurRadius < 1) {
|
if (blurRadius < 1) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
Color nullColor = Color.White;
|
|
||||||
|
byte[] nullColor = new byte[] { 255, 255, 255, 255 };
|
||||||
if (sourceBitmap.PixelFormat == PixelFormat.Format32bppArgb) {
|
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)) {
|
using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, applyRect, true)) {
|
||||||
bbbDest.Lock();
|
bbbDest.Lock();
|
||||||
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, applyRect, false)) {
|
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, applyRect, false)) {
|
||||||
bbbSrc.Lock();
|
bbbSrc.Lock();
|
||||||
Random rand = new Random();
|
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;
|
for (int wx = 0; wx < wlen; ++wx) {
|
||||||
int[] w = CreateGaussianBlurRow(r);
|
int srcX = wx - r;
|
||||||
int wlen = w.Length;
|
waSums[wx] = 0;
|
||||||
long[] waSums = new long[wlen];
|
wcSums[wx] = 0;
|
||||||
long[] wcSums = new long[wlen];
|
aSums[wx] = 0;
|
||||||
long[] aSums = new long[wlen];
|
rSums[wx] = 0;
|
||||||
long[] rSums = new long[wlen];
|
gSums[wx] = 0;
|
||||||
long[] gSums = new long[wlen];
|
bSums[wx] = 0;
|
||||||
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) {
|
if (srcX >= 0 && srcX < bbbDest.Width) {
|
||||||
int srcX = wx - r;
|
for (int wy = 0; wy < wlen; ++wy) {
|
||||||
waSums[wx] = 0;
|
int srcY = y + wy - r;
|
||||||
wcSums[wx] = 0;
|
|
||||||
aSums[wx] = 0;
|
|
||||||
rSums[wx] = 0;
|
|
||||||
gSums[wx] = 0;
|
|
||||||
bSums[wx] = 0;
|
|
||||||
|
|
||||||
if (srcX >= 0 && srcX < bbbDest.Width) {
|
if (srcY >= 0 && srcY < bbbDest.Height) {
|
||||||
for (int wy = 0; wy < wlen; ++wy) {
|
bbbSrc.GetColorIn(srcX, srcY, readingColor);
|
||||||
int srcY = y + wy - r;
|
int wp = w[wy];
|
||||||
|
|
||||||
if (srcY >= 0 && srcY < bbbDest.Height) {
|
waSums[wx] += wp;
|
||||||
int[] colors = bbbSrc.GetColorArrayAt(srcX, srcY);
|
wp *= readingColor[0] + (readingColor[0] >> 7);
|
||||||
int wp = w[wy];
|
wcSums[wx] += wp;
|
||||||
|
wp >>= 8;
|
||||||
|
|
||||||
waSums[wx] += wp;
|
aSums[wx] += wp * readingColor[0];
|
||||||
wp *= colors[0] + (colors[0] >> 7);
|
rSums[wx] += wp * readingColor[1];
|
||||||
wcSums[wx] += wp;
|
gSums[wx] += wp * readingColor[2];
|
||||||
wp >>= 8;
|
bSums[wx] += wp * readingColor[3];
|
||||||
|
}
|
||||||
aSums[wx] += wp * colors[0];
|
|
||||||
rSums[wx] += wp * colors[1];
|
|
||||||
gSums[wx] += wp * colors[2];
|
|
||||||
bSums[wx] += wp * colors[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;
|
wcSum >>= 8;
|
||||||
|
|
||||||
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
|
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
|
||||||
if (waSum == 0 || wcSum == 0) {
|
if (waSum == 0 || wcSum == 0) {
|
||||||
bbbDest.SetColorAt(x, y, nullColor);
|
bbbDest.SetUncheckedColorArrayAt(0, y, nullColor);
|
||||||
} else {
|
} else {
|
||||||
int alpha = (int)(aSum / waSum);
|
settingColor[0] = (byte)(aSum / waSum);
|
||||||
int red = (int)(rSum / wcSum);
|
settingColor[1] = (byte)(rSum / wcSum);
|
||||||
int green = (int)(gSum / wcSum);
|
settingColor[2] = (byte)(gSum / wcSum);
|
||||||
int blue = (int)(bSum / wcSum);
|
settingColor[3] = (byte)(bSum / wcSum);
|
||||||
bbbDest.SetColorAt(x, y, Color.FromArgb(alpha, red, green, blue));
|
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.Matrix22 = 0;
|
||||||
cm.Matrix33 = darkness;
|
cm.Matrix33 = darkness;
|
||||||
ia.SetColorMatrix(cm);
|
ia.SetColorMatrix(cm);
|
||||||
Point shadowLocation = new Point(shadowSize, shadowSize);
|
Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size);
|
||||||
graphics.DrawImage(sourceBitmap, new Rectangle(shadowLocation, sourceBitmap.Size), 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia);
|
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
|
// blur "shadow", apply to whole new image
|
||||||
Rectangle applyRectangle = new Rectangle(Point.Empty, newImage.Size);
|
Rectangle newImageRectangle = new Rectangle(0, 0, newImage.Width, newImage.Height);
|
||||||
ApplyBlur(graphics, newImage, applyRectangle, true, shadowSize, 1d, false, applyRectangle);
|
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!
|
// draw original with a TextureBrush so we have nice antialiasing!
|
||||||
using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) {
|
using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) {
|
||||||
|
|
|
@ -669,7 +669,7 @@ namespace GreenshotPlugin.Core {
|
||||||
User32.BringWindowToTop(this.hWnd);
|
User32.BringWindowToTop(this.hWnd);
|
||||||
User32.SetForegroundWindow(this.hWnd);
|
User32.SetForegroundWindow(this.hWnd);
|
||||||
// Make sure windows has time to perform the action
|
// Make sure windows has time to perform the action
|
||||||
Thread.Sleep(100);
|
Application.DoEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WindowStyleFlags WindowStyle {
|
public WindowStyleFlags WindowStyle {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue