从PictureBox绘制的区域获取位图

Leorob88.

成员
加入
12月31日,2020年12月31日
消息
19
编程经验
1-3
您好,我正在尝试用图形和绘图解决问题。首先,我定义了一个图片框区域,然后使用FillRectangle我绘制该区域。

我现在所做的是从该绘制的区域创建一个位图(因为那么我需要使用bitmap.getpixel来检查颜色),但我有点困惑。

我试着做到:
Bitmap IMG =(Bitmap)PictureBox.Image
甚至
Bitmap IMG =新位图((Bitmap)Picturebox.image,新尺寸(470,340))
但是当我尝试或尝试使用它时,我得到错误,说参数不能为空。它建议图像作为错误,就像它在转换为位图时没有正确获得图像。但是,我只需要将绘制的区域转换为位图,但是以任何可能的方式转换为位图。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,805
地点
切萨皮克,va.
编程经验
10+
发布您获得的确切错误。不要解释或总结。

出于好奇心,你是如何首先将位图纳入图片盒的?你不应该刚刚坚持参考该位图吗?图片盒的重要性也在这里是什么?您的问题以实际图像操纵/处理为中心。可以在没有任何UI的情况下完成。为什么甚至涉及图片盒?
 

Leorob88.

成员
加入
12月31日,2020年12月31日
消息
19
编程经验
1-3
嗯,在你的第二个问题上,我有两个图片盒:一个有一个图像,另一个是绘制一些形状(我必须设置可见的真或假,所以我可以将它设置为picturebox.visible),要在第二个照片箱中绘制这些形状,我首先设置该区域,然后使用Graphics.filleRectangle一起使用(所以只有该区域填充并且其余部分没有,所以下面的图像仍然可见,其中该区域未被填满的位置仍然可见) 。
我得到的错误是
system.argumentNullickception:"该值不能为null。参数名称:图像".

该值不能为null。参数名称:--->对不起,这是我尝试翻译,我是意大利人,所以我的软件也是如此,所以我试图用英语翻译我得到的错误消息。
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,686
地点
悉尼,澳大利亚
编程经验
10+
Nothing you draw on a PictureBox in its Paint event handler has anything at all to do with its Image property. That property only has a value if you assign something to it. Drawing on a control doesn't create an Image object. It's just pixels on the screen.

If you want an Image then you have to create one. You can do that before or after the fact. Before would be creating an Image object, drawing on that and then either drawing that onto the PictureBox or assigning it to the Image property. After would be putting your drawing code in its own method with a Graphics parameter, then using that same method to draw on a new Image object after using it to draw on the PictureBox.
 

Leorob88.

成员
加入
12月31日,2020年12月31日
消息
19
编程经验
1-3
@jmplhinney. 我觉得我懂了。我之后是答案"after"假设,或者,我需要的只是创建一个转换它的图像然后进入位图。现在我的问题是:我可以循环绘制同一个图像(是如此明显,我是图形的新手吗?)? IE。喜欢创建一个图像绘图"canvas"在特定点,然后在其他地方绘制,但总是在同一画布上,相同的图像。
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,686
地点
悉尼,澳大利亚
编程经验
10+
You can draw on the same Image object as often as you like but, unlike drawing on a control, previous drawing doesn't get erased as a matter of course. That also means that there's no need to draw the same thing multiple times. If that's what you want, by all means use the same Image object and draw multiple times.
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,686
地点
悉尼,澳大利亚
编程经验
10+
If you had this code to draw on a PictureBox:
C#:
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawString("Hello World", Font, Brushes.Black, 10.0F, 10.0F);
}
然后你可以用这个替换它:
C#:
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
    DoDrawing(e.Graphics);
}

private void DoDrawing(Graphics g)
{
    g.DrawString("Hello World", Font, Brushes.Black, 10.0F, 10.0F);
}
然后这样做:
C#:
var img = new Bitmap(100, 100);

using (var g = Graphics.FromImage(img))
{
    DoDrawing(g);
}
The drawing code can be as complex as you like. One thing I've done in a demo before is create a Bitmap and assign it to the Image property, store drawing data in fields and draw on the PictureBox until the user clicks a Button, then draw the same data on the Bitmap to make it permanent, then clear the fields. This would enable you to discard all changes since the last "save" while everything looks the same to the user whether the drawing is on the control or the Image.
 

Leorob88.

成员
加入
12月31日,2020年12月31日
消息
19
编程经验
1-3
If you had this code to draw on a PictureBox:
C#:
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawString("Hello World", Font, Brushes.Black, 10.0F, 10.0F);
}
然后你可以用这个替换它:
C#:
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
    DoDrawing(e.Graphics);
}

