diff --git a/GreenshotPlugin/Core/BitmapBuffer.cs b/GreenshotPlugin/Core/BitmapBuffer.cs
index 6a99c499d..04576203f 100644
--- a/GreenshotPlugin/Core/BitmapBuffer.cs
+++ b/GreenshotPlugin/Core/BitmapBuffer.cs
@@ -64,6 +64,11 @@ namespace GreenshotPlugin.Core {
}
}
+ public Bitmap UnlockAndReturnBitmap() {
+ Unlock();
+ return Bitmap;
+ }
+
public PixelFormat PixelFormat {
get {
return bitmap.PixelFormat;
@@ -208,9 +213,9 @@ namespace GreenshotPlugin.Core {
}
}
- /**
- * Unlock the System Memory
- */
+ ///
+ /// Unlock the System Memory
+ ///
public void Unlock() {
if (bitsLocked) {
bitmap.UnlockBits(bmData);
@@ -218,24 +223,31 @@ namespace GreenshotPlugin.Core {
}
}
- /**
- * Draw the stored bitmap to the destionation bitmap at the supplied point
- */
+ ///
+ /// 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!!
- */
+ ///
+ /// 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 helper to draw the bitmap
+ ///
+ ///
+ ///
+ ///
private void DrawTo(Graphics graphics, Rectangle? destinationRect, Point? destination) {
if (destinationRect.HasValue) {
// Does the rect have any pixels?
@@ -288,10 +300,13 @@ namespace GreenshotPlugin.Core {
}
}
- /**
- * Set the color at location x,y
- * Before the first time this is called the Lock() should be called once!
- */
+ ///
+ /// 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];
@@ -314,11 +332,14 @@ namespace GreenshotPlugin.Core {
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 GetColorIn(int x, int y, byte[] color) {
+ ///
+ /// 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];
@@ -333,11 +354,14 @@ namespace GreenshotPlugin.Core {
}
}
- /**
- * Set the color at location x,y as an array
- * Before the first time this is called the Lock() should be called once!
- */
- public void SetColorArrayAt(int x, int y, byte[] colors) {
+ ///
+ /// 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;
diff --git a/GreenshotPlugin/Core/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs
index 44e9f9c42..aa4a66e65 100644
--- a/GreenshotPlugin/Core/FastBitmap.cs
+++ b/GreenshotPlugin/Core/FastBitmap.cs
@@ -29,20 +29,79 @@ namespace GreenshotPlugin.Core {
/// The interface for the FastBitmap
///
public interface IFastBitmap : IDisposable {
+ ///
+ /// Get the color at x,y
+ /// The returned Color object depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// Color
Color GetColorAt(int x, int y);
+
+ ///
+ /// Set the color at the specified location
+ ///
+ /// int x
+ /// int y
+ /// Color
void SetColorAt(int x, int y, Color color);
+
+ ///
+ /// Get the color at x,y
+ /// The returned byte[] color depends on the underlying pixel format
+ ///
+ /// int x
+ /// int y
+ /// Set the color at the specified location
+ ///
+ /// int x
+ /// int y
+ /// byte[] color
+ void SetColorAt(int x, int y, byte[] color);
+
+ ///
+ /// Lock the bitmap
+ ///
void Lock();
+
+ ///
+ /// Unlock the bitmap
+ ///
void Unlock();
+
+ ///
+ /// Unlock the bitmap and get the underlying bitmap in one call
+ ///
+ ///
Bitmap UnlockAndReturnBitmap();
+
+ ///
+ /// Size of the underlying image
+ ///
Size Size {
get;
}
+
+ ///
+ /// Height of the underlying image
+ ///
int Height {
get;
}
+
+ ///
+ /// Width of the underlying image
+ ///
int Width {
get;
}
+
+ ///
+ /// Does the underlying image need to be disposed
+ ///
bool NeedsDispose {
get;
set;
@@ -55,6 +114,10 @@ namespace GreenshotPlugin.Core {
public unsafe abstract class FastBitmap : IFastBitmap {
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(FastBitmap));
+ protected const int AINDEX = 3;
+ protected const int RINDEX = 2;
+ protected const int GINDEX = 1;
+ protected const int BINDEX = 0;
///
/// If this is set to true, the bitmap will be disposed when disposing the IFastBitmap
///
@@ -86,6 +149,7 @@ namespace GreenshotPlugin.Core {
case PixelFormat.Format32bppRgb:
return new Fast32RGBBitmap(source);
case PixelFormat.Format32bppArgb:
+ case PixelFormat.Format32bppPArgb:
return new Fast32ARGBBitmap(source);
default:
throw new NotSupportedException(string.Format("Not supported Pixelformat {0}", source.PixelFormat));
@@ -97,7 +161,7 @@ namespace GreenshotPlugin.Core {
///
/// Bitmap to access
/// IFastBitmap
- public static IFastBitmap CreateDestinationFor(Bitmap source, PixelFormat pixelFormat) {
+ public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) {
Bitmap destination = ImageHelper.CloneArea(source, Rectangle.Empty, pixelFormat);
IFastBitmap fastBitmap = Create(destination);
((FastBitmap)fastBitmap).NeedsDispose = true;
@@ -119,8 +183,13 @@ namespace GreenshotPlugin.Core {
return fastBitmap;
}
+ ///
+ /// Constructor which stores the image and locks it when called
+ ///
+ ///
protected FastBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
+ Lock();
}
///
@@ -272,8 +341,13 @@ namespace GreenshotPlugin.Core {
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);
}
+ ///
+ /// This is the implementation of the FastBitmat for the 8BPP pixelformat
+ ///
public unsafe class FastChunkyBitmap : FastBitmap {
// Used for indexed images
private Color[] colorEntries;
@@ -295,6 +369,26 @@ namespace GreenshotPlugin.Core {
return colorEntries[colorIndex];
}
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference
+ public override void GetColorAt(int x, int y, byte[] color) {
+ throw new NotImplementedException("No performance gain!");
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference
+ public override void SetColorAt(int x, int y, byte[] color) {
+ throw new NotImplementedException("No performance gain!");
+ }
+
///
/// Get the color-index from the specified location
///
@@ -361,7 +455,7 @@ namespace GreenshotPlugin.Core {
/// Color
public override Color GetColorAt(int x, int y) {
int offset = (x * 3) + (y * stride);
- return Color.FromArgb(255, pointer[2 + offset], pointer[1 + offset], pointer[offset]);
+ return Color.FromArgb(255, pointer[RINDEX + offset], pointer[GINDEX + offset], pointer[BINDEX + offset]);
}
///
@@ -373,10 +467,38 @@ namespace GreenshotPlugin.Core {
///
public override void SetColorAt(int x, int y, Color color) {
int offset = (x * 3) + (y * stride);
- pointer[2 + offset] = color.R;
- pointer[1 + offset] = color.G;
- pointer[offset] = color.B;
+ pointer[RINDEX + offset] = color.R;
+ pointer[GINDEX + offset] = color.G;
+ pointer[BINDEX + offset] = color.B;
}
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void GetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 3) + (y * stride);
+ color[0] = 255;
+ color[1] = pointer[RINDEX + offset];
+ color[2] = pointer[GINDEX + offset];
+ color[3] = pointer[BINDEX + offset];
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void SetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 3) + (y * stride);
+ pointer[RINDEX + offset] = color[1];
+ pointer[GINDEX + offset] = color[2];
+ pointer[BINDEX + offset] = color[3];
+ }
+
}
///
@@ -396,7 +518,7 @@ namespace GreenshotPlugin.Core {
/// Color
public override Color GetColorAt(int x, int y) {
int offset = (x * 4) + (y * stride);
- return Color.FromArgb(255, pointer[2 + offset], pointer[1 + offset], pointer[offset]);
+ return Color.FromArgb(255, pointer[RINDEX + offset], pointer[GINDEX + offset], pointer[BINDEX + offset]);
}
///
@@ -408,9 +530,36 @@ namespace GreenshotPlugin.Core {
///
public override void SetColorAt(int x, int y, Color color) {
int offset = (x * 4) + (y * stride);
- pointer[2 + offset] = color.R;
- pointer[1 + offset] = color.G;
- pointer[offset] = color.B;
+ pointer[RINDEX + offset] = color.R;
+ pointer[GINDEX + offset] = color.G;
+ pointer[BINDEX + offset] = color.B;
+ }
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void GetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * stride);
+ color[0] = 255;
+ color[1] = pointer[RINDEX + offset];
+ color[2] = pointer[GINDEX + offset];
+ color[3] = pointer[BINDEX + offset];
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void SetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * stride);
+ pointer[RINDEX + offset] = color[1]; // R
+ pointer[GINDEX + offset] = color[2];
+ pointer[BINDEX + offset] = color[3];
}
}
@@ -434,7 +583,7 @@ namespace GreenshotPlugin.Core {
/// Color
public override Color GetColorAt(int x, int y) {
int offset = (x * 4) + (y * stride);
- return Color.FromArgb(pointer[3 + offset], pointer[2 + offset], pointer[1 + offset], pointer[offset]);
+ return Color.FromArgb(pointer[AINDEX + offset], pointer[RINDEX + offset], pointer[GINDEX + offset], pointer[BINDEX + offset]);
}
///
@@ -446,10 +595,38 @@ namespace GreenshotPlugin.Core {
///
public override void SetColorAt(int x, int y, Color color) {
int offset = (x * 4) + (y * stride);
- pointer[3 + offset] = color.A;
- pointer[2 + offset] = color.R;
- pointer[1 + offset] = color.G;
- pointer[offset] = color.B;
+ pointer[AINDEX + offset] = color.A;
+ pointer[RINDEX + offset] = color.R;
+ pointer[GINDEX + offset] = color.G;
+ pointer[BINDEX + offset] = color.B;
+ }
+
+ ///
+ /// Get the color from the specified location into the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void GetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * stride);
+ color[0] = pointer[AINDEX + offset];
+ color[1] = pointer[RINDEX + offset];
+ color[2] = pointer[GINDEX + offset];
+ color[3] = pointer[BINDEX + offset];
+ }
+
+ ///
+ /// Set the color at the specified location from the specified array
+ ///
+ ///
+ ///
+ /// byte[4] as reference (a,r,g,b)
+ public override void SetColorAt(int x, int y, byte[] color) {
+ int offset = (x * 4) + (y * stride);
+ pointer[AINDEX + offset] = color[0];
+ pointer[RINDEX + offset] = color[1]; // R
+ pointer[GINDEX + offset] = color[2];
+ pointer[BINDEX + offset] = color[3];
}
///
@@ -459,12 +636,12 @@ namespace GreenshotPlugin.Core {
/// X coordinate
/// Y Coordinate
/// Color
- public Color GetColorAtWithoutAlpha(int x, int y) {
+ public Color GetBlendedColorAt(int x, int y) {
int offset = (x * 4) + (y * stride);
- int a = pointer[3 + offset];
- int red = pointer[2 + offset];
- int green = pointer[1 + offset];
- int blue = pointer[offset];
+ int a = pointer[AINDEX + offset];
+ int red = pointer[RINDEX + offset];
+ int green = pointer[GINDEX + offset];
+ int blue = pointer[BINDEX + offset];
if (a < 255) {
// As the request is to get without alpha, we blend.
diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs
index 12996f461..b45c35996 100644
--- a/GreenshotPlugin/Core/ImageHelper.cs
+++ b/GreenshotPlugin/Core/ImageHelper.cs
@@ -487,10 +487,12 @@ namespace GreenshotPlugin.Core {
byte[] settingColor = new byte[4];
byte[] readingColor = new byte[4];
- using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, applyRect, true)) {
- bbbDest.Lock();
- using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, applyRect, false)) {
- bbbSrc.Lock();
+ 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;
@@ -519,12 +521,12 @@ namespace GreenshotPlugin.Core {
gSums[wx] = 0;
bSums[wx] = 0;
- if (srcX >= 0 && srcX < bbbDest.Width) {
+ if (srcX >= 0 && srcX < src.Width) {
for (int wy = 0; wy < wlen; ++wy) {
int srcY = y + wy - r;
- if (srcY >= 0 && srcY < bbbDest.Height) {
- bbbSrc.GetColorIn(srcX, srcY, readingColor);
+ if (srcY >= 0 && srcY < src.Height) {
+ src.GetColorAt(srcX, srcY, readingColor);
int wp = w[wy];
waSums[wx] += wp;
@@ -553,13 +555,13 @@ namespace GreenshotPlugin.Core {
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
if (waSum == 0 || wcSum == 0) {
- bbbDest.SetUncheckedColorArrayAt(0, y, nullColor);
+ 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);
- bbbDest.SetUncheckedColorArrayAt(0, y, settingColor);
+ dst.SetColorAt(0, y, settingColor);
}
}
@@ -609,7 +611,7 @@ namespace GreenshotPlugin.Core {
if ((useExportQuality || rand.NextDouble() < previewQuality) && srcY >= 0 && srcY < applyRect.Height) {
int wp = w[wy];
waSums[wx] += wp;
- bbbSrc.GetColorIn(srcX, srcY, readingColor);
+ src.GetColorAt(srcX, srcY, readingColor);
wp *= readingColor[0] + (readingColor[0] >> 7);
wcSums[wx] += wp;
wp >>= 8;
@@ -633,21 +635,20 @@ namespace GreenshotPlugin.Core {
wcSum >>= 8;
if (parentBounds.Contains(applyRect.Left + x, applyRect.Top + y) ^ invert) {
if (waSum == 0 || wcSum == 0) {
- bbbDest.SetUncheckedColorArrayAt(x, y, nullColor);
+ 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);
- bbbDest.SetUncheckedColorArrayAt(x, y, settingColor);
+ dst.SetColorAt(x, y, settingColor);
}
}
}
}
}
}
- bbbDest.Unlock();
- return bbbDest.Bitmap;
+ return dst.UnlockAndReturnBitmap();
}
}
@@ -659,17 +660,15 @@ namespace GreenshotPlugin.Core {
/// Bitmap
public static Bitmap BoxBlur(Bitmap sourceBitmap, int range) {
if ((range & 1) == 0) {
- throw new InvalidOperationException("Range must be odd!");
+ range++;
+ //throw new InvalidOperationException("Range must be odd!");
}
- using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, true)) {
- bbbDest.Lock();
- using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, false)) {
- bbbSrc.Lock();
- BoxBlurHorizontal(bbbSrc, bbbDest, range);
- }
+ using (IFastBitmap bbbDest = FastBitmap.CreateCloneOf(sourceBitmap, PixelFormat.Format32bppArgb)) {
+ BoxBlurHorizontal(bbbDest, range);
BoxBlurVertical(bbbDest, range);
- bbbDest.Unlock();
- return bbbDest.Bitmap;
+ BoxBlurHorizontal(bbbDest, range + 1);
+ BoxBlurVertical(bbbDest, range + 1);
+ return bbbDest.UnlockAndReturnBitmap();
}
}
@@ -679,11 +678,11 @@ namespace GreenshotPlugin.Core {
/// Source BitmapBuffer
/// Target BitmapBuffer
/// Range must be odd!
- private static void BoxBlurHorizontal(BitmapBuffer bbbSrc, BitmapBuffer bbbDest, int range) {
- int w = bbbSrc.Width;
- int h = bbbSrc.Height;
+ private static void BoxBlurHorizontal(IFastBitmap bbbDest, int range) {
+ int w = bbbDest.Width;
+ int h = bbbDest.Height;
int halfRange = range / 2;
- int[] newColors = new int[w];
+ Color[] newColors = new Color[w];
byte[] tmpColor = new byte[4];
for (int y = 0; y < h; y++) {
int hits = 0;
@@ -694,7 +693,7 @@ namespace GreenshotPlugin.Core {
for (int x = -halfRange; x < w; x++) {
int oldPixel = x - halfRange - 1;
if (oldPixel >= 0) {
- bbbSrc.GetUncheckedColorIn(oldPixel, y, tmpColor);
+ bbbDest.GetColorAt(oldPixel, y, tmpColor);
a -= tmpColor[0];
r -= tmpColor[1];
g -= tmpColor[2];
@@ -704,7 +703,7 @@ namespace GreenshotPlugin.Core {
int newPixel = x + halfRange;
if (newPixel < w) {
- bbbSrc.GetUncheckedColorIn(newPixel, y, tmpColor);
+ bbbDest.GetColorAt(newPixel, y, tmpColor);
a += tmpColor[0];
r += tmpColor[1];
g += tmpColor[2];
@@ -713,11 +712,11 @@ namespace GreenshotPlugin.Core {
}
if (x >= 0) {
- newColors[x] = ((byte)(a / hits)) << 24 | ((byte)(r / hits) << 16) | ((byte)(g / hits) << 8 ) | ((byte)(b / hits));
+ newColors[x] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
}
}
for (int x = 0; x < w; x++) {
- bbbDest.SetARGB(x, y, newColors[x]);
+ bbbDest.SetColorAt(x, y, newColors[x]);
}
}
}
@@ -727,11 +726,11 @@ namespace GreenshotPlugin.Core {
///
/// BitmapBuffer which previously was created with BoxBlurHorizontal
/// Range must be odd!
- private static void BoxBlurVertical(BitmapBuffer bbbDest, int range) {
+ private static void BoxBlurVertical(IFastBitmap bbbDest, int range) {
int w = bbbDest.Width;
int h = bbbDest.Height;
int halfRange = range / 2;
- int[] newColors = new int[h];
+ Color[] newColors = new Color[h];
int oldPixelOffset = -(halfRange + 1) * w;
int newPixelOffset = (halfRange) * w;
byte[] tmpColor = new byte[4];
@@ -745,7 +744,7 @@ namespace GreenshotPlugin.Core {
int oldPixel = y - halfRange - 1;
if (oldPixel >= 0) {
//int colorg = pixels[index + oldPixelOffset];
- bbbDest.GetUncheckedColorIn(x, oldPixel, tmpColor);
+ bbbDest.GetColorAt(x, oldPixel, tmpColor);
a -= tmpColor[0];
r -= tmpColor[1];
g -= tmpColor[2];
@@ -756,7 +755,7 @@ namespace GreenshotPlugin.Core {
int newPixel = y + halfRange;
if (newPixel < h) {
//int colorg = pixels[index + newPixelOffset];
- bbbDest.GetUncheckedColorIn(x, newPixel, tmpColor);
+ bbbDest.GetColorAt(x, newPixel, tmpColor);
a += tmpColor[0];
r += tmpColor[1];
g += tmpColor[2];
@@ -765,121 +764,26 @@ namespace GreenshotPlugin.Core {
}
if (y >= 0) {
- newColors[y] = ((byte)(a / hits)) << 24 | ((byte)(r / hits) << 16) | ((byte)(g / hits) << 8) | ((byte)(b / hits));
+ newColors[y] = Color.FromArgb((byte)(a / hits), (byte)(r / hits), (byte)(g / hits), (byte)(b / hits));
}
}
for (int y = 0; y < h; y++) {
- bbbDest.SetARGB(x, y, newColors[y]);
+ bbbDest.SetColorAt(x, y, newColors[y]);
}
}
}
- public static Bitmap FastBlur(Bitmap sourceBitmap, int radius) {
- if (radius < 1) return null;
-
- var rct = new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height);
- var dest = new int[rct.Width * rct.Height];
- var source = new int[rct.Width * rct.Height];
- var bits = sourceBitmap.LockBits(rct, ImageLockMode.ReadWrite, sourceBitmap.PixelFormat);
- Marshal.Copy(bits.Scan0, source, 0, source.Length);
- sourceBitmap.UnlockBits(bits);
-
- int w = rct.Width;
- int h = rct.Height;
- int wm = w - 1;
- int hm = h - 1;
- int wh = w * h;
- int div = radius + radius + 1;
- var r = new int[wh];
- var g = new int[wh];
- var b = new int[wh];
- int rsum, gsum, bsum, x, y, i, p1, p2, yi;
- var vmin = new int[max(w, h)];
- var vmax = new int[max(w, h)];
-
- var dv = new int[256 * div];
- for (i = 0; i < 256 * div; i++) {
- dv[i] = (i / div);
- }
-
- int yw = yi = 0;
-
- for (y = 0; y < h; y++) { // blur horizontal
- rsum = gsum = bsum = 0;
- for (i = -radius; i <= radius; i++) {
- int p = source[yi + min(wm, max(i, 0))];
- rsum += (p & 0xff0000) >> 16;
- gsum += (p & 0x00ff00) >> 8;
- bsum += p & 0x0000ff;
- }
- for (x = 0; x < w; x++) {
-
- r[yi] = dv[rsum];
- g[yi] = dv[gsum];
- b[yi] = dv[bsum];
-
- if (y == 0) {
- vmin[x] = min(x + radius + 1, wm);
- vmax[x] = max(x - radius, 0);
- }
- p1 = source[yw + vmin[x]];
- p2 = source[yw + vmax[x]];
-
- rsum += ((p1 & 0xff0000) - (p2 & 0xff0000)) >> 16;
- gsum += ((p1 & 0x00ff00) - (p2 & 0x00ff00)) >> 8;
- bsum += (p1 & 0x0000ff) - (p2 & 0x0000ff);
- yi++;
- }
- yw += w;
- }
-
- for (x = 0; x < w; x++) { // blur vertical
- rsum = gsum = bsum = 0;
- int yp = -radius * w;
- for (i = -radius; i <= radius; i++) {
- yi = max(0, yp) + x;
- rsum += r[yi];
- gsum += g[yi];
- bsum += b[yi];
- yp += w;
- }
- yi = x;
- for (y = 0; y < h; y++) {
- dest[yi] = unchecked((int)(0xff000000u | (uint)(dv[rsum] << 16) | (uint)(dv[gsum] << 8) | (uint)dv[bsum]));
- if (x == 0) {
- vmin[y] = min(y + radius + 1, hm) * w;
- vmax[y] = max(y - radius, 0) * w;
- }
- p1 = x + vmin[y];
- p2 = x + vmax[y];
-
- rsum += r[p1] - r[p2];
- gsum += g[p1] - g[p2];
- bsum += b[p1] - b[p2];
-
- yi += w;
- }
- }
-
- // copy back to image
- Bitmap newImage = CreateEmptyLike(sourceBitmap, Color.Empty);
- var bits2 = newImage.LockBits(rct, ImageLockMode.ReadWrite, newImage.PixelFormat);
- Marshal.Copy(dest, 0, bits2.Scan0, dest.Length);
- newImage.UnlockBits(bits);
- return newImage;
-
- }
-
- private static int min(int a, int b) { return Math.Min(a, b); }
- private static int max(int a, int b) { return Math.Max(a, b); }
-
- /**
- * This method fixes the problem that we can't apply a filter outside the target bitmap,
- * therefor the filtered-bitmap will be shifted if we try to draw it outside the target bitmap.
- * It will also account for the Invert flag.
- */
+ ///
+ /// This method fixes the problem that we can't apply a filter outside the target bitmap,
+ /// therefor the filtered-bitmap will be shifted if we try to draw it outside the target bitmap.
+ /// It will also account for the Invert flag.
+ ///
+ ///
+ ///
+ ///
+ ///
public static Rectangle CreateIntersectRectangle(Size applySize, Rectangle rect, bool invert) {
Rectangle myRect;
if (invert) {
@@ -927,10 +831,16 @@ namespace GreenshotPlugin.Core {
graphics.DrawImage(sourceBitmap, shadowRectangle, 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia);
}
// blur "shadow", apply to whole new image
- Rectangle newImageRectangle = new Rectangle(0, 0, tmpImage.Width, tmpImage.Height);
//using (Bitmap blurImage = FastBlur(newImage, shadowSize-1)) {
+
+ // Gaussian
+ Rectangle newImageRectangle = new Rectangle(0, 0, tmpImage.Width, tmpImage.Height);
returnImage = CreateBlur(tmpImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle);
+
+ // Box
//returnImage = BoxBlur(tmpImage, shadowSize);
+
+ //returnImage = FastBlur(tmpImage, shadowSize - 1);
}
if (returnImage != null) {
using (Graphics graphics = Graphics.FromImage(returnImage)) {
@@ -976,18 +886,17 @@ namespace GreenshotPlugin.Core {
/// Bitmap to create a b/w off
/// b/w bitmap
public static Bitmap CreateMonochrome(Image sourceImage) {
- using (BitmapBuffer bb = new BitmapBuffer(sourceImage, true)) {
- bb.Lock();
- for (int y = 0; y < bb.Height; y++) {
- for (int x = 0; x < bb.Width; x++) {
- Color color = bb.GetColorAt(x, y);
- int colorBrightness = (color.R+color.G+color.B > 382) ? 255 : 0;
+ 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);
+ int colorBrightness = (color.R + color.G + color.B > 382) ? 255 : 0;
Color monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness);
- bb.SetColorAt(x, y, monoColor);
+ fastBitmap.SetColorAt(x, y, monoColor);
}
}
- bb.Unlock();
- return bb.Bitmap;
+ return fastBitmap.UnlockAndReturnBitmap();
}
}