diff --git a/Greenshot/Drawing/ArrowContainer.cs b/Greenshot/Drawing/ArrowContainer.cs index dfae20645..64926b8e5 100644 --- a/Greenshot/Drawing/ArrowContainer.cs +++ b/Greenshot/Drawing/ArrowContainer.cs @@ -102,11 +102,12 @@ namespace Greenshot.Drawing { using (Pen pen = new Pen(Color.White)) { pen.Width = lineThickness; SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen); - GraphicsPath path = new GraphicsPath(); - path.AddLine(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); - Rectangle drawingBounds = Rectangle.Round(path.GetBounds(new Matrix(), pen)); - drawingBounds.Inflate(2,2); - return drawingBounds; + using (GraphicsPath path = new GraphicsPath()) { + path.AddLine(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); + Rectangle drawingBounds = Rectangle.Round(path.GetBounds(new Matrix(), pen)); + drawingBounds.Inflate(2, 2); + return drawingBounds; + } } } else { return Rectangle.Empty; @@ -120,9 +121,10 @@ namespace Greenshot.Drawing { using (Pen pen = new Pen(Color.White)) { pen.Width = lineThickness; SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen); - GraphicsPath path = new GraphicsPath(); - path.AddLine(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); - return path.IsOutlineVisible(x,y, pen); + using (GraphicsPath path = new GraphicsPath()) { + path.AddLine(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); + return path.IsOutlineVisible(x, y, pen); + } } } else { return false; diff --git a/Greenshot/Drawing/EllipseContainer.cs b/Greenshot/Drawing/EllipseContainer.cs index 86dcb8836..5e40cefc6 100644 --- a/Greenshot/Drawing/EllipseContainer.cs +++ b/Greenshot/Drawing/EllipseContainer.cs @@ -103,9 +103,10 @@ namespace Greenshot.Drawing { if (lineThickness > 0) { using (Pen pen = new Pen(Color.White)) { pen.Width = lineThickness; - GraphicsPath path = new GraphicsPath(); - path.AddEllipse(rect); - return path.IsOutlineVisible(x, y, pen); + using (GraphicsPath path = new GraphicsPath()) { + path.AddEllipse(rect); + return path.IsOutlineVisible(x, y, pen); + } } } else { return false; diff --git a/Greenshot/Drawing/LineContainer.cs b/Greenshot/Drawing/LineContainer.cs index 0ad6099d0..889b7c51a 100644 --- a/Greenshot/Drawing/LineContainer.cs +++ b/Greenshot/Drawing/LineContainer.cs @@ -98,9 +98,10 @@ namespace Greenshot.Drawing { if (lineThickness > 0) { using (Pen pen = new Pen(Color.White)) { pen.Width = lineThickness; - GraphicsPath path = new GraphicsPath(); - path.AddLine(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); - return path.IsOutlineVisible(x,y, pen); + using (GraphicsPath path = new GraphicsPath()) { + path.AddLine(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); + return path.IsOutlineVisible(x, y, pen); + } } } else { return false; diff --git a/Greenshot/Drawing/RectangleContainer.cs b/Greenshot/Drawing/RectangleContainer.cs index 35c02c353..7f28848a8 100644 --- a/Greenshot/Drawing/RectangleContainer.cs +++ b/Greenshot/Drawing/RectangleContainer.cs @@ -100,9 +100,10 @@ namespace Greenshot.Drawing { if (lineThickness > 0) { using (Pen pen = new Pen(Color.White)) { pen.Width = lineThickness; - GraphicsPath path = new GraphicsPath(); - path.AddRectangle(rect); - return path.IsOutlineVisible(x, y, pen); + using (GraphicsPath path = new GraphicsPath()) { + path.AddRectangle(rect); + return path.IsOutlineVisible(x, y, pen); + } } } else { return false; diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs index 216686b5b..75ef447a0 100644 --- a/Greenshot/Drawing/Surface.cs +++ b/Greenshot/Drawing/Surface.cs @@ -567,6 +567,7 @@ namespace Greenshot.Drawing { // Make undoable MakeUndoable(new SurfaceCropMemento(this, imageRectangle), false); SetImage(newImage, false); + Invalidate(); } } diff --git a/Greenshot/Forms/ImageEditorForm.cs b/Greenshot/Forms/ImageEditorForm.cs index 609b0ded3..b6957d744 100644 --- a/Greenshot/Forms/ImageEditorForm.cs +++ b/Greenshot/Forms/ImageEditorForm.cs @@ -1171,10 +1171,12 @@ namespace Greenshot { void TornEdgeToolStripMenuItemClick(object sender, EventArgs e) { surface.ApplyBitmapEffect(Effects.TornEdge); + updateUndoRedoSurfaceDependencies(); } void ShadowToolStripMenuItemClick(object sender, EventArgs e) { surface.ApplyBitmapEffect(Effects.Shadow); + updateUndoRedoSurfaceDependencies(); } } } diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs index dcfa72b51..9a902a4b9 100644 --- a/GreenshotPlugin/Core/ImageHelper.cs +++ b/GreenshotPlugin/Core/ImageHelper.cs @@ -311,62 +311,64 @@ namespace GreenshotPlugin.Core { } catch (Exception ex) { LOG.Warn("An exception occured while setting the resolution.", ex); } - GraphicsPath path = new GraphicsPath(); - Random random = new Random(); - int regionWidth = 20; - int regionHeight = 20; - int HorizontalRegions = (int)(sourceBitmap.Width / regionWidth); - int VerticalRegions = (int)(sourceBitmap.Height / regionHeight); - int distance = 12; + using (GraphicsPath path = new GraphicsPath()) { + Random random = new Random(); + int regionWidth = 20; + int regionHeight = 20; + int HorizontalRegions = (int)(sourceBitmap.Width / regionWidth); + int VerticalRegions = (int)(sourceBitmap.Height / regionHeight); + int distance = 12; - // Start - Point previousEndingPoint = new Point(regionWidth, random.Next(1, distance)); - Point newEndingPoint; - // Top - for (int i = 0; i < HorizontalRegions; i++) { - int x = (int)previousEndingPoint.X + regionWidth; - int y = random.Next(1, distance); - newEndingPoint = new Point(x, y); - path.AddLine(previousEndingPoint, newEndingPoint); - previousEndingPoint = newEndingPoint; - } + // Start + Point previousEndingPoint = new Point(regionWidth, random.Next(1, distance)); + Point newEndingPoint; + // Top + for (int i = 0; i < HorizontalRegions; i++) { + int x = (int)previousEndingPoint.X + regionWidth; + int y = random.Next(1, distance); + newEndingPoint = new Point(x, y); + path.AddLine(previousEndingPoint, newEndingPoint); + previousEndingPoint = newEndingPoint; + } - // Right - for (int i = 0; i < VerticalRegions; i++) { - int x = sourceBitmap.Width - random.Next(1, distance); - int y = (int)previousEndingPoint.Y + regionHeight; - newEndingPoint = new Point(x, y); - path.AddLine(previousEndingPoint, newEndingPoint); - previousEndingPoint = newEndingPoint; - } + // Right + for (int i = 0; i < VerticalRegions; i++) { + int x = sourceBitmap.Width - random.Next(1, distance); + int y = (int)previousEndingPoint.Y + regionHeight; + newEndingPoint = new Point(x, y); + path.AddLine(previousEndingPoint, newEndingPoint); + previousEndingPoint = newEndingPoint; + } - // Bottom - for (int i = 0; i < HorizontalRegions; i++) { - int x = (int)previousEndingPoint.X - regionWidth; - int y = sourceBitmap.Height - random.Next(1, distance); - newEndingPoint = new Point(x, y); - path.AddLine(previousEndingPoint, newEndingPoint); - previousEndingPoint = newEndingPoint; - } + // Bottom + for (int i = 0; i < HorizontalRegions; i++) { + int x = (int)previousEndingPoint.X - regionWidth; + int y = sourceBitmap.Height - random.Next(1, distance); + newEndingPoint = new Point(x, y); + path.AddLine(previousEndingPoint, newEndingPoint); + previousEndingPoint = newEndingPoint; + } - // Left - for (int i = 0; i < VerticalRegions; i++) { - int x = random.Next(1, distance); - int y = (int)previousEndingPoint.Y - regionHeight; - newEndingPoint = new Point(x, y); - path.AddLine(previousEndingPoint, newEndingPoint); - previousEndingPoint = newEndingPoint; - } - path.CloseFigure(); + // Left + for (int i = 0; i < VerticalRegions; i++) { + int x = random.Next(1, distance); + int y = (int)previousEndingPoint.Y - regionHeight; + newEndingPoint = new Point(x, y); + path.AddLine(previousEndingPoint, newEndingPoint); + previousEndingPoint = newEndingPoint; + } + path.CloseFigure(); - // Draw - using (Graphics graphics = Graphics.FromImage(returnImage)) { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using (Brush brush = new TextureBrush(sourceBitmap)) { - graphics.FillPath(brush, path); + // Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing + using (Graphics graphics = Graphics.FromImage(returnImage)) { + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + using (Brush brush = new TextureBrush(sourceBitmap)) { + // Imporant note: If the target wouldn't be at 0,0 we need to translate-transform!! + graphics.FillPath(brush, path); + } } } return returnImage; @@ -611,19 +613,26 @@ namespace GreenshotPlugin.Core { /// How many pixels is the original image moved? /// Bitmap with the shadow, is bigger than the sourceBitmap!! public static Bitmap CreateShadow(Bitmap sourceBitmap, float darkness, int shadowSize, PixelFormat targetPixelformat, out Point offset) { + // "return" the shifted offset, so the caller can e.g. move elements + offset = new Point(shadowSize - 2, shadowSize - 2); + + // Create a new "clean" image Bitmap newImage = new Bitmap(sourceBitmap.Width + (shadowSize * 2), sourceBitmap.Height + (shadowSize * 2), targetPixelformat); using (Graphics graphics = Graphics.FromImage(newImage)) { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - + // Make sure the background color is what we want (transparent or white, depending on the pixel format) if (Image.IsAlphaPixelFormat(targetPixelformat)) { graphics.Clear(Color.Transparent); } else { graphics.Clear(Color.White); } + // Make sure we draw with the best quality! + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + + // Draw "shadow" offsetted ImageAttributes ia = new ImageAttributes(); ColorMatrix cm = new ColorMatrix(); cm.Matrix00 = 0; @@ -631,14 +640,19 @@ namespace GreenshotPlugin.Core { cm.Matrix22 = 0; cm.Matrix33 = darkness; ia.SetColorMatrix(cm); - // Draw "shadow" offsetted - graphics.DrawImage(sourceBitmap, new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size), 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia); + Point shadowLocation = new Point(shadowSize, shadowSize); + graphics.DrawImage(sourceBitmap, new Rectangle(shadowLocation, sourceBitmap.Size), 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia); + // blur "shadow", apply to whole new image Rectangle applyRectangle = new Rectangle(Point.Empty, newImage.Size); ApplyBlur(graphics, newImage, applyRectangle, true, shadowSize, 1d, false, applyRectangle); - // draw original - offset = new Point(shadowSize - 2, shadowSize - 2); - graphics.DrawImage(sourceBitmap, offset); + + // draw original with a TextureBrush so we have nice antialiasing! + using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) { + // We need to do a translate-tranform otherwise the image is wrapped + graphics.TranslateTransform(shadowSize - 2, shadowSize - 2); + graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height); + } } return newImage; }