/// <summary> /// Creates a route for raster-etching the provided image. /// </summary> /// <param name="Image">The image to etch</param> /// <returns>A route for etching the provided image</returns> public Route Route(EtchableImage Image) { Point origin = new Point(0, 0); // Handle the pre-etch trace first Point topRight = new Point(Image.Width - 1, 0); Point bottomRight = new Point(Image.Width - 1, Image.Height - 1); Point bottomLeft = new Point(0, Image.Height - 1); Path preEtchTrace = new Path( new List <Point>() { origin, topRight, bottomRight, bottomLeft, origin }); // Handle the image etching List <Path> etchMoves = new List <Path>(); Point lastPoint = origin; List <Line> etchLines = GetRasterEtchLines(Image); foreach (Line line in etchLines) { // Check if the start of the line or the end is closest to the last point Point lineStart = new Point(line.Start, line.YIndex); Point lineEnd = new Point(line.End, line.YIndex); double startDistance = lastPoint.GetDistance(lineStart); double endDistance = lastPoint.GetDistance(lineEnd); // Go left-to-right if (startDistance <= endDistance) { for (int i = 0; i < line.Segments.Count; i++) { EtchSegment segment = line.Segments[i]; Point etchStart = new Point(segment.Start, line.YIndex); Point etchEnd = new Point(segment.End, line.YIndex); // Run the etch Path etch = new Path(new List <Point> { etchStart, etchEnd }); etchMoves.Add(etch); // Set the last known point to the end of this etch lastPoint = etchEnd; } } // Go right-to-left else { for (int i = line.Segments.Count - 1; i >= 0; i--) { EtchSegment segment = line.Segments[i]; Point etchStart = new Point(segment.End, line.YIndex); Point etchEnd = new Point(segment.Start, line.YIndex); // Run the etch Path etch = new Path(new List <Point> { etchStart, etchEnd }); etchMoves.Add(etch); // Set the last known point to the end of this etch lastPoint = etchEnd; } } } // Done! Route route = new Route(Config, preEtchTrace, etchMoves); return(route); }
/// <summary> /// Breaks the provided image into horizontal raster etch segments. /// </summary> /// <param name="Image">The image to get the raster etch lines for</param> /// <returns>A collection of horizontal lines (each of which can have multiple segments) /// necessary to etch the image in raster mode.</returns> private List <Line> GetRasterEtchLines(EtchableImage Image) { List <Line> lines = new List <Line>(); using (ILockedFramebuffer bitmapBuffer = Image.Bitmap.Lock()) { IntPtr bitmapAddress = bitmapBuffer.Address; for (int y = 0; y < Image.Height; y++) { Line line = new Line(y); bool isInEtchSegment = false; int etchStart = 0; for (int x = 0; x < Image.Width; x++) { // Get the blue channel - since this is a black and white image, the channel doesn't really matter byte pixelValue = Marshal.ReadByte(bitmapAddress); // This is a white pixel if (pixelValue > 127) { if (isInEtchSegment) { // Create a new etch segment from the recorded start to the previous pixel EtchSegment segment = new EtchSegment(etchStart, x - 1); line.Segments.Add(segment); isInEtchSegment = false; } } // This is a black pixel else { if (!isInEtchSegment) { // Start a new etch segment isInEtchSegment = true; etchStart = x; } // Check if we're at the last pixel in the row but still in an etch segment else if (x == Image.Width - 1) { EtchSegment segment = new EtchSegment(etchStart, x); line.Segments.Add(segment); isInEtchSegment = false; } } // Move to the next pixel in the bitmap buffer bitmapAddress += 4; } // Ignore lines with no etch segments if (line.Segments.Count > 0) { lines.Add(line); } } } return(lines); }