现在的位置: 首页 > 综合 > 正文

C#任意区域填充

2013年11月03日 ⁄ 综合 ⁄ 共 3909字 ⁄ 字号 评论关闭

namespace FloodFill
{
    public partial class Form1 : Form
    {

...
        public void FloodFill(Bitmap bmp, Point pt, Color fillcolor)
        {
            if (bmp.GetPixel(pt.X, pt.Y).ToArgb() != fillcolor.ToArgb())
            {
                int m_fillcolor = 255 << 8;
                byte[] m_Tolerance = new byte[] { 32, 32, 32 };
                bool[,] PixelsChecked;
                Queue CheckQueue = new Queue();
                m_fillcolor = ColorTranslator.ToWin32(fillcolor);
                m_fillcolor = (int)((byte)((byte)(short)((m_fillcolor >> 16) & 0xffff) & 0xff) + ((byte)(((short)(short)(m_fillcolor & 0xffff) >> 8) & 0xff) << 8) + ((byte)((byte)(short)(m_fillcolor & 0xffff) & 0xff) << 16) + ((byte)(((byte)(short)((m_fillcolor >> 16) & 0xffff) >> 8) & 0xff) << 24));
                BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
                System.IntPtr Scan0 = bmpData.Scan0;
                unsafe
                {
                    byte* scan0 = (byte*)(void*)Scan0;
                    int loc = (bmpData.Stride * pt.Y) + (pt.X * 4);
                    int color = *((int*)(scan0 + loc));
                    PixelsChecked = new bool[bmpData.Width + 1, bmpData.Height + 1];
                    Size bmpsize = new Size(bmpData.Width, bmpData.Height);
                    CheckQueue = new Queue();
                    byte* btcolor2 = (byte*)&color;
                    if (!((pt.X < 0) || (pt.X >= bmpsize.Width) || (pt.Y < 0) || (pt.Y >= bmpsize.Height)))
                    {
                        int* p1 = (int*)(scan0 + (bmpData.Stride * pt.Y) + (pt.X * 4));
                        bool ret1 = true;
                        byte* px1 = (byte*)p1;//change point to byte
                        for (byte i = 0; i < 3; i++)
                        {
                            ret1 &= (px1[i] >= (btcolor2[i] - m_Tolerance[i])) && px1[i] <= (btcolor2[i] + m_Tolerance[i]);
                        }
                        if (!(PixelsChecked[pt.X, pt.Y]) && ret1)
                        {
                            p1[0] = m_fillcolor;   //fill with the color
                            PixelsChecked[pt.X, pt.Y] = true;
                            CheckQueue.Enqueue(new Point(pt.X + 1, pt.Y));
                            CheckQueue.Enqueue(new Point(pt.X, pt.Y + 1));
                            CheckQueue.Enqueue(new Point(pt.X - 1, pt.Y));
                            CheckQueue.Enqueue(new Point(pt.X, pt.Y - 1));
                        }
                    }
                    while (CheckQueue.Count > 0)
                    {
                        Point pt2 = (Point)CheckQueue.Dequeue();
                        if (!((pt2.X < 0) || (pt2.X >= bmpsize.Width) || (pt2.Y < 0) || (pt2.Y >= bmpsize.Height)))
                        {
                            byte* btcolor = (byte*)&color;
                            int* p = (int*)(scan0 + (bmpData.Stride * pt2.Y) + (pt2.X * 4));
                            bool ret = true;
                            byte* px = (byte*)p;//change point to byte
                            for (byte i = 0; i < 3; i++)
                            {
                                ret &= (px[i] >= (btcolor[i] - m_Tolerance[i])) && px[i] <= (btcolor[i] + m_Tolerance[i]);
                            }
                            if (!(PixelsChecked[pt2.X, pt2.Y]) && ret)
                            {
                                p[0] = m_fillcolor;   //fill with the color
                                PixelsChecked[pt2.X, pt2.Y] = true;
                                CheckQueue.Enqueue(new Point(pt2.X + 1, pt2.Y));
                                CheckQueue.Enqueue(new Point(pt2.X, pt2.Y + 1));
                                CheckQueue.Enqueue(new Point(pt2.X - 1, pt2.Y));
                                CheckQueue.Enqueue(new Point(pt2.X, pt2.Y - 1));
                            }
                        }
                    }
                }
                bmp.UnlockBits(bmpData);
            }
        }

//将一个图片放到窗口中去。下面是单击事件

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            FloodFill((Bitmap)pictureBox1.Image, new Point(e.X, e.Y), Color.LightPink);
            pictureBox1.Refresh();
        }
    }

}

抱歉!评论已关闭.