Flood Fill Algorithms

前端 未结 7 2214
借酒劲吻你
借酒劲吻你 2020-11-30 08:40

Its the weekend again, and that means I get to play with my hobby project.

I\'ve gotten tired of creating test levels by hand, so I thought I\'d take a break from en

相关标签:
7条回答
  • 2020-11-30 08:41

    In all fairness it should be quite simple. Since you have the basic tile structure anyway the algorithm would be fairly simple:

    Select Tile To Fill:    
    Fill Till    
    Check neighbouring Tiles - If Empty Then Fill    
    Repeat, for all filled tiles.
    

    Disclaimer: The above is a very basic description. There are many references on the web which explain it a lot better than I can.

    0 讨论(0)
  • 2020-11-30 08:44

    The Wikipedia article is pretty good. As long as your grids are small, just about anything will work.

    Earlier this fall I did some flood filling on 10 megapixel scanned images. (The problem was to remove black edges from book pages that had been scanned on a photocopier.) In that case there are only two colors so I essentially treated the problem like a search in an undirected graph, with each pixel connected to its neighbors along the four compass directions. I maintained a separate bitmap to keep track of which pixels had been visited.

    The main findings were

    • Don't try recursive depth-first search. You really want an explicit data structure.

    • An auxiliary queue uses much less space than a stack. About forty times less space. In other words, prefer breadth-first search to depth-first search.

    Again, these findings apply only to grids with multiple megapixels. On a nice small grid like the one shown in your question, any simple algorithm should work.

    0 讨论(0)
  • 2020-11-30 08:44

    Here is example how to use GDI+ routines in C# program.

    ( https://www.pinvoke.net/default.aspx/gdi32.extfloodfill )

    using System.Runtime.InteropServices;
    //insert by Zswang(wjhu111#21cn.com) at 2007-05-22
    [DllImport("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
    [DllImport("gdi32.dll")]
    public static extern IntPtr CreateSolidBrush(int crColor);
    [DllImport("gdi32.dll")]
    public static extern bool ExtFloodFill(IntPtr hdc, int nXStart, int nYStart, 
        int crColor, uint fuFillType);
    [DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);
    [DllImport("gdi32.dll")]
    public static extern int GetPixel(IntPtr hdc, int x, int y);
    public static uint FLOODFILLBORDER = 0;
    public static uint FLOODFILLSURFACE = 1;
    
    private void button1_Click(object sender, EventArgs e)
    {
        Graphics vGraphics = Graphics.FromHwnd(Handle);
        vGraphics.DrawRectangle(Pens.Blue, new Rectangle(0, 0, 300, 300));
        vGraphics.DrawRectangle(Pens.Blue, new Rectangle(50, 70, 300, 300));
        IntPtr vDC = vGraphics.GetHdc();
        IntPtr vBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.Red));
        IntPtr vPreviouseBrush = SelectObject(vDC, vBrush);
        ExtFloodFill(vDC, 10, 10, GetPixel(vDC, 10, 10), FLOODFILLSURFACE);
        SelectObject(vDC, vPreviouseBrush);
        DeleteObject(vBrush);
        vGraphics.ReleaseHdc(vDC);
    }
    

    Instead of using Graphics vGraphics = Graphics.FromHwnd(Handle); , if you are calling this in OnPaint event handler, you may use e.Graphics . Worked for me quite well.

    Sometimes its better not to reinvent algorithm and use existing routines, although you may get some problems with this when porting to Mono.

    0 讨论(0)
  • 2020-11-30 08:52

    general reference

    optimized algorithm in C#

    0 讨论(0)
  • 2020-11-30 08:52

    Simple function without check the color tolerance

    Using:

    var img = Image.FromFile("test.png");
    img = img.FloodFill(new Point(0, 0), Color.Red);
    img.Save("testcomplete.png", ImageFormat.Png);
    

    Main function:

        public static Image FloodFill(this Image img, Point pt, Color color)
        {
            Stack<Point> pixels = new Stack<Point>();
            var targetColor = ((Bitmap)img).GetPixel(pt.X, pt.Y);
            pixels.Push(pt);
    
            while (pixels.Count > 0)
            {
                Point a = pixels.Pop();
                if (a.X < img.Width && a.X > -1 && a.Y < img.Height && a.Y > -1)
                {
                    if (((Bitmap)img).GetPixel(a.X, a.Y) == targetColor)
                    {
                        ((Bitmap)img).SetPixel(a.X, a.Y, color);
                        pixels.Push(new Point(a.X - 1, a.Y));
                        pixels.Push(new Point(a.X + 1, a.Y));
                        pixels.Push(new Point(a.X, a.Y - 1));
                        pixels.Push(new Point(a.X, a.Y + 1));
                    }
                }
            }
            return img;
        }
    
    0 讨论(0)
  • 2020-11-30 08:54

    Wikpedia provides some pseudocode examples of different flood fill techniques on their Flood fill article. Which technique you choose depends on the application.

    Remember that flood filling can easily be threaded (similar to how quicksort can be).

    0 讨论(0)
提交回复
热议问题