c# 一种图像填充算法

算法来源: https://pengfeixc.com/blog/60d06420e97367196dce3efb

 

非常感谢提供这么优秀的算法,  因为文章里面只有思路,  我写成了C# 代码,  

 

public void seedFillFast(Point pointseed, Color fillcolor, Bitmap bitmap)
        {

            //种子点的坐标必须在图片范围内
            if (pointseed.X < 0 || pointseed.X > bitmap.Width || pointseed.Y < 0 || pointseed.Y > bitmap.Height) return;

            Color backgroundColor = bitmap.GetPixel(pointseed.X, pointseed.Y);
            //如果背景颜色和填充颜色一样,直接返回
            if (backgroundColor == fillcolor) return;

            //1, 创建一个栈, 将起始点压入栈
            Stack<Point> stack = new Stack<Point>();
            stack.Push(pointseed);

            bool reachLeft=false,  reachRight=false; 
            //2, 执行出栈操作, 然后向上走,直到走到与起始点颜色不同像素或者图片边缘停止
            while (stack.Count > 0)
            {
                reachLeft = false;
                reachRight = false;
                Point point = stack.Pop();
                Color pointcolor =bitmap.GetPixel(point.X, point.Y);
                //跑到最高
                while( 1==1)
                {
                    if (point.Y == 0) break;

                    pointcolor = bitmap.GetPixel(point.X, point.Y-1);

                    if (pointcolor != backgroundColor) break;//向上看看能不能爬

                    point.Y -= 1;  //向上爬一格
                }

                //一直向下跑并填色
                while (1 == 1)
                {
                    //判断左右的像素是否可以入栈
                    if(point.X > 0  &&  point.X<bitmap.Width-1)
                    {
                        if(bitmap.GetPixel(point.X - 1, point.Y) == backgroundColor  )
                        {
                            //看看左边的颜色是否为背景色,
                            if (reachLeft == false)
                            {
                                //没有人管,就入栈,并标记已经被管理了
                                stack.Push(new Point(point.X - 1, point.Y));
                                reachLeft = true;  //表示暂时不需要判断左边是否需要入栈了
                            }
                        }
                        else
                        {
                            //颜色不一样,已管理的状态打断了,需要复位为false,
                            reachLeft = false;
                        }


                        if (bitmap.GetPixel(point.X + 1, point.Y) == backgroundColor)
                        {
                            //看看右边的颜色是否为背景色,
                            if (reachRight == false)
                            {
                                //没有人管,就入栈,并标记已经被管理了
                                stack.Push(new Point(point.X + 1, point.Y));
                                reachRight = true;  //表示暂时不需要判断左边是否需要入栈了
                            }
                        }
                        else
                        {
                            //颜色不一样,已管理的状态打断了,需要复位为false,
                            reachRight = false;
                        }

                    }

                    bitmap.SetPixel(point.X, point.Y, fillcolor);   //将当前像素设置为填充色
                    point.Y++;  //将指针向下移动
                    
                    //判断这一列是否处理完成

                    if(point.Y>=bitmap.Height-1  ||  bitmap.GetPixel(point.X,point.Y)!= backgroundColor)
                    {
                        break;  //跳出循环
                    }
                }
                

            }

        }

 

还有一些改善的空间,例如边框的颜色对比太死板了,应该有一定的差值,  一定范围内的颜色都可以看成是背景色.  这个很简单,大家就自己实现了.

 

posted @ 2022-07-18 16:41  小熊V5  阅读(367)  评论(0)    收藏  举报