diff --git a/Greenshot/Drawing/Filters/BlurFilter.cs b/Greenshot/Drawing/Filters/BlurFilter.cs
index 952584520..713052f2a 100644
--- a/Greenshot/Drawing/Filters/BlurFilter.cs
+++ b/Greenshot/Drawing/Filters/BlurFilter.cs
@@ -1,30 +1,37 @@
-///
-/// Parts of this class were taken from BlurEffect.cs of Paint.NET 3.0.1,
-/// which was released under MIT license.
-/// http://www.getpaint.net
-/// Some of this code has been adapted for integration with Greenshot.
-/// See Paint.NET copyright notice below.
-///
-
-/////////////////////////////////////////////////////////////////////////////////
-// Paint.NET //
-// Copyright (C) Rick Brewster, Tom Jackson, and past contributors. //
-// Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
-// See src/Resources/Files/License.txt for full licensing and attribution //
-// details. //
-// . //
-/////////////////////////////////////////////////////////////////////////////////
-
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
using System;
using System.Drawing;
using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core;
using System.Drawing.Imaging;
+using GreenshotPlugin.UnmanagedHelpers;
+using System.Drawing.Drawing2D;
namespace Greenshot.Drawing.Filters {
[Serializable()]
public class BlurFilter : AbstractFilter {
+ private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BlurFilter));
+
public double previewQuality;
public double PreviewQuality {
get { return previewQuality; }
@@ -40,11 +47,20 @@ namespace Greenshot.Drawing.Filters {
int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
double previewQuality = GetFieldValueAsDouble(FieldType.PREVIEW_QUALITY);
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);
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
+ if (GDIplus.isBlurPossible(blurRadius)) {
+ GDIplus.DrawWithBlur(graphics, applyBitmap, applyRect, null, null, blurRadius, false);
+ } else {
+ using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
+ ImageHelper.ApplyBoxBlur(fastBitmap, blurRadius);
+ fastBitmap.DrawTo(graphics, applyRect);
}
}
+ graphics.Restore(state);
return;
}
}
diff --git a/Greenshot/Drawing/Filters/BrightnessFilter.cs b/Greenshot/Drawing/Filters/BrightnessFilter.cs
index 6adbb83d6..5b0093768 100644
--- a/Greenshot/Drawing/Filters/BrightnessFilter.cs
+++ b/Greenshot/Drawing/Filters/BrightnessFilter.cs
@@ -24,6 +24,7 @@ using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core;
using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
namespace Greenshot.Drawing.Filters {
[Serializable()]
@@ -48,24 +49,14 @@ namespace Greenshot.Drawing.Filters {
return;
}
- using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
- double brightness = GetFieldValueAsDouble(FieldType.BRIGHTNESS);
- for (int y = 0; y < fastBitmap.Height; y++) {
- for (int x = 0; x < fastBitmap.Width; x++) {
- if (parent.Contains(applyRect.Left + x, applyRect.Top + y) ^ Invert) {
- Color color = fastBitmap.GetColorAt(x, y);
- int r = Convert.ToInt16(color.R * brightness);
- int g = Convert.ToInt16(color.G * brightness);
- int b = Convert.ToInt16(color.B * brightness);
- r = (r > 255) ? 255 : r;
- g = (g > 255) ? 255 : g;
- b = (b > 255) ? 255 : b;
- fastBitmap.SetColorAt(x, y, Color.FromArgb(color.A, r, g, b));
- }
- }
- }
- fastBitmap.DrawTo(graphics, applyRect.Location);
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
}
+ ImageAttributes ia = ImageHelper.CreateAdjustAttributes(0.9f, 1f, 1f);
+ graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia);
+ graphics.Restore(state);
}
}
}
diff --git a/Greenshot/Drawing/Filters/GrayscaleFilter.cs b/Greenshot/Drawing/Filters/GrayscaleFilter.cs
index 7a42d35a6..757cf8ddf 100644
--- a/Greenshot/Drawing/Filters/GrayscaleFilter.cs
+++ b/Greenshot/Drawing/Filters/GrayscaleFilter.cs
@@ -22,6 +22,8 @@ using System;
using System.Drawing;
using GreenshotPlugin.Core;
using Greenshot.Plugin.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
namespace Greenshot.Drawing.Filters {
///
@@ -39,20 +41,23 @@ namespace Greenshot.Drawing.Filters {
// nothing to do
return;
}
-
- using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
- for (int y = 0; y < fastBitmap.Height; y++) {
- for (int x = 0; x < fastBitmap.Width; x++) {
- if (parent.Contains(applyRect.Left + x, applyRect.Top + y) ^ Invert) {
- Color color = fastBitmap.GetColorAt(x, y);
- int luma = (int)((0.3 * color.R) + (0.59 * color.G) + (0.11 * color.B));
- color = Color.FromArgb(luma, luma, luma);
- fastBitmap.SetColorAt(x, y, color);
- }
- }
- }
- fastBitmap.DrawTo(graphics, applyRect.Location);
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
}
+ ColorMatrix grayscaleMatrix = new ColorMatrix(new float[][] {
+ new float[] {.3f, .3f, .3f, 0, 0},
+ new float[] {.59f, .59f, .59f, 0, 0},
+ new float[] {.11f, .11f, .11f, 0, 0},
+ new float[] {0, 0, 0, 1, 0},
+ new float[] {0, 0, 0, 0, 1}
+ });
+ ImageAttributes ia = new ImageAttributes();
+ ia.SetColorMatrix(grayscaleMatrix);
+ graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia);
+ graphics.Restore(state);
+
}
}
}
diff --git a/Greenshot/Drawing/Filters/HighlightFilter.cs b/Greenshot/Drawing/Filters/HighlightFilter.cs
index 757c32348..0e98a5b23 100644
--- a/Greenshot/Drawing/Filters/HighlightFilter.cs
+++ b/Greenshot/Drawing/Filters/HighlightFilter.cs
@@ -24,6 +24,7 @@ using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core;
using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
namespace Greenshot.Drawing.Filters {
[Serializable()]
@@ -46,20 +47,23 @@ namespace Greenshot.Drawing.Filters {
// nothing to do
return;
}
-
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
+ }
using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
Color highlightColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
- for (int y = 0; y < fastBitmap.Height; y++) {
- for (int x = 0; x < fastBitmap.Width; x++) {
- if (parent.Contains(applyRect.Left + x, applyRect.Top + y) ^ Invert) {
- Color color = fastBitmap.GetColorAt(x, y);
- color = Color.FromArgb(color.A, Math.Min(highlightColor.R, color.R), Math.Min(highlightColor.G, color.G), Math.Min(highlightColor.B, color.B));
- fastBitmap.SetColorAt(x, y, color);
- }
+ for (int y = fastBitmap.Top; y < fastBitmap.Bottom; y++) {
+ for (int x = fastBitmap.Left; x < fastBitmap.Right; x++) {
+ Color color = fastBitmap.GetColorAt(x, y);
+ color = Color.FromArgb(color.A, Math.Min(highlightColor.R, color.R), Math.Min(highlightColor.G, color.G), Math.Min(highlightColor.B, color.B));
+ fastBitmap.SetColorAt(x, y, color);
}
}
fastBitmap.DrawTo(graphics, applyRect.Location);
}
+ graphics.Restore(state);
}
}
}
diff --git a/Greenshot/Drawing/Filters/MagnifierFilter.cs b/Greenshot/Drawing/Filters/MagnifierFilter.cs
index c6993f994..73a3ff447 100644
--- a/Greenshot/Drawing/Filters/MagnifierFilter.cs
+++ b/Greenshot/Drawing/Filters/MagnifierFilter.cs
@@ -24,6 +24,7 @@ using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core;
using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
namespace Greenshot.Drawing.Filters {
[Serializable]
@@ -40,24 +41,22 @@ namespace Greenshot.Drawing.Filters {
return;
}
int magnificationFactor = GetFieldValueAsInt(FieldType.MAGNIFICATION_FACTOR);
-
- using (IFastBitmap destFastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) {
- int halfWidth = destFastBitmap.Size.Width / 2;
- int halfHeight = destFastBitmap.Size.Height / 2;
- using (IFastBitmap sourceFastBitmap = FastBitmap.Create(applyBitmap, applyRect)) {
- for (int y = 0; y < destFastBitmap.Height; y++) {
- int yDistanceFromCenter = halfHeight - y;
- for (int x = 0; x < destFastBitmap.Width; x++) {
- int xDistanceFromCenter = halfWidth - x;
- if (parent.Contains(applyRect.Left + x, applyRect.Top + y) ^ Invert) {
- Color color = sourceFastBitmap.GetColorAt(halfWidth - xDistanceFromCenter / magnificationFactor, halfHeight - yDistanceFromCenter / magnificationFactor);
- destFastBitmap.SetColorAt(x, y, color);
- }
- }
- }
- }
- destFastBitmap.DrawTo(graphics, applyRect.Location);
+ GraphicsState state = graphics.Save();
+ if (Invert) {
+ graphics.SetClip(applyRect);
+ graphics.ExcludeClip(rect);
}
+ graphics.SmoothingMode = SmoothingMode.None;
+ graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.None;
+ int halfWidth = rect.Width / 2;
+ int halfHeight = rect.Height / 2;
+ int newWidth = rect.Width / magnificationFactor;
+ int newHeight = rect.Width / magnificationFactor;
+ Rectangle source = new Rectangle(rect.X + halfWidth - (newWidth / 2), rect.Y + halfHeight - (newHeight / 2), newWidth, newHeight);
+ graphics.DrawImage(applyBitmap, rect, source, GraphicsUnit.Pixel);
+ graphics.Restore(state);
}
}
}
diff --git a/Greenshot/Drawing/Filters/PixelizationFilter.cs b/Greenshot/Drawing/Filters/PixelizationFilter.cs
index 14fc79dfb..9039184d1 100644
--- a/Greenshot/Drawing/Filters/PixelizationFilter.cs
+++ b/Greenshot/Drawing/Filters/PixelizationFilter.cs
@@ -48,35 +48,36 @@ namespace Greenshot.Drawing.Filters {
if (rect.Height < pixelSize) {
pixelSize = rect.Height;
}
-
- using (BitmapBuffer bbbDest = new BitmapBuffer(applyBitmap, rect)) {
- bbbDest.Lock();
- using (BitmapBuffer bbbSrc = new BitmapBuffer(applyBitmap, rect, false)) {
- bbbSrc.Lock();
+ using (IFastBitmap dest = FastBitmap.CreateCloneOf(applyBitmap, rect)) {
+ using (IFastBitmap src = FastBitmap.Create(applyBitmap, rect)) {
List colors = new List();
int halbPixelSize = pixelSize / 2;
- for (int y = -halbPixelSize; y < bbbSrc.Height + halbPixelSize; y = y + pixelSize) {
- for (int x = -halbPixelSize; x <= bbbSrc.Width + halbPixelSize; x = x + pixelSize) {
+ for (int y = src.Top - halbPixelSize; y < src.Bottom + halbPixelSize; y = y + pixelSize) {
+ for (int x = src.Left - halbPixelSize; x <= src.Right + halbPixelSize; x = x + pixelSize) {
colors.Clear();
for (int yy = y; yy < y + pixelSize; yy++) {
- if (yy >= 0 && yy < bbbSrc.Height) {
+ if (yy >= src.Top && yy < src.Bottom) {
for (int xx = x; xx < x + pixelSize; xx++) {
- colors.Add(bbbSrc.GetColorAt(xx, yy));
+ if (xx >= src.Left && xx < src.Right) {
+ colors.Add(src.GetColorAt(xx, yy));
+ }
}
}
}
Color currentAvgColor = Colors.Mix(colors);
for (int yy = y; yy <= y + pixelSize; yy++) {
- if (yy >= 0 && yy < bbbSrc.Height) {
+ if (yy >= src.Top && yy < src.Bottom) {
for (int xx = x; xx <= x + pixelSize; xx++) {
- bbbDest.SetColorAt(xx, yy, currentAvgColor);
+ if (xx >= src.Left && xx < src.Right) {
+ dest.SetColorAt(xx, yy, currentAvgColor);
+ }
}
}
}
}
}
}
- bbbDest.DrawTo(graphics, rect.Location);
+ dest.DrawTo(graphics, rect.Location);
}
}
}
diff --git a/GreenshotPlugin/Core/BitmapBuffer.cs b/GreenshotPlugin/Core/BitmapBuffer.cs
deleted file mode 100644
index 04576203f..000000000
--- a/GreenshotPlugin/Core/BitmapBuffer.cs
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-using System;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Runtime.Serialization;
-
-namespace GreenshotPlugin.Core {
- ///
- /// The BitmapBuffer is exactly what it says, it buffers a Bitmap.
- /// And it is possible to Draw on the Bitmap with direct memory access for better performance
- ///
- public unsafe class BitmapBuffer : IDisposable {
- private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BitmapBuffer));
- private bool clone;
- private Bitmap bitmap;
- // Used for indexed images
- private Color[] colorEntries;
-
-
- public static Color BackgroundBlendColor {
- get;
- set;
- }
-
- static BitmapBuffer() {
- BackgroundBlendColor = Color.White;
- }
-
- ///
- /// Get the bitmap, you will always need to dispose the returned bitmap!!
- /// Only works, and makes sense, if cloned and not locked!
- ///
- public Bitmap Bitmap {
- get {
- if (bitsLocked) {
- throw new NotSupportedException("Can't get a locked bitmap!");
- }
- if (!clone) {
- throw new NotSupportedException("Can't return a not cloned bitmap!");
- } else {
- // Make sure the bitmap isn't disposed when this object is closed
- clone = false;
- return bitmap;
- }
- }
- }
-
- public Bitmap UnlockAndReturnBitmap() {
- Unlock();
- return Bitmap;
- }
-
- public PixelFormat PixelFormat {
- get {
- return bitmap.PixelFormat;
- }
- }
-
- private BitmapData bmData;
- private Rectangle rect;
- private byte* pointer;
- private int* intPointer;
- private int stride; /* bytes per pixel row */
- private int aIndex = -1;
- private int rIndex = -1;
- private int gIndex = -1;
- private int bIndex = -1;
- private int bytesPerPixel;
- private bool bitsLocked = false;
-
- public Size Size {
- get {return rect.Size;}
- }
- public int Width {
- get {return rect.Width;}
- }
- public int Height {
- get {return rect.Height;}
- }
-
- ///
- /// Create a BitmapBuffer from a Bitmap
- ///
- /// Bitmap
- public BitmapBuffer(Image sourceBmp) : this(sourceBmp, Rectangle.Empty) {
- }
-
- ///
- /// Create a BitmapBuffer from a Bitmap a flag if we need a clone
- ///
- /// Bitmap
- /// bool specifying if the bitmap needs to be cloned
- public BitmapBuffer(Image sourceBmp, bool clone) : this(sourceBmp, Rectangle.Empty, clone) {
- }
-
- ///
- /// Create a BitmapBuffer from a Bitmap and a Rectangle specifying what part from the Bitmap to take.
- ///
- /// Bitmap
- /// Rectangle
- public BitmapBuffer(Image sourceBmp, Rectangle applyRect) : this(sourceBmp, applyRect, true) {
- }
-
- ///
- /// Create a BitmapBuffer from a Bitmap, a Rectangle specifying what part from the Bitmap to take and a flag if we need a clone
- ///
- /// Image, will be cloned if it's not a bitmap!!!
- /// Rectangle
- /// bool specifying if the bitmap needs to be cloned
- public BitmapBuffer(Image sourceImage, Rectangle applyRect, bool clone) {
- this.clone = clone;
- Rectangle sourceRect = new Rectangle(applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height);
- Rectangle bitmapRect = new Rectangle(0,0, sourceImage.Width, sourceImage.Height);
-
- if (sourceRect.IsEmpty) {
- sourceRect = bitmapRect;
- } else {
- sourceRect.Intersect(bitmapRect);
- }
- // Does the rect have any pixels?
- if (sourceRect.Height <= 0 || sourceRect.Width <= 0) {
- return;
- }
-
- if (!(sourceImage is Bitmap) && !clone) {
- LOG.Warn("Chancing clone to true, as the image is not a bitmap");
- clone = true;
- }
-
- if (clone) {
- this.bitmap = ImageHelper.CloneArea(sourceImage, sourceRect, PixelFormat.DontCare);
- // Set "this" rect to location 0,0
- // as the Cloned Bitmap is only the part we want to work with
- this.rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
- } else if (!ImageHelper.SupportsPixelFormat(sourceImage) && PixelFormat.Format8bppIndexed != sourceImage.PixelFormat) {
- throw new ArgumentException("Unsupported pixel format: " + sourceImage.PixelFormat + " set clone to true!");
- } else {
- this.bitmap = sourceImage as Bitmap;
- this.rect = sourceRect;
- }
- if (bitmap.PixelFormat == PixelFormat.Format8bppIndexed) {
- colorEntries = bitmap.Palette.Entries;
- }
- }
-
- /**
- * Destructor
- */
- ~BitmapBuffer() {
- Dispose(false);
- }
-
- /**
- * The public accessible Dispose
- * Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
- */
- public void Dispose() {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- // The bulk of the clean-up code is implemented in Dispose(bool)
-
- /**
- * This Dispose is called from the Dispose and the Destructor.
- * When disposing==true all non-managed resources should be freed too!
- */
- protected virtual void Dispose(bool disposing) {
- Unlock();
- if (disposing) {
- if (bitmap != null && clone) {
- bitmap.Dispose();
- }
- }
- bitmap = null;
- bmData = null;
- pointer = null;
- }
-
- /**
- * Lock the bitmap so we have direct access to the memory
- */
- public void Lock() {
- if(rect.Width > 0 && rect.Height > 0 && !bitsLocked) {
- bmData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
- bitsLocked = true;
-
- IntPtr Scan0 = bmData.Scan0;
- pointer = (byte*)(void*)Scan0;
- intPointer = (int*)(void*)Scan0;
-
- PrepareForPixelFormat();
- stride = bmData.Stride;
- }
- }
-
- ///
- /// Unlock the System Memory
- ///
- public void Unlock() {
- if (bitsLocked) {
- bitmap.UnlockBits(bmData);
- bitsLocked = false;
- }
- }
-
- ///
- /// Draw the stored bitmap to the destionation bitmap at the supplied point
- ///
- ///
- ///
- public void DrawTo(Graphics graphics, Point destination) {
- DrawTo(graphics, null, destination);
- }
-
- ///
- /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle
- /// Be aware that the stored bitmap will be resized to the specified rectangle!!
- ///
- ///
- ///
- public void DrawTo(Graphics graphics, Rectangle destinationRect) {
- DrawTo(graphics, destinationRect, null);
- }
-
- ///
- /// private helper to draw the bitmap
- ///
- ///
- ///
- ///
- private void DrawTo(Graphics graphics, Rectangle? destinationRect, Point? destination) {
- if (destinationRect.HasValue) {
- // Does the rect have any pixels?
- if (destinationRect.Value.Height <= 0 || destinationRect.Value.Width <= 0) {
- return;
- }
- }
- // Make sure this.bitmap is unlocked, if it was locked
- bool isLocked = bitsLocked;
- if (isLocked) {
- Unlock();
- }
-
- if (destinationRect.HasValue) {
- graphics.DrawImage(this.bitmap, destinationRect.Value);
- } else if (destination.HasValue) {
- graphics.DrawImageUnscaled(this.bitmap, destination.Value);
- }
- // If it was locked, lock it again
- if (isLocked) {
- Lock();
- }
- }
-
- ///
- /// 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!
- ///
- /// X coordinate
- /// Y Coordinate
- /// Color
- public Color GetColorAt(int x, int y) {
- if(x>=0 && y>=0 && x
- /// Set the color at location x,y
- /// Before the first time this is called the Lock() should be called once!
- ///
- ///
- ///
- ///
- public void SetColorAt(int x, int y, Color color) {
- if(x>=0 && y>=0 && x
- /// 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!
- ///
- ///
- ///
- ///
- public void GetColorAt(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
- /// Before the first time this is called the Lock() should be called once!
- ///
- ///
- ///
- ///
- public void SetColorAt(int x, int y, byte[] colors) {
- if(x>=0 && y>=0 && x
- /// Set some internal values for accessing the bitmap according to the PixelFormat
- ///
- private void PrepareForPixelFormat() {
- // aIndex is only set if the pixel format supports "A".
- aIndex = -1;
- switch(bitmap.PixelFormat) {
- case PixelFormat.Format32bppPArgb:
- case PixelFormat.Format32bppArgb:
- bIndex = 0;
- gIndex = 1;
- rIndex = 2;
- aIndex = 3;
- bytesPerPixel = 4;
- break;
- case PixelFormat.Format32bppRgb:
- bIndex = 0;
- gIndex = 1;
- rIndex = 2;
- bytesPerPixel = 4;
- break;
- case PixelFormat.Format24bppRgb:
- bIndex = 0;
- gIndex = 1;
- rIndex = 2;
- bytesPerPixel = 3;
- break;
- case PixelFormat.Format8bppIndexed:
- bytesPerPixel = 1;
- break;
- default:
- throw new FormatException("Bitmap.Pixelformat."+bitmap.PixelFormat+" is currently not supported. Supported: Format32bpp(A)Rgb, Format24bppRgb");
- }
- }
- }
-}
diff --git a/GreenshotPlugin/Core/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs
index 07ceb8ef1..6f9b11931 100644
--- a/GreenshotPlugin/Core/FastBitmap.cs
+++ b/GreenshotPlugin/Core/FastBitmap.cs
@@ -86,19 +86,47 @@ namespace GreenshotPlugin.Core {
}
///
- /// Height of the underlying image
+ /// Height of the image area that this fastbitmap covers
///
int Height {
get;
}
///
- /// Width of the underlying image
+ /// Width of the image area that this fastbitmap covers
///
int Width {
get;
}
+ ///
+ /// Top of the image area that this fastbitmap covers
+ ///
+ int Top {
+ get;
+ }
+
+ ///
+ /// Left of the image area that this fastbitmap covers
+ ///
+ int Left {
+ get;
+ }
+
+ ///
+ /// Right of the image area that this fastbitmap covers
+ ///
+ int Right {
+ get;
+ }
+
+ ///
+ /// Bottom of the image area that this fastbitmap covers
+ ///
+ int Bottom {
+ get;
+ }
+
///
/// Does the underlying image need to be disposed
///
@@ -136,6 +164,108 @@ namespace GreenshotPlugin.Core {
///
///
bool Contains(int x, int y);
+
+ ///
+ /// Set the bitmap resolution
+ ///
+ ///
+ ///
+ void SetResolution(float horizontal, float vertical);
+ }
+
+ ///
+ /// This interface can be used for when offsetting is needed
+ ///
+ public interface IFastBitmapWithOffset : IFastBitmap {
+ ///
+ /// Return true if the coordinates are inside the FastBitmap
+ ///
+ ///
+ ///
+ ///
+ bool Contains(int x, int y);
+
+ ///
+ /// Set the color at the specified location, using offsetting so the original coordinates can be used
+ ///
+ /// int x
+ /// int y
+ /// Color color
+ new void SetColorAt(int x, int y, Color color);
+
+ ///
+ /// Set the color at the specified location, using offsetting so the original coordinates can be used
+ ///
+ /// int x
+ /// int y
+ /// byte[] color
+ new void SetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Get the color at x,y
+ /// The returned Color object depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// Color
+ new Color GetColorAt(int x, int y);
+
+ ///
+ /// Get the color at x,y, using offsetting so the original coordinates can be used
+ /// The returned byte[] color depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// This interface can be used for when clipping is needed
+ ///
+ public interface IFastBitmapWithClip : IFastBitmap {
+ Rectangle Clip {
+ get;
+ set;
+ }
+
+ bool InvertClip {
+ get;
+ set;
+ }
+
+ ///
+ /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping
+ ///
+ /// int x
+ /// int y
+ /// Color color
+ new void SetColorAt(int x, int y, Color color);
+
+ ///
+ /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping
+ ///
+ /// int x
+ /// int y
+ /// byte[] color
+ new void SetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Return true if the coordinates are inside the FastBitmap and not clipped
+ ///
+ ///
+ ///
+ ///
+ new bool Contains(int x, int y);
}
///
@@ -152,7 +282,7 @@ namespace GreenshotPlugin.Core {
///
/// The base class for the fast bitmap implementation
///
- public unsafe abstract class FastBitmap : IFastBitmap {
+ public unsafe abstract class FastBitmap : IFastBitmap, IFastBitmapWithClip, IFastBitmapWithOffset {
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(FastBitmap));
protected const int PIXELFORMAT_INDEX_A = 3;
@@ -174,6 +304,16 @@ namespace GreenshotPlugin.Core {
set;
}
+ public Rectangle Clip {
+ get;
+ set;
+ }
+
+ public bool InvertClip {
+ get;
+ set;
+ }
+
///
/// The bitmap for which the FastBitmap is creating access
///
@@ -187,6 +327,11 @@ namespace GreenshotPlugin.Core {
public static IFastBitmap Create(Bitmap source) {
return Create(source, Rectangle.Empty);
}
+
+ public void SetResolution(float horizontal, float vertical) {
+ bitmap.SetResolution(horizontal, vertical);
+ }
+
///
/// Factory for creating a FastBitmap depending on the pixelformat of the source
/// The supplied rectangle specifies the area for which the FastBitmap does its thing
@@ -247,8 +392,10 @@ namespace GreenshotPlugin.Core {
/// IFastBitmap
public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat, Rectangle area) {
Bitmap destination = ImageHelper.CloneArea(source, area, pixelFormat);
- IFastBitmap fastBitmap = Create(destination);
- ((FastBitmap)fastBitmap).NeedsDispose = true;
+ FastBitmap fastBitmap = Create(destination) as FastBitmap;
+ fastBitmap.NeedsDispose = true;
+ fastBitmap.Left = area.Left;
+ fastBitmap.Top = area.Top;
return fastBitmap;
}
@@ -279,6 +426,13 @@ namespace GreenshotPlugin.Core {
} else {
this.area = bitmapArea;
}
+ // As the lock takes care that only the specified area is made available we need to calculate the offset
+ this.Left = area.Left;
+ this.Top = area.Top;
+ // Default cliping is done to the area without invert
+ this.Clip = this.area;
+ this.InvertClip = false;
+ // Always lock, so we don't need to do this ourselves
Lock();
}
@@ -318,12 +472,79 @@ namespace GreenshotPlugin.Core {
}
}
+ private int left;
+ ///
+ /// Return the left of the fastbitmap, this is also used as an offset
+ ///
+ public int Left {
+ get {
+ return 0;
+ }
+ set {
+ left = value;
+ }
+ }
+
+ ///
+ /// Return the left of the fastbitmap, this is also used as an offset
+ ///
+ int IFastBitmapWithOffset.Left {
+ get {
+ return left;
+ }
+ set {
+ left = value;
+ }
+ }
+
+ private int top;
+ ///
+ /// Return the top of the fastbitmap, this is also used as an offset
+ ///
+ public int Top {
+ get {
+ return 0;
+ }
+ set {
+ top = value;
+ }
+ }
+
+ ///
+ /// Return the top of the fastbitmap, this is also used as an offset
+ ///
+ int IFastBitmapWithOffset.Top {
+ get {
+ return top;
+ }
+ set {
+ top = value;
+ }
+ }
+
+ ///
+ /// Return the right of the fastbitmap
+ ///
+ public int Right {
+ get {
+ return Left + Width;
+ }
+ }
+
+ ///
+ /// Return the bottom of the fastbitmap
+ ///
+ public int Bottom {
+ get {
+ return Top + Height;
+ }
+ }
+
///
/// Returns the underlying bitmap, unlocks it and prevents that it will be disposed
///
public Bitmap UnlockAndReturnBitmap() {
if (bitsLocked) {
- LOG.Warn("Unlocking the bitmap");
Unlock();
}
NeedsDispose = false;
@@ -401,7 +622,7 @@ namespace GreenshotPlugin.Core {
///
///
public void DrawTo(Graphics graphics, Point destination) {
- DrawTo(graphics, null, destination);
+ DrawTo(graphics, new Rectangle(destination, area.Size));
}
///
@@ -410,38 +631,15 @@ namespace GreenshotPlugin.Core {
///
///
///
- public void DrawTo(Graphics graphics, Rectangle destinationRect) {
- DrawTo(graphics, destinationRect, null);
- }
-
- ///
- /// private helper to draw the bitmap
- ///
- ///
- ///
///
- private void DrawTo(Graphics graphics, Rectangle? destinationRect, Point? destination) {
- if (destinationRect.HasValue) {
- // Does the rect have any pixels?
- if (destinationRect.Value.Height <= 0 || destinationRect.Value.Width <= 0) {
- return;
- }
- }
+ public void DrawTo(Graphics graphics, Rectangle destinationRect) {
// Make sure this.bitmap is unlocked, if it was locked
bool isLocked = bitsLocked;
if (isLocked) {
Unlock();
}
- if (destinationRect.HasValue) {
- graphics.DrawImage(this.bitmap, destinationRect.Value);
- } else if (destination.HasValue) {
- graphics.DrawImageUnscaled(this.bitmap, destination.Value);
- }
- // If it was locked, lock it again
- if (isLocked) {
- Lock();
- }
+ graphics.DrawImage(this.bitmap, destinationRect, area, GraphicsUnit.Pixel);
}
///
@@ -451,13 +649,75 @@ namespace GreenshotPlugin.Core {
///
/// true if x & y are inside the FastBitmap
public bool Contains(int x, int y) {
- return x >= 0 && x < Width && y >= 0 && y < Height;
+ return area.Contains(x - Left, y - Top);
}
public abstract Color GetColorAt(int x, int y);
public abstract void SetColorAt(int x, int y, Color color);
public abstract void GetColorAt(int x, int y, byte[] color);
public abstract void SetColorAt(int x, int y, byte[] color);
+
+ #region IFastBitmapWithClip
+ bool IFastBitmapWithClip.Contains(int x, int y) {
+ bool contains = Clip.Contains(x, y);
+ if (InvertClip) {
+ return !contains;
+ } else {
+ return contains;
+ }
+ }
+
+ void IFastBitmapWithClip.SetColorAt(int x, int y, byte[] color) {
+ bool contains = Clip.Contains(x, y);
+ if ((InvertClip && contains) || (!InvertClip && !contains)) {
+ return;
+ }
+ SetColorAt(x, y, color);
+ }
+
+ void IFastBitmapWithClip.SetColorAt(int x, int y, Color color) {
+ bool contains = Clip.Contains(x, y);
+ if ((InvertClip && contains) || (!InvertClip && !contains)) {
+ return;
+ }
+ SetColorAt(x, y, color);
+ }
+ #endregion
+
+ #region IFastBitmapWithOffset
+ ///
+ /// returns true if x & y are inside the FastBitmap
+ ///
+ ///
+ ///
+ /// true if x & y are inside the FastBitmap
+ bool IFastBitmapWithOffset.Contains(int x, int y) {
+ return area.Contains(x - Left, y - Top);
+ }
+
+ Color IFastBitmapWithOffset.GetColorAt(int x, int y) {
+ x -= left;
+ y -= top;
+ return GetColorAt(x, y);
+ }
+ void IFastBitmapWithOffset.GetColorAt(int x, int y, byte[] color) {
+ x -= left;
+ y -= top;
+ GetColorAt(x, y, color);
+ }
+
+ void IFastBitmapWithOffset.SetColorAt(int x, int y, byte[] color) {
+ x -= left;
+ y -= top;
+ SetColorAt(x, y, color);
+ }
+
+ void IFastBitmapWithOffset.SetColorAt(int x, int y, Color color) {
+ x -= left;
+ y -= top;
+ SetColorAt(x, y, color);
+ }
+ #endregion
}
///
@@ -771,6 +1031,5 @@ namespace GreenshotPlugin.Core {
}
return Color.FromArgb(255, red, green, blue);
}
-
}
}
diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs
index 37f89370b..630bc3186 100644
--- a/GreenshotPlugin/Core/ImageHelper.cs
+++ b/GreenshotPlugin/Core/ImageHelper.cs
@@ -175,8 +175,6 @@ namespace GreenshotPlugin.Core {
// Bottom Right
checkPoints.Add(new Point(image.Width - 1, image.Height - 1));
using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap)image)) {
- fastBitmap.Lock();
-
// find biggest area
foreach(Point checkPoint in checkPoints) {
currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference);
@@ -461,197 +459,6 @@ namespace GreenshotPlugin.Core {
return weights;
}
- ///
- /// Create a new bitmap with the sourceBitmap blurred
- ///
- /// Source to blur
- /// 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 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 null;
- }
- // do nothing when nothing can be done!
- if (blurRadius < 1) {
- return null;
- }
-
- byte[] nullColor = new byte[] { 255, 255, 255, 255 };
- if (sourceBitmap.PixelFormat == PixelFormat.Format32bppArgb || sourceBitmap.PixelFormat == PixelFormat.Format32bppPArgb) {
- nullColor = new byte[] { 0, 0, 0, 0 };
- }
- byte[] settingColor = new byte[4];
- byte[] readingColor = new byte[4];
-
- using (BitmapBuffer dst = new BitmapBuffer(sourceBitmap, applyRect, true)) {
- //using (IFastBitmap dst = FastBitmap.CreateEmpty(sourceBitmap.Size, sourceBitmap.PixelFormat, Color.Empty)) {
- dst.Lock();
- using (BitmapBuffer src = new BitmapBuffer(sourceBitmap, applyRect, false)) {
- //using (IFastBitmap src = FastBitmap.Create(sourceBitmap)) {
- src.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;
-
- 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 < src.Width) {
- for (int wy = 0; wy < wlen; ++wy) {
- int srcY = y + wy - r;
-
- if (srcY >= 0 && srcY < src.Height) {
- src.GetColorAt(srcX, srcY, readingColor);
- int wp = w[wy];
-
- waSums[wx] += wp;
- 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 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) {
- dst.SetColorAt(0, y, nullColor);
- } else {
- settingColor[0] = (byte)(aSum / waSum);
- settingColor[1] = (byte)(rSum / wcSum);
- settingColor[2] = (byte)(gSum / wcSum);
- settingColor[3] = (byte)(bSum / wcSum);
- dst.SetColorAt(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;
- src.GetColorAt(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) {
- dst.SetColorAt(x, y, nullColor);
- } else {
- settingColor[0] = (byte)(aSum / waSum);
- settingColor[1] = (byte)(rSum / wcSum);
- settingColor[2] = (byte)(gSum / wcSum);
- settingColor[3] = (byte)(bSum / wcSum);
- dst.SetColorAt(x, y, settingColor);
- }
- }
- }
- }
- }
- }
- return dst.UnlockAndReturnBitmap();
- }
- }
-
///
/// Apply BoxBlur to the destinationBitmap
///
@@ -674,6 +481,9 @@ namespace GreenshotPlugin.Core {
if ((range & 1) == 0) {
range++;
}
+ if (range <= 1) {
+ return;
+ }
// Box blurs are frequently used to approximate a Gaussian blur.
// By the central limit theorem, if applied 3 times on the same image, a box blur approximates the Gaussian kernel to within about 3%, yielding the same result as a quadratic convolution kernel.
// This might be true, but the GDI+ BlurEffect doesn't look the same, a 2x blur is more simular and we only make 2x Box-Blur.
@@ -700,19 +510,17 @@ namespace GreenshotPlugin.Core {
if (targetFastBitmap.hasAlphaChannel) {
throw new NotSupportedException("BoxBlurHorizontal should NOT be called for bitmaps with alpha channel");
}
- int w = targetFastBitmap.Width;
- int h = targetFastBitmap.Height;
int halfRange = range / 2;
- Color[] newColors = new Color[w];
+ Color[] newColors = new Color[targetFastBitmap.Width];
byte[] tmpColor = new byte[3];
- for (int y = 0; y < h; y++) {
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) {
int hits = 0;
int r = 0;
int g = 0;
int b = 0;
- for (int x = -halfRange; x < w; x++) {
+ for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) {
int oldPixel = x - halfRange - 1;
- if (oldPixel >= 0) {
+ if (oldPixel >= targetFastBitmap.Left) {
targetFastBitmap.GetColorAt(oldPixel, y, tmpColor);
r -= tmpColor[FastBitmap.COLOR_INDEX_R];
g -= tmpColor[FastBitmap.COLOR_INDEX_G];
@@ -721,7 +529,7 @@ namespace GreenshotPlugin.Core {
}
int newPixel = x + halfRange;
- if (newPixel < w) {
+ if (newPixel < targetFastBitmap.Right) {
targetFastBitmap.GetColorAt(newPixel, y, tmpColor);
r += tmpColor[FastBitmap.COLOR_INDEX_R];
g += tmpColor[FastBitmap.COLOR_INDEX_G];
@@ -729,12 +537,12 @@ namespace GreenshotPlugin.Core {
hits++;
}
- if (x >= 0) {
- newColors[x] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ if (x >= targetFastBitmap.Left) {
+ newColors[x - targetFastBitmap.Left] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
}
}
- for (int x = 0; x < w; x++) {
- targetFastBitmap.SetColorAt(x, y, newColors[x]);
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) {
+ targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]);
}
}
}
@@ -748,20 +556,18 @@ namespace GreenshotPlugin.Core {
if (!targetFastBitmap.hasAlphaChannel) {
throw new NotSupportedException("BoxBlurHorizontalAlpha should be called for bitmaps with alpha channel");
}
- int w = targetFastBitmap.Width;
- int h = targetFastBitmap.Height;
int halfRange = range / 2;
- Color[] newColors = new Color[w];
+ Color[] newColors = new Color[targetFastBitmap.Width];
byte[] tmpColor = new byte[4];
- for (int y = 0; y < h; y++) {
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) {
int hits = 0;
int a = 0;
int r = 0;
int g = 0;
int b = 0;
- for (int x = -halfRange; x < w; x++) {
+ for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) {
int oldPixel = x - halfRange - 1;
- if (oldPixel >= 0) {
+ if (oldPixel >= targetFastBitmap.Left) {
targetFastBitmap.GetColorAt(oldPixel, y, tmpColor);
a -= tmpColor[FastBitmap.COLOR_INDEX_A];
r -= tmpColor[FastBitmap.COLOR_INDEX_R];
@@ -771,7 +577,7 @@ namespace GreenshotPlugin.Core {
}
int newPixel = x + halfRange;
- if (newPixel < w) {
+ if (newPixel < targetFastBitmap.Right) {
targetFastBitmap.GetColorAt(newPixel, y, tmpColor);
a += tmpColor[FastBitmap.COLOR_INDEX_A];
r += tmpColor[FastBitmap.COLOR_INDEX_R];
@@ -780,12 +586,12 @@ namespace GreenshotPlugin.Core {
hits++;
}
- if (x >= 0) {
- newColors[x] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ if (x >= targetFastBitmap.Left) {
+ newColors[x - targetFastBitmap.Left] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
}
}
- for (int x = 0; x < w; x++) {
- targetFastBitmap.SetColorAt(x, y, newColors[x]);
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) {
+ targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]);
}
}
}
@@ -800,20 +606,19 @@ namespace GreenshotPlugin.Core {
throw new NotSupportedException("BoxBlurVertical should NOT be called for bitmaps with alpha channel");
}
int w = targetFastBitmap.Width;
- int h = targetFastBitmap.Height;
int halfRange = range / 2;
- Color[] newColors = new Color[h];
+ Color[] newColors = new Color[targetFastBitmap.Height];
int oldPixelOffset = -(halfRange + 1) * w;
int newPixelOffset = (halfRange) * w;
byte[] tmpColor = new byte[4];
- for (int x = 0; x < w; x++) {
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) {
int hits = 0;
int r = 0;
int g = 0;
int b = 0;
- for (int y = -halfRange; y < h; y++) {
+ for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) {
int oldPixel = y - halfRange - 1;
- if (oldPixel >= 0) {
+ if (oldPixel >= targetFastBitmap.Top) {
targetFastBitmap.GetColorAt(x, oldPixel, tmpColor);
r -= tmpColor[FastBitmap.COLOR_INDEX_R];
g -= tmpColor[FastBitmap.COLOR_INDEX_G];
@@ -822,7 +627,7 @@ namespace GreenshotPlugin.Core {
}
int newPixel = y + halfRange;
- if (newPixel < h) {
+ if (newPixel < targetFastBitmap.Bottom) {
targetFastBitmap.GetColorAt(x, newPixel, tmpColor);
r += tmpColor[FastBitmap.COLOR_INDEX_R];
g += tmpColor[FastBitmap.COLOR_INDEX_G];
@@ -830,13 +635,13 @@ namespace GreenshotPlugin.Core {
hits++;
}
- if (y >= 0) {
- newColors[y] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ if (y >= targetFastBitmap.Top) {
+ newColors[y - targetFastBitmap.Top] = Color.FromArgb(255, (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
}
}
- for (int y = 0; y < h; y++) {
- targetFastBitmap.SetColorAt(x, y, newColors[y]);
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) {
+ targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]);
}
}
}
@@ -852,22 +657,20 @@ namespace GreenshotPlugin.Core {
}
int w = targetFastBitmap.Width;
- int h = targetFastBitmap.Height;
int halfRange = range / 2;
- Color[] newColors = new Color[h];
+ Color[] newColors = new Color[targetFastBitmap.Height];
int oldPixelOffset = -(halfRange + 1) * w;
int newPixelOffset = (halfRange) * w;
byte[] tmpColor = new byte[4];
- for (int x = 0; x < w; x++) {
+ for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) {
int hits = 0;
int a = 0;
int r = 0;
int g = 0;
int b = 0;
- for (int y = -halfRange; y < h; y++) {
+ for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) {
int oldPixel = y - halfRange - 1;
- if (oldPixel >= 0) {
- //int colorg = pixels[index + oldPixelOffset];
+ if (oldPixel >= targetFastBitmap.Top) {
targetFastBitmap.GetColorAt(x, oldPixel, tmpColor);
a -= tmpColor[FastBitmap.COLOR_INDEX_A];
r -= tmpColor[FastBitmap.COLOR_INDEX_R];
@@ -877,7 +680,7 @@ namespace GreenshotPlugin.Core {
}
int newPixel = y + halfRange;
- if (newPixel < h) {
+ if (newPixel < targetFastBitmap.Bottom) {
//int colorg = pixels[index + newPixelOffset];
targetFastBitmap.GetColorAt(x, newPixel, tmpColor);
a += tmpColor[FastBitmap.COLOR_INDEX_A];
@@ -887,13 +690,13 @@ namespace GreenshotPlugin.Core {
hits++;
}
- if (y >= 0) {
- newColors[y] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
+ if (y >= targetFastBitmap.Top) {
+ newColors[y - targetFastBitmap.Top] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
}
}
- for (int y = 0; y < h; y++) {
- targetFastBitmap.SetColorAt(x, y, newColors[y]);
+ for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) {
+ targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]);
}
}
}
@@ -1068,7 +871,6 @@ namespace GreenshotPlugin.Core {
/// b/w bitmap
public static Bitmap CreateMonochrome(Image sourceImage, byte threshold) {
using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(sourceImage, sourceImage.PixelFormat)) {
- fastBitmap.Lock();
for (int y = 0; y < fastBitmap.Height; y++) {
for (int x = 0; x < fastBitmap.Width; x++) {
Color color = fastBitmap.GetColorAt(x, y);
@@ -1122,15 +924,13 @@ namespace GreenshotPlugin.Core {
}
///
- /// Adjust the brightness, contract or gamma of an image.
- /// Use the value "1.0f" for no changes.
+ /// Create ImageAttributes to modify
///
- /// Original bitmap
- /// Bitmap with grayscale
- public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma) {
- //create a blank bitmap the same size as original
- // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format.
- Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ ///
+ ///
+ ///
+ /// ImageAttributes
+ public static ImageAttributes CreateAdjustAttributes(float brightness, float contrast, float gamma) {
float adjustedBrightness = brightness - 1.0f;
ColorMatrix applyColorMatrix = new ColorMatrix(
new float[][] {
@@ -1146,8 +946,19 @@ namespace GreenshotPlugin.Core {
attributes.ClearColorMatrix();
attributes.SetColorMatrix(applyColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
attributes.SetGamma(gamma, ColorAdjustType.Bitmap);
- ApplyImageAttributes((Bitmap)sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, attributes);
-
+ return attributes;
+ }
+ ///
+ /// Adjust the brightness, contract or gamma of an image.
+ /// Use the value "1.0f" for no changes.
+ ///
+ /// Original bitmap
+ /// Bitmap with grayscale
+ public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma) {
+ //create a blank bitmap the same size as original
+ // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format.
+ Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
+ ApplyImageAttributes((Bitmap)sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, CreateAdjustAttributes(brightness, contrast, gamma));
return newBitmap;
}
@@ -1407,8 +1218,7 @@ namespace GreenshotPlugin.Core {
if (!includeAlpha) {
toCount = toCount & 0xffffff;
}
- using (BitmapBuffer bb = new BitmapBuffer(sourceImage, false)) {
- bb.Lock();
+ using (IFastBitmap bb = FastBitmap.Create((Bitmap)sourceImage)) {
for (int y = 0; y < bb.Height; y++) {
for (int x = 0; x < bb.Width; x++) {
int bitmapcolor = bb.GetColorAt(x, y).ToArgb();
@@ -1420,7 +1230,6 @@ namespace GreenshotPlugin.Core {
}
}
}
- bb.Unlock();
return colors;
}
}
diff --git a/GreenshotPlugin/Core/QuantizerHelper.cs b/GreenshotPlugin/Core/QuantizerHelper.cs
index 80c723769..b61216146 100644
--- a/GreenshotPlugin/Core/QuantizerHelper.cs
+++ b/GreenshotPlugin/Core/QuantizerHelper.cs
@@ -332,21 +332,19 @@ namespace GreenshotPlugin.Core {
LOG.Info("Starting bitmap reconstruction...");
- using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) {
- bbbDest.Lock();
- using (IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap)) {
- IFastBitmapWithBlend bbbSrcBlend = bbbSrc as IFastBitmapWithBlend;
- bbbSrc.Lock();
+ using (FastChunkyBitmap dest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) {
+ using (IFastBitmap src = FastBitmap.Create(sourceBitmap)) {
+ IFastBitmapWithBlend srcBlend = src as IFastBitmapWithBlend;
Dictionary lookup = new Dictionary();
byte bestMatch;
- for (int y = 0; y < bbbSrc.Height; y++) {
- for (int x = 0; x < bbbSrc.Width; x++) {
+ for (int y = 0; y < src.Height; y++) {
+ for (int x = 0; x < src.Width; x++) {
Color color;
- if (bbbSrcBlend != null) {
+ if (srcBlend != null) {
// WithoutAlpha, this makes it possible to ignore the alpha
- color = bbbSrcBlend.GetBlendedColorAt(x, y);
+ color = srcBlend.GetBlendedColorAt(x, y);
} else {
- color = bbbSrc.GetColorAt(x, y);
+ color = src.GetColorAt(x, y);
}
// Check if we already matched the color
@@ -354,7 +352,7 @@ namespace GreenshotPlugin.Core {
// If not we need to find the best match
// First get initial match
- bestMatch = bbbDest.GetColorIndexAt(x, y);
+ bestMatch = dest.GetColorIndexAt(x, y);
bestMatch = tag[bestMatch];
Int32 bestDistance = 100000000;
@@ -384,7 +382,7 @@ namespace GreenshotPlugin.Core {
blues[bestMatch] += color.B;
sums[bestMatch]++;
- bbbDest.SetColorIndexAt(x, y, bestMatch);
+ dest.SetColorIndexAt(x, y, bestMatch);
}
}
}
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index f0dd294bb..9dc0e9b9c 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -1117,14 +1117,13 @@ namespace GreenshotPlugin.Core {
///
/// The bitmap to remove the corners from.
private void RemoveCorners(Bitmap image) {
- using (BitmapBuffer buffer = new BitmapBuffer((Bitmap)image, false)) {
- buffer.Lock();
+ using (IFastBitmap fastBitmap = FastBitmap.Create(image)) {
for (int y = 0; y < conf.WindowCornerCutShape.Count; y++) {
for (int x = 0; x < conf.WindowCornerCutShape[y]; x++) {
- buffer.SetColorAt(x, y, Color.Transparent);
- buffer.SetColorAt(image.Width-1-x, y, Color.Transparent);
- buffer.SetColorAt(image.Width-1-x, image.Height-1-y, Color.Transparent);
- buffer.SetColorAt(x, image.Height-1-y, Color.Transparent);
+ fastBitmap.SetColorAt(x, y, Color.Transparent);
+ fastBitmap.SetColorAt(image.Width-1-x, y, Color.Transparent);
+ fastBitmap.SetColorAt(image.Width-1-x, image.Height-1-y, Color.Transparent);
+ fastBitmap.SetColorAt(x, image.Height-1-y, Color.Transparent);
}
}
}
@@ -1139,23 +1138,19 @@ namespace GreenshotPlugin.Core {
/// Bitmap with the black image
/// Bitmap with transparency
private Bitmap ApplyTransparency(Bitmap blackBitmap, Bitmap whiteBitmap) {
- Bitmap returnBitmap = new Bitmap(blackBitmap.Width, blackBitmap.Height, PixelFormat.Format32bppArgb);
- returnBitmap.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution);
- using (BitmapBuffer blackBuffer = new BitmapBuffer(blackBitmap, false)) {
- blackBuffer.Lock();
- using (BitmapBuffer whiteBuffer = new BitmapBuffer(whiteBitmap, false)) {
- whiteBuffer.Lock();
- using (BitmapBuffer targetBuffer = new BitmapBuffer(returnBitmap, false)) {
- targetBuffer.Lock();
- for(int y=0; y
diff --git a/GreenshotPlugin/GreenshotPlugin.csproj b/GreenshotPlugin/GreenshotPlugin.csproj
index d0ee900e2..c06c4a09e 100644
--- a/GreenshotPlugin/GreenshotPlugin.csproj
+++ b/GreenshotPlugin/GreenshotPlugin.csproj
@@ -146,7 +146,6 @@
-