/// <summary> /// Fills the area surrounding the point with the color passed in /// </summary> /// <param name="bitmap">The bitmap to be edited</param> /// <param name="x">The x value of the pointer location</param> /// <param name="y">The y value of the pointer location</param> /// <param name="color">The color to fill the area with</param> public static void Fill(WriteableBitmap bitmap, int x, int y, int color) { toFillWith = color; //use the using keyword to ensure the BitmapReader is disposed of before the method returns. using (BitmapReader bmpReader = new BitmapReader(bitmap)) { toBeFilled = bmpReader.GetPixeli(x, y); if (toBeFilled != toFillWith) { FloodFillScanline(bmpReader, x, y); } } }
public static void RedrawSelection() { if (selectionMade && selectionDisplaying) { //first do the draw logic for the rectangle WriteableBitmap oldbmp = new WriteableBitmap(bmp.PixelWidth, bmp.PixelHeight); oldbmp.PixelBuffer.AsStream().Write(beforeSelection, 0, beforeSelection.Length); using (BitmapReader oldReader = new BitmapReader(oldbmp)) { using (BitmapReader newReader = new BitmapReader(bmp)) { //top line for (int i = selection.topLeft.x; i <= selection.bottomRight.x; i++) { int color = oldReader.GetPixeli(i, selection.topLeft.y); newReader.SetPixel(i, selection.topLeft.y, color); } //bottom line for (int i = selection.topLeft.x; i <= selection.bottomRight.x; i++) { int color = oldReader.GetPixeli(i, selection.bottomRight.y); newReader.SetPixel(i, selection.bottomRight.y, color); } //left line for (int i = selection.topLeft.y; i <= selection.bottomRight.y; i++) { int color = oldReader.GetPixeli(selection.topLeft.x, i); newReader.SetPixel(selection.topLeft.x, i, color); } //right for (int i = selection.topLeft.y; i <= selection.bottomRight.y; i++) { int color = oldReader.GetPixeli(selection.bottomRight.x, i); newReader.SetPixel(selection.bottomRight.x, i, color); } } } byte[] b = new byte[beforeSelection.Length]; bmp.PixelBuffer.ToArray().CopyTo(b, 0); History.EndAction(new Action(b)); bmp.DrawRectangle(selection.topLeft.x, selection.topLeft.y, selection.bottomRight.x, selection.bottomRight.y, Colors.Black); bmp.Invalidate(); } }
/// <summary> /// Uses the scanline algorithm to flood fill a selected area with the color given, starting from the point given. /// </summary> /// <param name="x">The X position to start the fill from</param> /// <param name="y">The Y position to start the fill from</param> private static void FloodFillScanline(BitmapReader bmpReader, int x, int y) { Queue <P> points = new Queue <P>(); points.Enqueue(new P(x, y)); while (points.Count > 0) { P temp = points.Dequeue(); int y1 = temp.y; while (y1 >= 0 && bmpReader.GetPixeli(temp.x, y1) == toBeFilled) { y1--; } y1++; bool toBeFilledLeft = false; bool toBeFilledRight = false; while (y1 < bmpReader.Height && bmpReader.GetPixeli(temp.x, y1) == toBeFilled) { bmpReader.SetPixel(temp.x, y1, toFillWith); if (!toBeFilledLeft && (temp.x > 0 && bmpReader.GetPixeli(temp.x - 1, y1) == toBeFilled)) { points.Enqueue(new P(temp.x - 1, y1)); toBeFilledLeft = true; } else if (toBeFilledLeft && (temp.x > 0 && bmpReader.GetPixeli(temp.x - 1, y1) != toBeFilled)) { toBeFilledLeft = false; } if (!toBeFilledRight && (temp.x < bmpReader.Width - 1 && bmpReader.GetPixeli(temp.x + 1, y1) == toBeFilled)) { points.Enqueue(new P(temp.x + 1, y1)); toBeFilledRight = true; } else if (toBeFilledRight && (temp.x < bmpReader.Width - 1 && bmpReader.GetPixeli(temp.x + 1, y1) != toBeFilled)) { toBeFilledRight = false; } y1++; } } }