diff --git a/Greenshot/Drawing/Filters/BrightnessFilter.cs b/Greenshot/Drawing/Filters/BrightnessFilter.cs index 33355453a..6adbb83d6 100644 --- a/Greenshot/Drawing/Filters/BrightnessFilter.cs +++ b/Greenshot/Drawing/Filters/BrightnessFilter.cs @@ -23,6 +23,7 @@ using System.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Plugin.Drawing; using GreenshotPlugin.Core; +using System.Drawing.Imaging; namespace Greenshot.Drawing.Filters { [Serializable()] @@ -47,24 +48,23 @@ namespace Greenshot.Drawing.Filters { return; } - using (BitmapBuffer bbb = new BitmapBuffer(applyBitmap, applyRect)) { - bbb.Lock(); + using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) { double brightness = GetFieldValueAsDouble(FieldType.BRIGHTNESS); - for (int y = 0; y < bbb.Height; y++) { - for (int x = 0; x < bbb.Width; x++) { + 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 = bbb.GetColorAt(x, y); + 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; - bbb.SetColorAt(x, y, Color.FromArgb(color.A, r, g, b)); + fastBitmap.SetColorAt(x, y, Color.FromArgb(color.A, r, g, b)); } } } - bbb.DrawTo(graphics, applyRect.Location); + fastBitmap.DrawTo(graphics, applyRect.Location); } } } diff --git a/Greenshot/Drawing/Filters/GrayscaleFilter.cs b/Greenshot/Drawing/Filters/GrayscaleFilter.cs index 33ebd90d4..7a42d35a6 100644 --- a/Greenshot/Drawing/Filters/GrayscaleFilter.cs +++ b/Greenshot/Drawing/Filters/GrayscaleFilter.cs @@ -40,19 +40,18 @@ namespace Greenshot.Drawing.Filters { return; } - using (BitmapBuffer bbb = new BitmapBuffer(applyBitmap, applyRect)) { - bbb.Lock(); - for (int y = 0; y < bbb.Height; y++) { - for (int x = 0; x < bbb.Width; x++) { + 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 = bbb.GetColorAt(x, y); + 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); - bbb.SetColorAt(x, y, color); + fastBitmap.SetColorAt(x, y, color); } } } - bbb.DrawTo(graphics, applyRect.Location); + fastBitmap.DrawTo(graphics, applyRect.Location); } } } diff --git a/Greenshot/Drawing/Filters/HighlightFilter.cs b/Greenshot/Drawing/Filters/HighlightFilter.cs index 9ff893dcc..757c32348 100644 --- a/Greenshot/Drawing/Filters/HighlightFilter.cs +++ b/Greenshot/Drawing/Filters/HighlightFilter.cs @@ -23,6 +23,7 @@ using System.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Plugin.Drawing; using GreenshotPlugin.Core; +using System.Drawing.Imaging; namespace Greenshot.Drawing.Filters { [Serializable()] @@ -46,19 +47,18 @@ namespace Greenshot.Drawing.Filters { return; } - using (BitmapBuffer bbb = new BitmapBuffer(applyBitmap, applyRect)) { - bbb.Lock(); + using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect)) { Color highlightColor = GetFieldValueAsColor(FieldType.FILL_COLOR); - for (int y = 0; y < bbb.Height; y++) { - for (int x = 0; x < bbb.Width; x++) { + 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 = bbb.GetColorAt(x, y); + 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)); - bbb.SetColorAt(x, y, color); + fastBitmap.SetColorAt(x, y, color); } } } - bbb.DrawTo(graphics, applyRect.Location); + fastBitmap.DrawTo(graphics, applyRect.Location); } } } diff --git a/Greenshot/Drawing/Filters/MagnifierFilter.cs b/Greenshot/Drawing/Filters/MagnifierFilter.cs index 16a09d207..c6993f994 100644 --- a/Greenshot/Drawing/Filters/MagnifierFilter.cs +++ b/Greenshot/Drawing/Filters/MagnifierFilter.cs @@ -23,6 +23,7 @@ using System.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Plugin.Drawing; using GreenshotPlugin.Core; +using System.Drawing.Imaging; namespace Greenshot.Drawing.Filters { [Serializable] @@ -40,23 +41,22 @@ namespace Greenshot.Drawing.Filters { } int magnificationFactor = GetFieldValueAsInt(FieldType.MAGNIFICATION_FACTOR); - using (BitmapBuffer bbb = new BitmapBuffer(applyBitmap, applyRect)) { - int halfWidth = bbb.Size.Width / 2; - int halfHeight = bbb.Size.Height / 2; - bbb.Lock(); - using (BitmapBuffer bbbSrc = new BitmapBuffer(applyBitmap, applyRect)) { - for (int y = 0; y < bbb.Height; y++) { + 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 < bbb.Width; x++) { + for (int x = 0; x < destFastBitmap.Width; x++) { int xDistanceFromCenter = halfWidth - x; if (parent.Contains(applyRect.Left + x, applyRect.Top + y) ^ Invert) { - Color color = bbbSrc.GetColorAt(halfWidth - xDistanceFromCenter / magnificationFactor, halfHeight - yDistanceFromCenter / magnificationFactor); - bbb.SetColorAt(x, y, color); + Color color = sourceFastBitmap.GetColorAt(halfWidth - xDistanceFromCenter / magnificationFactor, halfHeight - yDistanceFromCenter / magnificationFactor); + destFastBitmap.SetColorAt(x, y, color); } } } } - bbb.DrawTo(graphics, applyRect.Location); + destFastBitmap.DrawTo(graphics, applyRect.Location); } } } diff --git a/GreenshotPlugin/Core/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs index aa4a66e65..49bbb58b1 100644 --- a/GreenshotPlugin/Core/FastBitmap.cs +++ b/GreenshotPlugin/Core/FastBitmap.cs @@ -106,6 +106,21 @@ namespace GreenshotPlugin.Core { get; set; } + + /// + /// Draw the stored bitmap to the destionation bitmap at the supplied point + /// + /// Graphics + /// Point with location + void DrawTo(Graphics graphics, Point 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!! + /// + /// Graphics + /// Rectangle with destination + void DrawTo(Graphics graphics, Rectangle destinationRect); } /// @@ -118,6 +133,7 @@ namespace GreenshotPlugin.Core { protected const int RINDEX = 2; protected const int GINDEX = 1; protected const int BINDEX = 0; + protected Rectangle area = Rectangle.Empty; /// /// If this is set to true, the bitmap will be disposed when disposing the IFastBitmap /// @@ -130,27 +146,33 @@ namespace GreenshotPlugin.Core { /// The bitmap for which the FastBitmap is creating access /// protected Bitmap bitmap; + protected BitmapData bmData; protected int stride; /* bytes per pixel row */ protected bool bitsLocked = false; protected byte* pointer; + public static IFastBitmap Create(Bitmap source) { + return Create(source, Rectangle.Empty); + } /// /// 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 /// /// Bitmap to access + /// Rectangle which specifies the area to have access to, can be Rectangle.Empty for the whole image /// IFastBitmap - public static IFastBitmap Create(Bitmap source) { + public static IFastBitmap Create(Bitmap source, Rectangle area) { switch (source.PixelFormat) { case PixelFormat.Format8bppIndexed: - return new FastChunkyBitmap(source); + return new FastChunkyBitmap(source, area); case PixelFormat.Format24bppRgb: - return new Fast24RGBBitmap(source); + return new Fast24RGBBitmap(source, area); case PixelFormat.Format32bppRgb: - return new Fast32RGBBitmap(source); + return new Fast32RGBBitmap(source, area); case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppPArgb: - return new Fast32ARGBBitmap(source); + return new Fast32ARGBBitmap(source, area); default: throw new NotSupportedException(string.Format("Not supported Pixelformat {0}", source.PixelFormat)); } @@ -162,7 +184,27 @@ namespace GreenshotPlugin.Core { /// Bitmap to access /// IFastBitmap public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) { - Bitmap destination = ImageHelper.CloneArea(source, Rectangle.Empty, pixelFormat); + return CreateCloneOf(source, pixelFormat, Rectangle.Empty); + } + /// + /// Factory for creating a FastBitmap as a destination for the source + /// + /// Bitmap to access + /// Area of the bitmap to access, can be Rectangle.Empty for the whole + /// IFastBitmap + public static IFastBitmap CreateCloneOf(Image source, Rectangle area) { + return CreateCloneOf(source, PixelFormat.DontCare, area); + } + + /// + /// Factory for creating a FastBitmap as a destination for the source + /// + /// Bitmap to access + /// Pixelformat of the cloned bitmap + /// Area of the bitmap to access, can be Rectangle.Empty for the whole + /// 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; return fastBitmap; @@ -187,8 +229,15 @@ namespace GreenshotPlugin.Core { /// Constructor which stores the image and locks it when called /// /// - protected FastBitmap(Bitmap bitmap) { + protected FastBitmap(Bitmap bitmap, Rectangle area) { this.bitmap = bitmap; + Rectangle bitmapArea = new Rectangle(Point.Empty, bitmap.Size); + if (area != Rectangle.Empty) { + area.Intersect(bitmapArea); + this.area = area; + } else { + this.area = bitmapArea; + } Lock(); } @@ -197,7 +246,10 @@ namespace GreenshotPlugin.Core { /// public Size Size { get { - return bitmap.Size; + if (area == Rectangle.Empty) { + return bitmap.Size; + } + return area.Size; } } @@ -206,7 +258,10 @@ namespace GreenshotPlugin.Core { /// public int Width { get { - return bitmap.Width; + if (area == Rectangle.Empty) { + return bitmap.Width; + } + return area.Width; } } @@ -215,7 +270,10 @@ namespace GreenshotPlugin.Core { /// public int Height { get { - return bitmap.Height; + if (area == Rectangle.Empty) { + return bitmap.Height; + } + return area.Height; } } @@ -271,7 +329,7 @@ namespace GreenshotPlugin.Core { /// public void Lock() { if (Width > 0 && Height > 0 && !bitsLocked) { - bmData = bitmap.LockBits(new Rectangle(Point.Empty, Size), ImageLockMode.ReadWrite, bitmap.PixelFormat); + bmData = bitmap.LockBits(area, ImageLockMode.ReadWrite, bitmap.PixelFormat); bitsLocked = true; IntPtr Scan0 = bmData.Scan0; @@ -353,7 +411,7 @@ namespace GreenshotPlugin.Core { private Color[] colorEntries; private Dictionary colorCache = new Dictionary(); - public FastChunkyBitmap(Bitmap source) : base(source) { + public FastChunkyBitmap(Bitmap source, Rectangle area) : base(source, area) { colorEntries = bitmap.Palette.Entries; } @@ -443,7 +501,7 @@ namespace GreenshotPlugin.Core { /// public unsafe class Fast24RGBBitmap : FastBitmap { - public Fast24RGBBitmap(Bitmap source) : base(source) { + public Fast24RGBBitmap(Bitmap source, Rectangle area) : base(source, area) { } /// @@ -505,7 +563,7 @@ namespace GreenshotPlugin.Core { /// This is the implementation of the IFastBitmap for 32 bit images (no Alpha) /// public unsafe class Fast32RGBBitmap : FastBitmap { - public Fast32RGBBitmap(Bitmap source) : base(source) { + public Fast32RGBBitmap(Bitmap source, Rectangle area) : base(source, area) { } @@ -571,7 +629,7 @@ namespace GreenshotPlugin.Core { get; set; } - public Fast32ARGBBitmap(Bitmap source) : base(source) { + public Fast32ARGBBitmap(Bitmap source, Rectangle area) : base(source, area) { BackgroundBlendColor = Color.White; }