mirror of
https://github.com/greenshot/greenshot
synced 2025-07-16 10:03:44 -07:00
Fixed and optimized some drawing routines, still didn't find a solution for shadowing when target format has transparency.
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1648 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
46758d238c
commit
dede5cf292
16 changed files with 275 additions and 161 deletions
|
@ -44,12 +44,15 @@ namespace Greenshot.Drawing {
|
|||
AddField(GetType(), FieldType.ARROWHEADS, Greenshot.Drawing.ArrowContainer.ArrowHeadCombination.END_POINT);
|
||||
}
|
||||
|
||||
public override void Draw(Graphics g, RenderMode rm) {
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
|
||||
if (lineThickness > 0 ) {
|
||||
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
ArrowHeadCombination heads = (ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS);
|
||||
if (shadow) {
|
||||
|
@ -63,7 +66,7 @@ namespace Greenshot.Drawing {
|
|||
shadowCapPen.Width = lineThickness;
|
||||
SetArrowHeads(heads, shadowCapPen);
|
||||
|
||||
g.DrawLine(shadowCapPen,
|
||||
graphics.DrawLine(shadowCapPen,
|
||||
this.Left + currentStep,
|
||||
this.Top + currentStep,
|
||||
this.Left + currentStep + this.Width,
|
||||
|
@ -80,7 +83,7 @@ namespace Greenshot.Drawing {
|
|||
|
||||
if ( pen.Width > 0 ) {
|
||||
SetArrowHeads(heads, pen);
|
||||
g.DrawLine(pen, this.Left, this.Top, this.Left + this.Width, this.Top + this.Height);
|
||||
graphics.DrawLine(pen, this.Left, this.Top, this.Left + this.Width, this.Top + this.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ using Greenshot.Drawing.Fields;
|
|||
using Greenshot.Helpers;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using GreenshotPlugin.Core;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Greenshot.Drawing {
|
||||
/// <summary>
|
||||
|
@ -54,7 +55,7 @@ namespace Greenshot.Drawing {
|
|||
if (bitmap != null) {
|
||||
bitmap.Dispose();
|
||||
}
|
||||
bitmap = (Bitmap)value.Clone();
|
||||
bitmap = ImageHelper.Clone(value);
|
||||
Width = value.Width;
|
||||
Height = value.Height;
|
||||
}
|
||||
|
@ -103,6 +104,11 @@ namespace Greenshot.Drawing {
|
|||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
if (bitmap != null) {
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
if (shadow) {
|
||||
ImageAttributes ia = new ImageAttributes();
|
||||
ColorMatrix cm = new ColorMatrix();
|
||||
|
|
|
@ -24,6 +24,7 @@ using System.IO;
|
|||
using System.Windows.Forms;
|
||||
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Greenshot.Drawing {
|
||||
/// <summary>
|
||||
|
@ -98,6 +99,10 @@ namespace Greenshot.Drawing {
|
|||
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
if (cursor != null) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
graphics.CompositingQuality = CompositingQuality.Default;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
cursor.DrawStretched(graphics, Bounds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,10 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode renderMode) {
|
||||
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
|
|
|
@ -174,7 +174,9 @@ namespace Greenshot.Drawing {
|
|||
/// <param name="graphics"></param>
|
||||
/// <param name="renderMode"></param>
|
||||
public override void Draw(Graphics graphics, RenderMode renderMode) {
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
|
|
|
@ -24,6 +24,7 @@ using System.IO;
|
|||
using System.Windows.Forms;
|
||||
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Greenshot.Drawing {
|
||||
/// <summary>
|
||||
|
@ -97,6 +98,10 @@ namespace Greenshot.Drawing {
|
|||
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
if (icon != null) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
graphics.CompositingQuality = CompositingQuality.Default;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
graphics.DrawIcon(icon, Bounds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,9 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
|
|
|
@ -24,6 +24,7 @@ using System.Drawing.Imaging;
|
|||
using System.IO;
|
||||
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Greenshot.Drawing {
|
||||
/// <summary>
|
||||
|
@ -111,6 +112,10 @@ namespace Greenshot.Drawing {
|
|||
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
if (metafile != null) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
graphics.DrawImage(metafile, Bounds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,12 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
|
||||
public override void Draw(Graphics g, RenderMode rm) {
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
|
@ -61,7 +66,7 @@ namespace Greenshot.Drawing {
|
|||
this.Top + currentStep,
|
||||
this.Width,
|
||||
this.Height);
|
||||
g.DrawRectangle(shadowPen, shadowRect);
|
||||
graphics.DrawRectangle(shadowPen, shadowRect);
|
||||
currentStep++;
|
||||
alpha = alpha - (basealpha / steps);
|
||||
}
|
||||
|
@ -72,14 +77,14 @@ namespace Greenshot.Drawing {
|
|||
|
||||
if (!Color.Transparent.Equals(fillColor)) {
|
||||
using (Brush brush = new SolidBrush(fillColor)) {
|
||||
g.FillRectangle(brush, rect);
|
||||
graphics.FillRectangle(brush, rect);
|
||||
}
|
||||
}
|
||||
|
||||
if (lineThickness > 0) {
|
||||
using (Pen pen = new Pen(lineColor)) {
|
||||
pen.Width = lineThickness;
|
||||
g.DrawRectangle(pen, rect);
|
||||
graphics.DrawRectangle(pen, rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -576,6 +576,9 @@ namespace Greenshot.Drawing {
|
|||
MakeUndoable(new SurfaceBackgroundChangeMemento(this, offset), false);
|
||||
SetImage(newImage, false);
|
||||
Invalidate();
|
||||
if (SurfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size))) {
|
||||
SurfaceSizeChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,8 +607,9 @@ namespace Greenshot.Drawing {
|
|||
|
||||
public bool ApplyCrop(Rectangle cropRectangle) {
|
||||
if (isCropPossible(ref cropRectangle)) {
|
||||
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
|
||||
// we should not forget to Dispose the images!!
|
||||
Bitmap tmpImage = ((Bitmap)Image).Clone(cropRectangle, Image.PixelFormat);
|
||||
Bitmap tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare);
|
||||
tmpImage.SetResolution(Image.HorizontalResolution, Image.VerticalResolution);
|
||||
|
||||
Point offset = new Point(-cropRectangle.Left, -cropRectangle.Top);
|
||||
|
@ -614,7 +618,7 @@ namespace Greenshot.Drawing {
|
|||
|
||||
SetImage(tmpImage, false);
|
||||
elements.MoveBy(offset.X, offset.Y);
|
||||
if (SurfaceSizeChanged != null) {
|
||||
if (SurfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size))) {
|
||||
SurfaceSizeChanged(this);
|
||||
}
|
||||
Invalidate();
|
||||
|
@ -799,14 +803,15 @@ namespace Greenshot.Drawing {
|
|||
|
||||
private Image GetImage(RenderMode renderMode) {
|
||||
// Generate a copy of the original image with a dpi equal to the default...
|
||||
Bitmap clone = ImageHelper.CloneImageToBitmap(Image);
|
||||
Bitmap clone = ImageHelper.Clone(Image);
|
||||
// otherwise we would have a problem drawing the image to the surface... :(
|
||||
using (Graphics graphics = Graphics.FromImage(clone)) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
elements.Draw(graphics, (Bitmap)clone, renderMode, new Rectangle(Point.Empty, clone.Size));
|
||||
// Do not set the following, the containers need to decide themselves
|
||||
//graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
//graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
//graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
//graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
elements.Draw(graphics, clone, renderMode, new Rectangle(Point.Empty, clone.Size));
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
@ -841,10 +846,11 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
// Elements might need the bitmap, so we copy the part we need
|
||||
using (Graphics graphics = Graphics.FromImage(buffer)) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
// do not set the following, the containers need to decide this themselves!
|
||||
//graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
//graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
//graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
//graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel);
|
||||
graphics.SetClip(targetGraphics);
|
||||
elements.Draw(graphics, buffer, RenderMode.EDIT, clipRectangle);
|
||||
|
|
|
@ -28,6 +28,8 @@ using Greenshot.Drawing.Fields;
|
|||
using Greenshot.Helpers;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using Greenshot.Memento;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
|
||||
namespace Greenshot.Drawing {
|
||||
/// <summary>
|
||||
|
@ -264,13 +266,18 @@ namespace Greenshot.Drawing {
|
|||
HideTextBox();
|
||||
}
|
||||
|
||||
public override void Draw(Graphics g, RenderMode rm) {
|
||||
base.Draw(g, rm);
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
base.Draw(graphics, rm);
|
||||
UpdateFont();
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
|
||||
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(this.Left, this.Top, this.Width, this.Height);
|
||||
if (Selected && rm == RenderMode.EDIT) {
|
||||
DrawSelectionBorder(g, rect);
|
||||
DrawSelectionBorder(graphics, rect);
|
||||
}
|
||||
|
||||
if (text == null || text.Length == 0 ) {
|
||||
|
@ -295,7 +302,7 @@ namespace Greenshot.Drawing {
|
|||
shadowRect.Inflate(-textOffset, -textOffset);
|
||||
}
|
||||
using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) {
|
||||
g.DrawString(text, font, fontBrush, shadowRect);
|
||||
graphics.DrawString(text, font, fontBrush, shadowRect);
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
}
|
||||
|
@ -308,7 +315,7 @@ namespace Greenshot.Drawing {
|
|||
fontRect.Inflate(-textOffset,-textOffset);
|
||||
}
|
||||
using (Brush fontBrush = new SolidBrush(lineColor)) {
|
||||
g.DrawString(text, font, fontBrush, fontRect);
|
||||
graphics.DrawString(text, font, fontBrush, fontRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ namespace GreenshotNetworkImportPlugin {
|
|||
// Convert byte[] to Image
|
||||
memoryStream.Write(imageBytes, 0, imageBytes.Length);
|
||||
using (Image image = Bitmap.FromStream(memoryStream, true)) {
|
||||
ICapture capture = host.GetCapture(ImageHelper.CloneImageToBitmap(image));
|
||||
ICapture capture = host.GetCapture(ImageHelper.Clone(image));
|
||||
capture.CaptureDetails.Title = title;
|
||||
host.ImportCapture(capture);
|
||||
}
|
||||
|
|
|
@ -33,9 +33,7 @@ namespace GreenshotPlugin.Core {
|
|||
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BitmapBuffer));
|
||||
private bool clone;
|
||||
private Bitmap bitmap;
|
||||
public Bitmap Bitmap {
|
||||
get {return bitmap;}
|
||||
}
|
||||
|
||||
[NonSerialized]
|
||||
private BitmapData bmData;
|
||||
[NonSerialized]
|
||||
|
@ -114,30 +112,17 @@ namespace GreenshotPlugin.Core {
|
|||
return;
|
||||
}
|
||||
|
||||
if (SupportsPixelFormat(sourceBmp)) {
|
||||
if (clone) {
|
||||
// Create copy with supported format
|
||||
this.bitmap = sourceBmp.Clone(sourceRect, sourceBmp.PixelFormat);
|
||||
} else {
|
||||
this.bitmap = sourceBmp;
|
||||
}
|
||||
} else {
|
||||
// We can only clone, as we don't support the pixel format!
|
||||
if (!clone) {
|
||||
throw new ArgumentException("Not supported pixel format: " + sourceBmp.PixelFormat);
|
||||
}
|
||||
// When sourceRect is the whole bitmap there is a GDI+ bug in Clone
|
||||
// Clone will than return the same PixelFormat as the source
|
||||
// a quick workaround is using new Bitmap which uses a default of Format32bppArgb
|
||||
if (sourceRect.Equals(bitmapRect)) {
|
||||
this.bitmap = new Bitmap(sourceBmp);
|
||||
} else {
|
||||
this.bitmap = sourceBmp.Clone(sourceRect, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
}
|
||||
this.bitmap = ImageHelper.CloneArea(sourceBmp, 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(sourceBmp)) {
|
||||
throw new ArgumentException("Unsupported pixel format: " + sourceBmp.PixelFormat + " set clone to true!");
|
||||
} else {
|
||||
this.bitmap = sourceBmp;
|
||||
this.rect = sourceRect;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,19 +172,25 @@ namespace GreenshotPlugin.Core {
|
|||
* This is called when serializing the object
|
||||
*/
|
||||
public void GetObjectData(SerializationInfo info, StreamingContext ctxt) {
|
||||
bool isLocked = bitsLocked;
|
||||
if (isLocked) {
|
||||
Unlock();
|
||||
}
|
||||
info.AddValue("bitmap", this.bitmap);
|
||||
if (isLocked) {
|
||||
Lock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the bitmap so we have direct access to the memory
|
||||
*/
|
||||
public void Lock() {
|
||||
if(rect.Width > 0 && rect.Height > 0) {
|
||||
if(rect.Width > 0 && rect.Height > 0 && !bitsLocked) {
|
||||
bmData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
|
||||
bitsLocked = true;
|
||||
|
||||
System.IntPtr Scan0 = bmData.Scan0;
|
||||
IntPtr Scan0 = bmData.Scan0;
|
||||
pointer = (byte*)(void*)Scan0;
|
||||
|
||||
PrepareForPixelFormat();
|
||||
|
@ -242,14 +233,20 @@ namespace GreenshotPlugin.Core {
|
|||
return;
|
||||
}
|
||||
}
|
||||
// Make sure this.bitmap is unlocked
|
||||
// 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.DrawImage(this.bitmap, destination.Value);
|
||||
graphics.DrawImageUnscaled(this.bitmap, destination.Value);
|
||||
}
|
||||
// If it was locked, lock it again
|
||||
if (isLocked) {
|
||||
Lock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,7 +301,7 @@ namespace GreenshotPlugin.Core {
|
|||
int a = (aIndex==-1) ? 255 : (int)pointer[aIndex+offset];
|
||||
return new int[]{a, pointer[rIndex+offset], pointer[gIndex+offset], pointer[bIndex+offset]};
|
||||
} else {
|
||||
return new int[]{0,0,0,0};
|
||||
return new int[]{255,255,255,255};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,15 +319,6 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the supplied Bitmap has a PixelFormat we support
|
||||
*/
|
||||
private bool SupportsPixelFormat(Bitmap bitmap) {
|
||||
return (bitmap.PixelFormat.Equals(PixelFormat.Format32bppArgb) ||
|
||||
bitmap.PixelFormat.Equals(PixelFormat.Format32bppRgb) ||
|
||||
bitmap.PixelFormat.Equals(PixelFormat.Format24bppRgb));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some internal values for accessing the bitmap according to the PixelFormat
|
||||
*/
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace GreenshotPlugin.Core {
|
|||
if (image != null && image is Bitmap && ((image.Width * image.Height) > 0)) {
|
||||
cropRectangle.Intersect(new Rectangle(0,0, image.Width, image.Height));
|
||||
if (cropRectangle.Width != 0 || cropRectangle.Height != 0) {
|
||||
returnImage = (image as Bitmap).Clone(cropRectangle, image.PixelFormat);
|
||||
returnImage = CloneArea(image, cropRectangle, PixelFormat.DontCare);
|
||||
image.Dispose();
|
||||
image = returnImage;
|
||||
return true;
|
||||
|
@ -90,6 +90,12 @@ namespace GreenshotPlugin.Core {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for the FindAutoCropRectangle
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="colorPoint"></param>
|
||||
/// <returns></returns>
|
||||
private static Rectangle FindAutoCropRectangle(BitmapBuffer buffer, Point colorPoint) {
|
||||
Rectangle cropRectangle = Rectangle.Empty;
|
||||
Color referenceColor = buffer.GetColorAtWithoutAlpha(colorPoint.X,colorPoint.Y);
|
||||
|
@ -163,6 +169,11 @@ namespace GreenshotPlugin.Core {
|
|||
return cropRectangle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load an image from file
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public static Bitmap LoadBitmap(string filename) {
|
||||
if (string.IsNullOrEmpty(filename)) {
|
||||
return null;
|
||||
|
@ -179,7 +190,7 @@ namespace GreenshotPlugin.Core {
|
|||
try {
|
||||
using (Image tmpImage = ExtractVistaIcon(imageFileStream)) {
|
||||
if (tmpImage != null) {
|
||||
fileBitmap = CloneImageToBitmap(tmpImage);
|
||||
fileBitmap = Clone(tmpImage);
|
||||
}
|
||||
}
|
||||
} catch (Exception vistaIconException) {
|
||||
|
@ -192,7 +203,7 @@ namespace GreenshotPlugin.Core {
|
|||
// We create a copy of the bitmap, so everything else can be disposed
|
||||
using (Icon tmpIcon = new Icon(imageFileStream, new Size(1024,1024))) {
|
||||
using (Image tmpImage = tmpIcon.ToBitmap()) {
|
||||
fileBitmap = ImageHelper.CloneImageToBitmap(tmpImage);
|
||||
fileBitmap = Clone(tmpImage);
|
||||
}
|
||||
}
|
||||
} catch (Exception iconException) {
|
||||
|
@ -204,45 +215,13 @@ namespace GreenshotPlugin.Core {
|
|||
// We create a copy of the bitmap, so everything else can be disposed
|
||||
imageFileStream.Position = 0;
|
||||
using (Image tmpImage = Image.FromStream(imageFileStream, true, true)) {
|
||||
fileBitmap = ImageHelper.CloneImageToBitmap(tmpImage);
|
||||
fileBitmap = Clone(tmpImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileBitmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone the image to a bitmap
|
||||
/// </summary>
|
||||
/// <param name="srcImage">Image to clone</param>
|
||||
/// <returns>Bitmap</returns>
|
||||
public static Bitmap CloneImageToBitmap(Image srcImage) {
|
||||
Bitmap returnImage;
|
||||
int width = srcImage.Width;
|
||||
int height = srcImage.Height;
|
||||
float horizontalResolution = srcImage.HorizontalResolution;
|
||||
float verticalResolution = srcImage.VerticalResolution;
|
||||
PixelFormat pixelFormat = srcImage.PixelFormat;
|
||||
if (srcImage is Metafile) {
|
||||
pixelFormat = PixelFormat.Format32bppArgb;
|
||||
}
|
||||
// Make sure Greenshot supports the pixelformat, if not convert to one we support
|
||||
if (!isSupported(pixelFormat)) {
|
||||
pixelFormat = PixelFormat.Format24bppRgb;
|
||||
}
|
||||
returnImage = new Bitmap(width, height, pixelFormat);
|
||||
returnImage.SetResolution(horizontalResolution, verticalResolution);
|
||||
using (Graphics graphics = Graphics.FromImage(returnImage)) {
|
||||
if (Image.IsAlphaPixelFormat(pixelFormat)) {
|
||||
graphics.Clear(Color.Transparent);
|
||||
} else {
|
||||
graphics.Clear(Color.White);
|
||||
}
|
||||
graphics.DrawImageUnscaled(srcImage, 0, 0);
|
||||
}
|
||||
return returnImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if we support the supplied PixelFormat
|
||||
*/
|
||||
|
@ -414,9 +393,9 @@ namespace GreenshotPlugin.Core {
|
|||
nullColor = Color.Transparent;
|
||||
}
|
||||
|
||||
using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, applyRect)) {
|
||||
using (BitmapBuffer bbbDest = new BitmapBuffer(sourceBitmap, applyRect, true)) {
|
||||
bbbDest.Lock();
|
||||
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, applyRect)) {
|
||||
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, applyRect, false)) {
|
||||
bbbSrc.Lock();
|
||||
Random rand = new Random();
|
||||
|
||||
|
@ -426,25 +405,25 @@ namespace GreenshotPlugin.Core {
|
|||
long[] waSums = new long[wlen];
|
||||
long[] wcSums = new long[wlen];
|
||||
long[] aSums = new long[wlen];
|
||||
long[] bSums = new long[wlen];
|
||||
long[] gSums = new long[wlen];
|
||||
long[] rSums = new long[wlen];
|
||||
long[] gSums = new long[wlen];
|
||||
long[] bSums = new long[wlen];
|
||||
for (int y = 0; y < applyRect.Height; ++y) {
|
||||
long waSum = 0;
|
||||
long wcSum = 0;
|
||||
long aSum = 0;
|
||||
long bSum = 0;
|
||||
long gSum = 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;
|
||||
bSums[wx] = 0;
|
||||
gSums[wx] = 0;
|
||||
rSums[wx] = 0;
|
||||
gSums[wx] = 0;
|
||||
bSums[wx] = 0;
|
||||
|
||||
if (srcX >= 0 && srcX < bbbDest.Width) {
|
||||
for (int wy = 0; wy < wlen; ++wy) {
|
||||
|
@ -460,9 +439,9 @@ namespace GreenshotPlugin.Core {
|
|||
wp >>= 8;
|
||||
|
||||
aSums[wx] += wp * colors[0];
|
||||
bSums[wx] += wp * colors[3];
|
||||
gSums[wx] += wp * colors[2];
|
||||
rSums[wx] += wp * colors[1];
|
||||
gSums[wx] += wp * colors[2];
|
||||
bSums[wx] += wp * colors[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,24 +449,22 @@ namespace GreenshotPlugin.Core {
|
|||
waSum += wwx * waSums[wx];
|
||||
wcSum += wwx * wcSums[wx];
|
||||
aSum += wwx * aSums[wx];
|
||||
bSum += wwx * bSums[wx];
|
||||
gSum += wwx * gSums[wx];
|
||||
rSum += wwx * rSums[wx];
|
||||
gSum += wwx * gSums[wx];
|
||||
bSum += wwx * bSums[wx];
|
||||
}
|
||||
}
|
||||
|
||||
wcSum >>= 8;
|
||||
|
||||
if (waSum == 0 || wcSum == 0) {
|
||||
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
|
||||
if (waSum == 0 || wcSum == 0) {
|
||||
bbbDest.SetColorAt(0, y, nullColor);
|
||||
}
|
||||
} else {
|
||||
int alpha = (int)(aSum / waSum);
|
||||
int blue = (int)(bSum / wcSum);
|
||||
int green = (int)(gSum / wcSum);
|
||||
int red = (int)(rSum / wcSum);
|
||||
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
|
||||
int green = (int)(gSum / wcSum);
|
||||
int blue = (int)(bSum / wcSum);
|
||||
bbbDest.SetColorAt(0, y, Color.FromArgb(alpha, red, green, blue));
|
||||
}
|
||||
}
|
||||
|
@ -497,17 +474,17 @@ namespace GreenshotPlugin.Core {
|
|||
waSums[i] = waSums[i + 1];
|
||||
wcSums[i] = wcSums[i + 1];
|
||||
aSums[i] = aSums[i + 1];
|
||||
bSums[i] = bSums[i + 1];
|
||||
gSums[i] = gSums[i + 1];
|
||||
rSums[i] = rSums[i + 1];
|
||||
gSums[i] = gSums[i + 1];
|
||||
bSums[i] = bSums[i + 1];
|
||||
}
|
||||
|
||||
waSum = 0;
|
||||
wcSum = 0;
|
||||
aSum = 0;
|
||||
bSum = 0;
|
||||
gSum = 0;
|
||||
rSum = 0;
|
||||
gSum = 0;
|
||||
bSum = 0;
|
||||
|
||||
int wx;
|
||||
for (wx = 0; wx < wlen - 1; ++wx) {
|
||||
|
@ -515,9 +492,9 @@ namespace GreenshotPlugin.Core {
|
|||
waSum += wwx * waSums[wx];
|
||||
wcSum += wwx * wcSums[wx];
|
||||
aSum += wwx * aSums[wx];
|
||||
bSum += wwx * bSums[wx];
|
||||
gSum += wwx * gSums[wx];
|
||||
rSum += wwx * rSums[wx];
|
||||
gSum += wwx * gSums[wx];
|
||||
bSum += wwx * bSums[wx];
|
||||
}
|
||||
|
||||
wx = wlen - 1;
|
||||
|
@ -525,9 +502,9 @@ namespace GreenshotPlugin.Core {
|
|||
waSums[wx] = 0;
|
||||
wcSums[wx] = 0;
|
||||
aSums[wx] = 0;
|
||||
bSums[wx] = 0;
|
||||
gSums[wx] = 0;
|
||||
rSums[wx] = 0;
|
||||
gSums[wx] = 0;
|
||||
bSums[wx] = 0;
|
||||
|
||||
int srcX = x + wx - r;
|
||||
|
||||
|
@ -545,9 +522,9 @@ namespace GreenshotPlugin.Core {
|
|||
wp >>= 8;
|
||||
|
||||
aSums[wx] += wp * (long)colors[0];
|
||||
bSums[wx] += wp * (long)colors[3];
|
||||
gSums[wx] += wp * (long)colors[2];
|
||||
rSums[wx] += wp * (long)colors[1];
|
||||
gSums[wx] += wp * (long)colors[2];
|
||||
bSums[wx] += wp * (long)colors[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -555,23 +532,20 @@ namespace GreenshotPlugin.Core {
|
|||
waSum += (long)wr * waSums[wx];
|
||||
wcSum += (long)wr * wcSums[wx];
|
||||
aSum += (long)wr * aSums[wx];
|
||||
bSum += (long)wr * bSums[wx];
|
||||
gSum += (long)wr * gSums[wx];
|
||||
rSum += (long)wr * rSums[wx];
|
||||
gSum += (long)wr * gSums[wx];
|
||||
bSum += (long)wr * bSums[wx];
|
||||
}
|
||||
|
||||
wcSum >>= 8;
|
||||
|
||||
if (parentBounds.Contains(applyRect.Left, applyRect.Top + y) ^ invert) {
|
||||
if (waSum == 0 || wcSum == 0) {
|
||||
if (parentBounds.Contains(applyRect.Left + x, applyRect.Top + y) ^ invert) {
|
||||
bbbDest.SetColorAt(x, y, nullColor);
|
||||
}
|
||||
} else {
|
||||
int alpha = (int)(aSum / waSum);
|
||||
int blue = (int)(bSum / wcSum);
|
||||
int green = (int)(gSum / wcSum);
|
||||
int red = (int)(rSum / wcSum);
|
||||
if (parentBounds.Contains(applyRect.Left + x, applyRect.Top + y) ^ invert) {
|
||||
int green = (int)(gSum / wcSum);
|
||||
int blue = (int)(bSum / wcSum);
|
||||
bbbDest.SetColorAt(x, y, Color.FromArgb(alpha, red, green, blue));
|
||||
}
|
||||
}
|
||||
|
@ -731,5 +705,103 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
return newBitmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the supplied Bitmap has a PixelFormat we support
|
||||
/// </summary>
|
||||
/// <param name="bitmap">bitmap to check</param>
|
||||
/// <returns>bool if we support it</returns>
|
||||
public static bool SupportsPixelFormat(Bitmap bitmap) {
|
||||
return SupportsPixelFormat(bitmap.PixelFormat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if we support the pixel format
|
||||
/// </summary>
|
||||
/// <param name="pixelformat">PixelFormat to check</param>
|
||||
/// <returns>bool if we support it</returns>
|
||||
public static bool SupportsPixelFormat(PixelFormat pixelformat) {
|
||||
return (pixelformat.Equals(PixelFormat.Format32bppArgb) ||
|
||||
pixelformat.Equals(PixelFormat.Format32bppRgb) ||
|
||||
pixelformat.Equals(PixelFormat.Format24bppRgb));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for just cloning which calls the CloneArea
|
||||
/// </summary>
|
||||
/// <param name="sourceBitmap">Image to clone</param>
|
||||
/// <returns>Bitmap with clone image data</returns>
|
||||
public static Bitmap Clone(Image sourceBitmap) {
|
||||
return CloneArea(sourceBitmap, Rectangle.Empty, PixelFormat.DontCare);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone an image, taking some rules into account:
|
||||
/// 1) When sourceRect is the whole bitmap there is a GDI+ bug in Clone
|
||||
/// Clone will than return the same PixelFormat as the source
|
||||
/// a quick workaround is using new Bitmap which uses a default of Format32bppArgb
|
||||
/// 2) When going from a transparent to a non transparent bitmap, we draw the background white!
|
||||
/// </summary>
|
||||
/// <param name="sourceBitmap">Source bitmap to clone</param>
|
||||
/// <param name="sourceRect">Rectangle to copy from the source, use Rectangle.Empty for all</param>
|
||||
/// <param name="targetFormat">Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported)</param>
|
||||
/// <returns></returns>
|
||||
public static Bitmap CloneArea(Image sourceBitmap, Rectangle sourceRect, PixelFormat targetFormat) {
|
||||
Bitmap newImage = null;
|
||||
Rectangle bitmapRect = new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height);
|
||||
|
||||
// Make sure the source is not Rectangle.Empty
|
||||
if (Rectangle.Empty.Equals(sourceRect)) {
|
||||
sourceRect = new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height);
|
||||
}
|
||||
|
||||
// If no pixelformat is supplied
|
||||
if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat) {
|
||||
if (SupportsPixelFormat(sourceBitmap.PixelFormat)) {
|
||||
targetFormat = sourceBitmap.PixelFormat;
|
||||
} else if (Image.IsAlphaPixelFormat(sourceBitmap.PixelFormat)) {
|
||||
targetFormat = PixelFormat.Format32bppArgb;
|
||||
} else {
|
||||
targetFormat = PixelFormat.Format24bppRgb;
|
||||
}
|
||||
}
|
||||
|
||||
// check the target format
|
||||
if (!SupportsPixelFormat(targetFormat)) {
|
||||
if (Image.IsAlphaPixelFormat(targetFormat)) {
|
||||
targetFormat = PixelFormat.Format32bppArgb;
|
||||
} else {
|
||||
targetFormat = PixelFormat.Format24bppRgb;
|
||||
}
|
||||
}
|
||||
|
||||
bool destinationIsTransparent = Image.IsAlphaPixelFormat(targetFormat);
|
||||
bool sourceIsTransparent = Image.IsAlphaPixelFormat(sourceBitmap.PixelFormat);
|
||||
bool fromTransparentToNon = !destinationIsTransparent && sourceIsTransparent;
|
||||
bool isBitmap = sourceBitmap is Bitmap;
|
||||
bool isAreaEqual = sourceRect.Equals(bitmapRect);
|
||||
if (isAreaEqual || fromTransparentToNon || !isBitmap) {
|
||||
// Rule 1: if the areas are equal, always copy ourselves
|
||||
newImage = new Bitmap(bitmapRect.Width, bitmapRect.Height, targetFormat);
|
||||
using (Graphics graphics = Graphics.FromImage(newImage)) {
|
||||
if (fromTransparentToNon) {
|
||||
// Rule 2: Make sure the background color is white
|
||||
graphics.Clear(Color.White);
|
||||
}
|
||||
// decide fastest copy method
|
||||
if (isAreaEqual) {
|
||||
graphics.DrawImageUnscaled(sourceBitmap, 0, 0);
|
||||
} else {
|
||||
graphics.DrawImage(sourceBitmap, 0, 0, sourceRect, GraphicsUnit.Pixel);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Let GDI+ decide how to convert, need to test what is quicker...
|
||||
newImage = (sourceBitmap as Bitmap).Clone(sourceRect, targetFormat);
|
||||
}
|
||||
// Make sure both images have the same resolution
|
||||
newImage.SetResolution(sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution);
|
||||
return newImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,7 +209,12 @@ namespace Greenshot.Interop {
|
|||
private void Dispose(bool disposing) {
|
||||
if (null != this._COMObject) {
|
||||
if(Marshal.IsComObject(this._COMObject)) {
|
||||
try {
|
||||
while (Marshal.ReleaseComObject(this._COMObject) > 0) ;
|
||||
} catch (Exception ex) {
|
||||
LOG.WarnFormat("Problem releasing {0}", _COMType);
|
||||
LOG.Warn("Error: ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
this._COMObject = null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue