diff --git a/Greenshot/Drawing/BitmapContainer.cs b/Greenshot/Drawing/BitmapContainer.cs index fd4cb496c..73cf86540 100644 --- a/Greenshot/Drawing/BitmapContainer.cs +++ b/Greenshot/Drawing/BitmapContainer.cs @@ -38,26 +38,78 @@ namespace Greenshot.Drawing { public class BitmapContainer : DrawableContainer, IBitmapContainer { private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BitmapContainer)); - protected Bitmap bitmap; + private Bitmap bitmap; + + /// + /// This is the shadow version of the bitmap, rendered once to save performance + /// Do not serialize, as the shadow is recreated from the original bitmap if it's not available + /// + [NonSerialized] + private Bitmap shadowBitmap = null; + + /// + /// This is the offset for the shadow version of the bitmap + /// Do not serialize, as the offset is recreated + /// + [NonSerialized] + private Point shadowOffset = new Point(-1, -1); public BitmapContainer(Surface parent, string filename) : this(parent) { - AddField(GetType(), FieldType.SHADOW, false); Load(filename); } public BitmapContainer(Surface parent) : base(parent) { AddField(GetType(), FieldType.SHADOW, false); + FieldChanged += BitmapContainer_OnFieldChanged; } + protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) { + if (sender.Equals(this)) { + if (e.Field.FieldType == FieldType.SHADOW) { + ChangeShadowField(); + } + } + } + + public void ChangeShadowField() { + bool shadow = GetFieldValueAsBool(FieldType.SHADOW); + if (shadow) { + CheckShadow(shadow); + this.Width = shadowBitmap.Width; + this.Height = shadowBitmap.Height; + this.Left = this.Left - this.shadowOffset.X; + this.Top = this.Top - this.shadowOffset.Y; + } else { + this.Width = bitmap.Width; + this.Height = bitmap.Height; + if (shadowBitmap != null) { + this.Left = this.Left + this.shadowOffset.X; + this.Top = this.Top + this.shadowOffset.Y; + } + } + } public Bitmap Bitmap { set { if (bitmap != null) { bitmap.Dispose(); } + if (shadowBitmap != null) { + shadowBitmap.Dispose(); + shadowBitmap = null; + } bitmap = ImageHelper.Clone(value); - Width = value.Width; - Height = value.Height; + bool shadow = GetFieldValueAsBool(FieldType.SHADOW); + CheckShadow(shadow); + if (!shadow) { + Width = bitmap.Width; + Height = bitmap.Height; + } else { + Width = shadowBitmap.Width; + Height = shadowBitmap.Height; + this.Left = this.Left - this.shadowOffset.X; + this.Top = this.Top - this.shadowOffset.Y; + } } get { return bitmap; } } @@ -90,13 +142,21 @@ namespace Greenshot.Drawing { if (bitmap != null) { bitmap.Dispose(); } + if (shadowBitmap != null) { + shadowBitmap.Dispose(); + } } bitmap = null; + shadowBitmap = null; } public void Load(string filename) { if (File.Exists(filename)) { - Bitmap = ImageHelper.LoadBitmap(filename); + // Always make sure ImageHelper.LoadBitmap results are disposed some time, + // as we close the bitmap internally, we need to do it afterwards + using (Bitmap tmpImage = ImageHelper.LoadBitmap(filename)) { + Bitmap = tmpImage; + } LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); } } @@ -110,6 +170,12 @@ namespace Greenshot.Drawing { base.Rotate(rotateFlipType); } + private void CheckShadow(bool shadow) { + if (shadow && shadowBitmap == null) { + shadowBitmap = ImageHelper.CreateShadow(bitmap, 1f, 6, ref shadowOffset, PixelFormat.Format32bppArgb); + } + } + public override void Draw(Graphics graphics, RenderMode rm) { if (bitmap != null) { bool shadow = GetFieldValueAsBool(FieldType.SHADOW); @@ -119,16 +185,11 @@ namespace Greenshot.Drawing { graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; if (shadow) { - ImageAttributes ia = new ImageAttributes(); - ColorMatrix cm = new ColorMatrix(); - cm.Matrix00 = 0; - cm.Matrix11 = 0; - cm.Matrix22 = 0; - cm.Matrix33 = 0.25f; - ia.SetColorMatrix(cm); - graphics.DrawImage(bitmap, new Rectangle(Bounds.Left + 2, Bounds.Top + 2, Bounds.Width, Bounds.Height), 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, ia); + CheckShadow(shadow); + graphics.DrawImage(shadowBitmap, Bounds); + } else { + graphics.DrawImage(bitmap, Bounds); } - graphics.DrawImage(bitmap, Bounds); } }