private void DoDrawing(Graphics g)
{
    g.DrawString("Hello World", Font, Brushes.Black, 10.0F, 10.0F);
}
然后这样做:
C#:
var img = new Bitmap(100, 100);

using (var g = Graphics.FromImage(img))
{
    DoDrawing(g);
}
The drawing code can be as complex as you like. One thing I've done in a demo before is create a Bitmap and assign it to the Image property, store drawing data in fields and draw on the PictureBox until the user clicks a Button, then draw the same data on the Bitmap to make it permanent, then clear the fields. This would enable you to discard all changes since the last "save" while everything looks the same to the user whether the drawing is on the control or the Image.
我会试试这个让你知道!它会让我从构建整个字典来定义油漆异常!
 

Leorob88.

成员
加入
12月31日,2020年12月31日
消息
19
编程经验
1-3
抱歉,也许是我不理解。我尝试使用E.Graphics.DrawRectangle在Paint事件处理程序中,假设它会正确创建图像,但是当我去存储位图时,图片框中.Image它会给我发送一个错误。我的代码是:

"for"循环//循环绘制到PictureBox
{
矩形双打=新矩形(新点(x,y),新尺寸(wid,hei));
E.Graphics.DrawRectangle(新笔(Color.Black,1),双语);
}
Bitmap Img =(Bitmap)picturebox.image; // ***
图形path映射= new graphicspath();
//循环以将矩形添加到映射
map.closefigure();
picturebox.region =新地区(地图);

它说system.nullreferenceException(我是意大利人,对不起,但它说"引用未命令对象/元素"。如果我更改为// ***签名的行
Bitmap IMG =新位图((bitmap)picturebox.image,480,340)
它说它改装了system.argumentNulLException:该值不能为null。参数名称:图像。
你说在你的演示中你将图像存储到位图中,以便清除图片框并仍然保留该图像。这正是我缺少的,你如何将其存储到位图中?
 
Last edited:

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,686
地点
悉尼,澳大利亚
编程经验
10+
我告诉你该怎么办,你根本没有这样做。如果您不遵循所提供的说明,那么为什么您希望获得所需的结果?

Step 1: Create a Paint event handler for your PictureBox and use e.Graphics to draw as desired.

首先,只有在适用于所需工作时,请继续执行下一步。

Step 2: Create a method with a parameter of type Graphics. Copy the code from your Paint event handler into that method and replace all references to e.Graphics with the parameter. Replace the code in the Paint event handler with a call to that method and pass e.Graphics as an argument.

执行此操作,只有在其所需工作时,请继续执行下一步。

Step 3: Create a Graphics object by calling Graphics.FromImage and passing the appropriate Bitmap as an argument, then call the method created in step 2 and pass that Graphics object as an argument.

You have now drawn the same thing on both your PictureBox and your Bitmap.

顺便说一下,请不要发布未格式化的代码片段。您可以看到我发布的代码之间的区别以及您发布的内容。请为您提供易于阅读的代码的礼貌。
 

Leorob88.

成员
加入
12月31日,2020年12月31日
消息
19
编程经验
1-3
Basically, it works. It draws Rectangles in the right places. Now, my problem comes to the point when i need to refer to that Bitmap to create a Region to re-draw on the Picturebox.
I literally used the img name like in your code. Now i need to create a new Region 为了 the picture, based on that Bitmap. First i create a GraphicsPath to store data for the Region.
My goal, precisely, is to check the Bitmap every 10x10 area. If the first pixel is Black (which it should be), it adds a Rectangle in the same "pixel" position in the GraphicsPath.
Suppose you check every 10x10 area in a cycle, it comes to the point when it's checking an area into the Bitmap corresponding to the pixel 10;0: my code now is going to check if that pixel in the Bitmap is black (i need to check 10x10 areas, but for this case if the first pixel is Black it's just enough, it means in the Bitmap i drawed a 10x10 Rectangle there); if it is, then i add in the GraphicsPath a Rectangle 10x10 in that position, 10;0.
This, as i said, is cyclically made and handled, inside the same Paint event. Problem is, i don't get any error message, but the problem seems to be when i check the pixel color. My condition to check is

C#:
if (img.GetPixel(x * 10, y * 10).Equals(Color.Black))

but debugging this it seems it doesn't see that as a black pixel. Just for the sake of comprehension, x and y are int to check the picture every 10x10 area (as i said). Meaning, if i remove this condition it keeps as Region the full Picturebox, if i use this condition instead the Region becomes empty, like it doesn't see Color.Black in the checked pixels. So, i suppose i'm wrongly referring to the Bitmap to draw the region?
 
Last edited:
最佳 底部