我有我在形式中添加的图像。我如何填写图像的一部分?
我有这个
我想要实现的目标:
答案 0 :(得分:3)
floodfill 一个区域,你需要一个食品填充程序而且很少。
见这个例子:
它使用两个图片框,也是一个显示所选颜色的标签。
两个鼠标点击事件,一个用于选择颜色:
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例程取自this post;它基本上是wikipedia算法的直接实现..:
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<Point> stack = new Stack<Point>();
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(p.X, p.Y);
if (cx == c0)
{
bmp.SetPixel(p.X, p.Y, c1);
stack.Push(new Point(p.X, p.Y + 1));
stack.Push(new Point(p.X, p.Y - 1));
stack.Push(new Point(p.X + 1, p.Y));
stack.Push(new Point(p.X - 1, p.Y));
}
}
}
更新
我已经更新了代码,以包含一个将鼠标点击位置缩放到图像像素点的功能;现在它也适用于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));
}