From 95d8cc6e96cbe147c38c9de1dfb4d2953e213a68 Mon Sep 17 00:00:00 2001 From: Mitchell William Cooper Date: Tue, 11 Aug 2015 10:45:21 +0100 Subject: [PATCH] Bug fix to remove transparency Transparent pixels were causes some opaque pixels to be removed from exported frames (fixes #3). Also fix to Drag drop handler to handle null object. --- ASU/BO/ImageUnpacker.cs | 85 ++++++++++++++++++++++++++++++---- ASU/BO/RegionUnpacker.cs | 32 ++++++------- ASU/Properties/AssemblyInfo.cs | 4 +- ASU/UI/MainForm.cs | 17 +++++-- 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/ASU/BO/ImageUnpacker.cs b/ASU/BO/ImageUnpacker.cs index f2af67e..93ac4aa 100644 --- a/ASU/BO/ImageUnpacker.cs +++ b/ASU/BO/ImageUnpacker.cs @@ -46,11 +46,76 @@ public ImageUnpacker(Bitmap image, string fileName) } this.original = new Bitmap((Bitmap)image.Clone()); this.originalSize = image.Size; + this.original = this.RemoveTransparencyFromImage(this.original); this.boxes = new List(); this.FileName = fileName; this.IsLarge = (this.original.Width * this.original.Height) > (800 * 800); } + private Bitmap RemoveTransparencyFromImage(Bitmap image) + { + Dictionary coloursByArgb = new Dictionary(); + Dictionary transparentPixelsByCoord = new Dictionary(); + Dictionary opaquedByTransparent = new Dictionary(); + Color pixel; + bool containsTransparency = false; + Color transparentPixel; + Color opaquedPixel; + + for(int x = 0; x < image.Width; x++) + { + for(int y = 0; y < image.Height; y++) + { + pixel = image.GetPixel(x, y); + + if (!coloursByArgb.ContainsKey(pixel.ToArgb())) + { + coloursByArgb.Add(pixel.ToArgb(), pixel); + } + if (pixel.A < 255) + { + containsTransparency = true; + transparentPixelsByCoord.Add(new Point(x, y), pixel); + } + } + } + + if (containsTransparency) + { + foreach (Point coord in transparentPixelsByCoord.Keys) + { + transparentPixel = transparentPixelsByCoord[coord]; + if (opaquedByTransparent.ContainsKey(transparentPixel)) + { + opaquedPixel = opaquedByTransparent[transparentPixel]; + } + else + { + opaquedPixel = Color.FromArgb(255, transparentPixel); + + do + { + if (transparentPixel.R > (255 / 2)) + { + opaquedPixel = Color.FromArgb(opaquedPixel.R - 1, opaquedPixel.G, opaquedPixel.B); + } + else + { + opaquedPixel = Color.FromArgb(opaquedPixel.R + 1, opaquedPixel.G, opaquedPixel.B); + } + } while (coloursByArgb.ContainsKey(opaquedPixel.ToArgb())); + + coloursByArgb.Remove(transparentPixel.ToArgb()); + coloursByArgb.Add(opaquedPixel.ToArgb(), opaquedPixel); + opaquedByTransparent.Add(transparentPixel, opaquedPixel); + } + image.SetPixel(coord.X, coord.Y, opaquedPixel); + } + } + + return image; + } + public System.Drawing.Imaging.ColorPalette GetPallette() { return this.pallette; @@ -330,8 +395,8 @@ private void HandleDividedArea(Rectangle region, bool updateCounter, Bitmap imag private void SetBackgroundColour(Bitmap image) { - Dictionary colours = new Dictionary(); - Color presentColour = default(Color); + Dictionary colourCountsByArgb = new Dictionary(); + Color presentColour; int maxCount = 0; for (int x = 0; x <= this.originalSize.Width - 1; x++) @@ -340,13 +405,13 @@ private void SetBackgroundColour(Bitmap image) { presentColour = image.GetPixel(x, y); - if (!colours.ContainsKey(presentColour)) + if (!colourCountsByArgb.ContainsKey(presentColour.ToArgb())) { - colours.Add(presentColour, 1); + colourCountsByArgb.Add(presentColour.ToArgb(), 1); } else { - colours[presentColour] += 1; + colourCountsByArgb[presentColour.ToArgb()] += 1; } if ((x + y) % 100 == 0) @@ -359,17 +424,17 @@ private void SetBackgroundColour(Bitmap image) } } - foreach (Color colour in colours.Keys) + foreach (int colourArgb in colourCountsByArgb.Keys) { - if (colours[colour] >= maxCount) + if (colourCountsByArgb[colourArgb] >= maxCount) { - maxCount = colours[colour]; - this.backgroundColour = colour; + maxCount = colourCountsByArgb[colourArgb]; + this.backgroundColour = Color.FromArgb(colourArgb); } } image.Dispose(); this._isBackgroundColourSet = true; - this.ColoursCount = colours.Count - 1; + this.ColoursCount = colourCountsByArgb.Count - 1; } private void HandleUnpackComplete() diff --git a/ASU/BO/RegionUnpacker.cs b/ASU/BO/RegionUnpacker.cs index e79ca49..829c601 100644 --- a/ASU/BO/RegionUnpacker.cs +++ b/ASU/BO/RegionUnpacker.cs @@ -57,26 +57,26 @@ private static List CreateBoxes(Bitmap image, Rectangle region, Color presentColour = image.GetPixel(x, y); - if (presentColour != background) + if (presentColour.ToArgb() != background.ToArgb()) { newBox = new Rectangle(presentPixel, new Size(0, 0)); x2 = x; - while (x2 < (image.Width - 1) && image.GetPixel(x2, y) != background) + while (x2 < (image.Width - 1) && image.GetPixel(x2, y).ToArgb() != background.ToArgb()) { x2 += 1; newBox = new Rectangle(newBox.X, newBox.Y, newBox.Width + 1, newBox.Height); } y2 = y; - while (y2 < (image.Height - 1) && image.GetPixel(x2, y2) != background) + while (y2 < (image.Height - 1) && image.GetPixel(x2, y2).ToArgb() != background.ToArgb()) { y2 += 1; newBox = new Rectangle(newBox.X, newBox.Y, newBox.Width, newBox.Height + 1); } y2 = y + newBox.Height; - while (y2 < (image.Height - 1) && image.GetPixel(x, y2) != background) + while (y2 < (image.Height - 1) && image.GetPixel(x, y2).ToArgb() != background.ToArgb()) { y2 += 1; newBox = new Rectangle(newBox.X, newBox.Y, newBox.Width, newBox.Height + 1); @@ -204,8 +204,8 @@ private static bool DoBoxesContainAdjacentOrOverlappingPixels(Rectangle box1, Re for (int x = intersection.X; x <= intersection.Right; x++) { for (int y = intersection.Y; y <= intersection.Bottom; y++) - { - if (image.GetPixel(x, y) != background) + { + if (image.GetPixel(x, y).ToArgb() != background.ToArgb()) { return true; } @@ -214,19 +214,17 @@ private static bool DoBoxesContainAdjacentOrOverlappingPixels(Rectangle box1, Re } - if (ForkandBeard.Util.Geometry.GeometryHelper.GetXGapBetweenRectangles(box1, box2) <= UI.MainForm.DistanceBetweenTiles) { for (int y = box1.Y - UI.MainForm.DistanceBetweenTiles; y <= box1.Bottom + UI.MainForm.DistanceBetweenTiles; y++) { - if (y >= box2.Top && y <= box2.Bottom) { if (box2.Left > box1.Right) { - if (image.GetPixel(box1.Right, y) != background) + if (image.GetPixel(box1.Right, y).ToArgb() != background.ToArgb()) { - if (image.GetPixel(box2.Left, y) != background) + if (image.GetPixel(box2.Left, y).ToArgb() != background.ToArgb()) { return true; } @@ -234,9 +232,9 @@ private static bool DoBoxesContainAdjacentOrOverlappingPixels(Rectangle box1, Re } else { - if (image.GetPixel(box1.Left, y) != background) + if (image.GetPixel(box1.Left, y).ToArgb() != background.ToArgb()) { - if (image.GetPixel(box2.Right, y) != background) + if (image.GetPixel(box2.Right, y).ToArgb() != background.ToArgb()) { return true; } @@ -247,19 +245,17 @@ private static bool DoBoxesContainAdjacentOrOverlappingPixels(Rectangle box1, Re } } - if (ForkandBeard.Util.Geometry.GeometryHelper.GetYGapBetweenRectangles(box1, box2) <= UI.MainForm.DistanceBetweenTiles) { for (int x = box1.Left - UI.MainForm.DistanceBetweenTiles; x <= box1.Right + UI.MainForm.DistanceBetweenTiles; x++) { - if (x >= box2.Left && x <= box2.Right) { if (box2.Top > box1.Bottom) { - if (image.GetPixel(x, box1.Bottom) != background) + if (image.GetPixel(x, box1.Bottom).ToArgb() != background.ToArgb()) { - if (image.GetPixel(x, box2.Top) != background) + if (image.GetPixel(x, box2.Top).ToArgb() != background.ToArgb()) { return true; } @@ -267,9 +263,9 @@ private static bool DoBoxesContainAdjacentOrOverlappingPixels(Rectangle box1, Re } else { - if (image.GetPixel(x, box1.Top) != background) + if (image.GetPixel(x, box1.Top).ToArgb() != background.ToArgb()) { - if (image.GetPixel(x, box2.Bottom) != background) + if (image.GetPixel(x, box2.Bottom).ToArgb() != background.ToArgb()) { return true; } diff --git a/ASU/Properties/AssemblyInfo.cs b/ASU/Properties/AssemblyInfo.cs index 0d8f02a..52a20a4 100644 --- a/ASU/Properties/AssemblyInfo.cs +++ b/ASU/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("14.0.0.0")] -[assembly: AssemblyFileVersion("14.0.0.0")] +[assembly: AssemblyVersion("15.0.0.0")] +[assembly: AssemblyFileVersion("15.0.0.0")] diff --git a/ASU/UI/MainForm.cs b/ASU/UI/MainForm.cs index 8ccaa02..57f71ae 100644 --- a/ASU/UI/MainForm.cs +++ b/ASU/UI/MainForm.cs @@ -437,7 +437,10 @@ private void MainPanel_DragDrop(object sender, System.Windows.Forms.DragEventArg { dropped = e.Data.GetData(objFormat); - if (object.ReferenceEquals(dropped.GetType(), typeof(string[]))) + if( + (dropped != null) + && (object.ReferenceEquals(dropped.GetType(), typeof(string[]))) + ) { // Dropped object is an array of string, so assume they are file names. Bitmap image; List fileNames = null; @@ -909,6 +912,7 @@ private void ExportUnpackers(List unpackers) bool userOkToConvertFiles = true; List boxes = null; DateTime lapse = System.DateTime.MinValue; + System.Windows.Forms.DialogResult folderResponse = System.Windows.Forms.DialogResult.Cancel; try { @@ -919,10 +923,17 @@ private void ExportUnpackers(List unpackers) if (this.Selected.Count > 0 || unpackers.Count > 1) { - foreach (BO.ImageUnpacker unpacker in unpackers) + if (PromptForDestinationFolder) { + folderResponse = this.FolderBrowserDialog1.ShowDialog(); + } - if ((PromptForDestinationFolder && this.FolderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) || !PromptForDestinationFolder) + foreach (BO.ImageUnpacker unpacker in unpackers) + { + if ( + (folderResponse == System.Windows.Forms.DialogResult.OK) + || (!PromptForDestinationFolder) + ) { if (PromptForDestinationFolder) {