From 13059f3c2e019b918a1285d3dad1c4082c26e996 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Tue, 3 May 2016 18:45:10 -0700 Subject: [PATCH] Added POC of image processing for image imports. --- OSCADSharp/OSCADSharp.ConsoleTests/Program.cs | 5 +- OSCADSharp/OSCADSharp/OSCADSharp.csproj | 2 + OSCADSharp/OSCADSharp/Solids/ImportedImage.cs | 197 ++++++++++++++++++ 3 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 OSCADSharp/OSCADSharp/Solids/ImportedImage.cs diff --git a/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs b/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs index 682f3c5..d8c0103 100644 --- a/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs +++ b/OSCADSharp/OSCADSharp.ConsoleTests/Program.cs @@ -56,8 +56,9 @@ namespace OSCADSharp.ConsoleTests static void Main(string[] args) { - var model = new ImportedModel("seahawkImport.stl", new Bounds(new Vector3(1, 1, 1), new Vector3(-1, -1, -1))); - model.ToFile("modelTest").Open(); + var img = new ImportedImage("seahawks coaster.png"); + img.ToFile("seaImg").Open(); + //makePeg(); //var diam = new Variable("mainColumn", Inches.Half); diff --git a/OSCADSharp/OSCADSharp/OSCADSharp.csproj b/OSCADSharp/OSCADSharp/OSCADSharp.csproj index 16d3bd5..500fceb 100644 --- a/OSCADSharp/OSCADSharp/OSCADSharp.csproj +++ b/OSCADSharp/OSCADSharp/OSCADSharp.csproj @@ -34,6 +34,7 @@ + @@ -47,6 +48,7 @@ + diff --git a/OSCADSharp/OSCADSharp/Solids/ImportedImage.cs b/OSCADSharp/OSCADSharp/Solids/ImportedImage.cs new file mode 100644 index 0000000..c39087f --- /dev/null +++ b/OSCADSharp/OSCADSharp/Solids/ImportedImage.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OSCADSharp.DataBinding; +using OSCADSharp.Spatial; +using System.Drawing; + +namespace OSCADSharp.Solids +{ + /// + /// An image file imported and processed into a 3D object + /// + public class ImportedImage : OSCADObject + { + #region Private Fields + private string imagePath; + + List cubes; + #endregion + + #region Constructors / Initialization + /// + /// Creates an imported image with the default settings + /// + /// + public ImportedImage(string imagePath) + { + this.imagePath = imagePath; + + this.cubes = this.processImage(); + } + + private List processImage() + { + Bitmap img = new Bitmap(Image.FromFile(this.imagePath)); + if(img.Width > 200 || img.Height > 200) + { + throw new InvalidOperationException("Cannot process images larger greater than 200x200 pixels"); + } + + List cubes = new List(); + bool[,] visited = new bool[img.Width, img.Height]; + + Point? start = this.getNextPoint(img, ref visited, img.Width-1, img.Height-1); + do + { + System.Drawing.Color color = img.GetPixel(((Point)start).X, ((Point)start).Y); + + var cube = this.traverseNext(img, (Point)start, ref visited, color); + if(cube != null) + { + this.markVisited(ref visited, cube, (Point)start, img); + if(color.A != 0) + { + cubes.Add(cube.Translate(((Point)start).X, ((Point)start).Y, 0) + .Color(String.Format("[{0}, {1}, {2}]", color.R == 0 ? 0 : color.R / 255, color.G == 0 ? 0 : color.G / 255, color.B == 0 ? 0 : color.B / 255), color.A)); + } + } + + start = this.getNextPoint(img, ref visited, img.Width-1, img.Height-1); + } while (start != null); + + return cubes; + } + + private void markVisited(ref bool[,] visited, Cube cube, Point start, Bitmap img) + { + var bounds = cube.Bounds(); + for(int column = start.X; column < start.X + bounds.Width; column++) + { + for (int row = start.Y; row < start.Y + bounds.Length; row++) + { + visited[column, row] = true; + } + } + } + + Cube traverseNext(Bitmap img, Point start, ref bool[,] visited, System.Drawing.Color color, Cube cube = null) + { + bool canTraverse = true; + if(cube != null) + { + canContinueTraversal(img, ref start, ref visited, color, cube, ref canTraverse); + } + else + { + canTraverse = pixelCanBeTraversed(img, ref visited, new Point(start.X + 1, start.Y + 1), color) && + pixelCanBeTraversed(img, ref visited, new Point(start.X + 1, start.Y), color) && + pixelCanBeTraversed(img, ref visited, new Point(start.X, start.Y + 1), color); + } + + + if(canTraverse) + { + if (cube == null) + { + cube = new Cube(); + cube.Size.X += 1; + cube.Size.Y += 1; + + return traverseNext(img, start, ref visited, color, cube); + } + else + { + cube.Size.X += 1; + cube.Size.Y += 1; + return traverseNext(img, start, ref visited, color, cube); + } + } + else + { + + if(cube == null) + { + return new Cube(); + } + else + { + return cube; + } + } + + } + + private void canContinueTraversal(Bitmap img, ref Point start, ref bool[,] visited, Color color, Cube cube, ref bool canTraverse) + { + var bounds = cube.Bounds(); + for (int column = start.X; column < start.X + bounds.Width && canTraverse; column++) + { + for (int row = start.Y; row < start.Y + bounds.Length && canTraverse; row++) + { + if (start.X + column >= img.Width || start.Y + row >= img.Height) + { + canTraverse = false; + } + else + { + canTraverse = canTraverse && pixelCanBeTraversed(img, ref visited, new Point(column, row), color); + } + } + } + } + + bool pixelCanBeTraversed(Bitmap img, ref bool[,] visited, Point pixel, Color colorToMatch) { + return pixel.X < img.Width && pixel.Y < img.Height && + visited[pixel.X, pixel.Y] == false && img.GetPixel(pixel.X, pixel.Y) == colorToMatch; + + } + + Point? getNextPoint(Bitmap img, ref bool[,] visited, int width, int height) + { + for (int column = 0; column < width; column++) + { + for (int row = 0; row < height; row++) + { + if(visited[column, row] == false) + { + return new Point(column, row); + } + } + } + + return null; + } + #endregion + + #region OSCADObject Overrides + public override void Bind(string property, Variable variable) + { + throw new NotImplementedException(); + } + + public override Bounds Bounds() + { + throw new NotImplementedException(); + } + + public override OSCADObject Clone() + { + throw new NotImplementedException(); + } + + public override Vector3 Position() + { + throw new NotImplementedException(); + } + + public override string ToString() + { + var obj = new MultiStatementObject("union()", cubes); + return obj.ToString(); + } + #endregion + } +}