From 3361873fe7eeb7bd9eb8015f902feaba2b3d4606 Mon Sep 17 00:00:00 2001 From: RKrom Date: Tue, 5 Mar 2013 12:07:48 +0000 Subject: [PATCH] Cleanup of ColorMatrix & ImageAttribute code usage git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2514 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- GreenshotPlugin/Core/FastBitmap.cs | 17 ++- GreenshotPlugin/Core/ImageHelper.cs | 208 +++++++++++++++------------- 2 files changed, 126 insertions(+), 99 deletions(-) diff --git a/GreenshotPlugin/Core/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs index 573379e39..07ceb8ef1 100644 --- a/GreenshotPlugin/Core/FastBitmap.cs +++ b/GreenshotPlugin/Core/FastBitmap.cs @@ -213,7 +213,17 @@ namespace GreenshotPlugin.Core { /// /// Factory for creating a FastBitmap as a destination for the source /// - /// Bitmap to access + /// Bitmap to clone + /// IFastBitmap + public static IFastBitmap CreateCloneOf(Image source) { + return CreateCloneOf(source, source.PixelFormat, Rectangle.Empty); + } + + /// + /// Factory for creating a FastBitmap as a destination for the source + /// + /// Bitmap to clone + /// new Pixelformat /// IFastBitmap public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) { return CreateCloneOf(source, pixelFormat, Rectangle.Empty); @@ -221,7 +231,7 @@ namespace GreenshotPlugin.Core { /// /// Factory for creating a FastBitmap as a destination for the source /// - /// Bitmap to access + /// Bitmap to clone /// Area of the bitmap to access, can be Rectangle.Empty for the whole /// IFastBitmap public static IFastBitmap CreateCloneOf(Image source, Rectangle area) { @@ -231,7 +241,7 @@ namespace GreenshotPlugin.Core { /// /// Factory for creating a FastBitmap as a destination for the source /// - /// Bitmap to access + /// Bitmap to clone /// Pixelformat of the cloned bitmap /// Area of the bitmap to access, can be Rectangle.Empty for the whole /// IFastBitmap @@ -242,7 +252,6 @@ namespace GreenshotPlugin.Core { return fastBitmap; } - /// /// Factory for creating a FastBitmap as a destination /// diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs index a1507af62..ebd21390e 100644 --- a/GreenshotPlugin/Core/ImageHelper.cs +++ b/GreenshotPlugin/Core/ImageHelper.cs @@ -939,32 +939,20 @@ namespace GreenshotPlugin.Core { shadowSize++; } bool canUseGDIBlur = GDIplus.isBlurPossible(shadowSize); - using (Graphics graphics = Graphics.FromImage(returnImage)) { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingMode = CompositingMode.SourceCopy; - - // Draw "shadow" offsetted - ImageAttributes ia = new ImageAttributes(); - ColorMatrix cm = new ColorMatrix(); - cm.Matrix00 = 0; - cm.Matrix11 = 0; - cm.Matrix22 = 0; - if (canUseGDIBlur) { - cm.Matrix33 = darkness + 0.1f; - } else { - cm.Matrix33 = darkness; - } - ia.SetColorMatrix(cm); - Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); - graphics.DrawImage(sourceBitmap, shadowRectangle, 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia); + // Create "mask" for the shadow + ColorMatrix maskMatrix = new ColorMatrix(); + maskMatrix.Matrix00 = 0; + maskMatrix.Matrix11 = 0; + maskMatrix.Matrix22 = 0; + if (canUseGDIBlur) { + maskMatrix.Matrix33 = darkness + 0.1f; + } else { + maskMatrix.Matrix33 = darkness; } - // blur "shadow", apply to whole new image + Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); + ApplyColorMatrix((Bitmap)sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix); - // Gaussian + // blur "shadow", apply to whole new image if (canUseGDIBlur) { // Use GDI Blur Rectangle newImageRectangle = new Rectangle(0, 0, returnImage.Width, returnImage.Height); @@ -975,19 +963,18 @@ namespace GreenshotPlugin.Core { ApplyBoxBlur(returnImage, shadowSize); } - if (returnImage != null) { - using (Graphics graphics = Graphics.FromImage(returnImage)) { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - // draw original with a TextureBrush so we have nice antialiasing! - using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) { - // We need to do a translate-tranform otherwise the image is wrapped - graphics.TranslateTransform(offset.X, offset.Y); - graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height); - } + // Draw the original image over the shadow + using (Graphics graphics = Graphics.FromImage(returnImage)) { + // Make sure we draw with the best quality! + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + // draw original with a TextureBrush so we have nice antialiasing! + using (Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp)) { + // We need to do a translate-tranform otherwise the image is wrapped + graphics.TranslateTransform(offset.X, offset.Y); + graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height); } } return returnImage; @@ -999,17 +986,77 @@ namespace GreenshotPlugin.Core { /// Bitmap to create a negative off /// Negative bitmap public static Bitmap CreateNegative(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); - Color invertedColor = Color.FromArgb(color.A, color.R ^ 255, color.G ^ 255, color.B ^ 255); - bb.SetColorAt(x, y, invertedColor); - } - } - bb.Unlock(); - return bb.Bitmap; + Bitmap clone = (Bitmap)ImageHelper.Clone(sourceImage); + ColorMatrix invertMatrix = new ColorMatrix(new float[][] { + new float[] {-1, 0, 0, 0, 0}, + new float[] {0, -1, 0, 0, 0}, + new float[] {0, 0, -1, 0, 0}, + new float[] {0, 0, 0, 1, 0}, + new float[] {1, 1, 1, 1, 1} + }); + ApplyColorMatrix(clone, invertMatrix); + return clone; + } + /// + /// Apply a color matrix to the image + /// + /// Image to apply matrix to + /// ColorMatrix to apply + public static void ApplyColorMatrix(Bitmap source, ColorMatrix colorMatrix) { + ApplyColorMatrix(source, Rectangle.Empty, source, Rectangle.Empty, colorMatrix); + } + + /// + /// Apply a color matrix by copying from the source to the destination + /// + /// Image to copy from + /// Rectangle to copy from + /// Rectangle to copy to + /// Image to copy to + /// ColorMatrix to apply + public static void ApplyColorMatrix(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ColorMatrix colorMatrix) { + ImageAttributes imageAttributes = new ImageAttributes(); + imageAttributes.ClearColorMatrix(); + imageAttributes.SetColorMatrix(colorMatrix); + ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes); + } + + /// + /// Apply image attributes to the image + /// + /// Image to apply matrix to + /// ImageAttributes to apply + public static void ApplyColorMatrix(Bitmap source, ImageAttributes imageAttributes) { + ApplyImageAttributes(source, Rectangle.Empty, source, Rectangle.Empty, imageAttributes); + } + + /// + /// Apply a color matrix by copying from the source to the destination + /// + /// Image to copy from + /// Rectangle to copy from + /// Rectangle to copy to + /// Image to copy to + /// ImageAttributes to apply + public static void ApplyImageAttributes(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ImageAttributes imageAttributes) { + if (sourceRect == Rectangle.Empty) { + sourceRect = new Rectangle(0, 0, source.Width, source.Height); + } + if (dest == null) { + dest = source; + } + if (destRect == Rectangle.Empty) { + destRect = new Rectangle(0, 0, dest.Width, dest.Height); + } + using (Graphics graphics = Graphics.FromImage(dest)) { + // Make sure we draw with the best quality! + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.CompositingMode = CompositingMode.SourceCopy; + + graphics.DrawImage(source, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes); } } @@ -1017,7 +1064,7 @@ namespace GreenshotPlugin.Core { /// Returns a b/w of Bitmap /// /// Bitmap to create a b/w of - /// Threshold for monochrome filter (0 - 255), lower value means less black + /// Threshold for monochrome filter (0 - 255), lower value means less black /// b/w bitmap public static Bitmap CreateMonochrome(Image sourceImage, byte threshold) { using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(sourceImage, sourceImage.PixelFormat)) { @@ -1085,10 +1132,7 @@ namespace GreenshotPlugin.Core { // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format. Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); float adjustedBrightness = brightness - 1.0f; - // get a graphics object from the new image - using (Graphics graphics = Graphics.FromImage(newBitmap)) { - // create the grayscale ColorMatrix - ColorMatrix colorMatrix = new ColorMatrix( + ColorMatrix applyColorMatrix = new ColorMatrix( new float[][] { new float[] {contrast, 0, 0, 0, 0}, // scale red new float[] {0, contrast, 0, 0, 0}, // scale green @@ -1097,15 +1141,12 @@ namespace GreenshotPlugin.Core { new float[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1} }); - //create some image attributes - ImageAttributes attributes = new ImageAttributes(); - attributes.ClearColorMatrix(); - attributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - attributes.SetGamma(gamma, ColorAdjustType.Bitmap); - - //draw the original image on the new image using the grayscale color matrix - graphics.DrawImage(sourceImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, attributes); - } + //create some image attributes + ImageAttributes attributes = new ImageAttributes(); + attributes.ClearColorMatrix(); + attributes.SetColorMatrix(applyColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + attributes.SetGamma(gamma, ColorAdjustType.Bitmap); + ApplyImageAttributes((Bitmap)sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, attributes); return newBitmap; } @@ -1116,39 +1157,16 @@ namespace GreenshotPlugin.Core { /// Original bitmap /// Bitmap with grayscale public static Image CreateGrayscale(Image sourceImage) { - //create a blank bitmap the same size as original - // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format. - Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - //ColorPalette imagePalette = newBitmap.Palette; - //for (int i = 0; i <= 255; i++) { - // // create greyscale color table - // imagePalette.Entries[i] = Color.FromArgb(i, i, i); - //} - //newBitmap.Palette = imagePalette; - - // get a graphics object from the new image - using (Graphics graphics = Graphics.FromImage(newBitmap)) { - // create the grayscale ColorMatrix - ColorMatrix colorMatrix = 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} - }); - - //create some image attributes - ImageAttributes attributes = new ImageAttributes(); - - //set the color matrix attribute - attributes.SetColorMatrix(colorMatrix); - - //draw the original image on the new image using the grayscale color matrix - graphics.DrawImage(sourceImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, attributes); - } - - return newBitmap; + Bitmap clone = (Bitmap)ImageHelper.Clone(sourceImage); + 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} + }); + ApplyColorMatrix(clone, grayscaleMatrix); + return clone; } ///