Optimizing: Replaced BitmapBuffer with FastBitmap, also changed some filters to use more GDI "hardware" instead of home-made pixel processing. Only on Windows 8 the blur is "slow", when radius < 20.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2531 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2013-03-11 16:44:34 +00:00
commit 5018f67ff7
12 changed files with 481 additions and 814 deletions

View file

@ -1,30 +1,37 @@
/// <summary>
/// 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.
/// </summary>
/////////////////////////////////////////////////////////////////////////////////
// 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View file

@ -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);
}
}
}

View file

@ -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 {
/// <summary>
@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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<Color> colors = new List<Color>();
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);
}
}
}