如何用颜色填充部分图像?

我有我在forms中添加的图像。如何填写图像的一部分?

我有这个

我有这个

我想要实现的目标:

我想要的是什么

填充一个区域,你需要一个食品填充程序,而其他很少。

看这个例子:

在此处输入图像描述

它使用两个图片框,也是一个标签来显示所选的颜色。

还有两个鼠标点击事件,一个用于选择颜色:

private void pictureBoxPalette_MouseClick(object sender, MouseEventArgs e) { Point sPt = scaledPoint(pictureBoxPalette, e.Location); lbl_color.BackColor = ((Bitmap)pictureBoxPalette.Image).GetPixel(sPt.X, sPt.Y); } 

..和一个称为填充:

 private void pictureBoxTgt_MouseClick(object sender, MouseEventArgs e) { Point sPt = scaledPoint(pictureBoxTgt, e.Location); Bitmap bmp = (Bitmap)pictureBoxTgt.Image; Color c0 = bmp.GetPixel(sPt.X, sPt.Y); Fill4(bmp, sPt, c0, lbl_color.BackColor); pictureBoxTgt.Image = bmp; } 

Floodfill例程来自这篇文章 ; 它基本上是维基百科算法的直接实现..:

 static void Fill4(Bitmap bmp, Point pt, Color c0, Color c1) { Color cx = bmp.GetPixel(pt.X, pt.Y); if (cx.GetBrightness() < 0.01f) return; // optional, to prevent filling a black grid Rectangle bmpRect = new Rectangle(Point.Empty, bmp.Size); Stack stack = new Stack(); int x0 = pt.X; int y0 = pt.Y; stack.Push(new Point(x0, y0) ); while (stack.Any() ) { Point p = stack.Pop(); if (!bmpRect.Contains(p)) continue; cx = bmp.GetPixel(pX, pY); if (cx == c0) { bmp.SetPixel(pX, pY, c1); stack.Push(new Point(pX, pY + 1)); stack.Push(new Point(pX, pY - 1)); stack.Push(new Point(pX + 1, pY)); stack.Push(new Point(pX - 1, pY)); } } } 

更新

我已经更新了代码,以包含一个将鼠标单击位置缩放到图像像素点的function; 现在它也适用于SizeMode=StretchImage ,所以你可以处理整个图像..

 static Point scaledPoint(PictureBox pb, Point pt) { float scaleX = 1f * pb.Image.Width / pb.ClientSize.Width; float scaleY = 1f * pb.Image.Height / pb.ClientSize.Height; return new Point((int)(pt.X * scaleX), (int)(pt.Y * scaleY)); } 

当然,您可以保存图像。

请注意,您的原始图像是4bpp,在着色之前必须转换为24bpp或更好。

另请注意,对于SizeMode=Zoom ,计算更复杂一些。 这是一个适用于任何SizeMode的示例。:

 static Point scaledPoint(PictureBox pbox, Point pt) { Size si = pbox.Image.Size; Size sp = pbox.ClientSize; int left = 0; int top = 0; if (pbox.SizeMode == PictureBoxSizeMode.Normal || pbox.SizeMode == PictureBoxSizeMode.AutoSize) return pt; if (pbox.SizeMode == PictureBoxSizeMode.CenterImage) { left = (sp.Width - si.Width) / 2; top = (sp.Height - si.Height) / 2; return new Point(pt.X - left, pt.Y - top); } if (pbox.SizeMode == PictureBoxSizeMode.Zoom) { if (1f * si.Width / si.Height < 1f * sp.Width / sp.Height) left = (sp.Width - si.Width * sp.Height / si.Height) / 2; else top = (sp.Height - si.Height * sp.Width / si.Width) / 2; } pt = new Point(pt.X - left, pt.Y - top); float scaleX = 1f * pbox.Image.Width / (pbox.ClientSize.Width - 2 * left) ; float scaleY = 1f * pbox.Image.Height / (pbox.ClientSize.Height - 2 * top); return new Point((int)(pt.X * scaleX), (int)(pt.Y * scaleY)); }