如何从PictureBox获取真实图像像素点x,y [英] How to get real image pixel point x,y from PictureBox
问题描述
我有一个 pictureBox2
并且它设置为 zoom
,我试图找出如何通过 <在图像上获得真实的 x,y 像素位置pictureBox2
上的 code>Mouse.Click.但我尝试了我知道的 3 个可能的想法:没有/有 PointToClient
,PointToScreen
但我永远做对了.
I have a pictureBox2
and it is set to zoom
, I am trying to find out how to to get a real x,y pixel location on the image by Mouse.Click
on pictureBox2
. but I tried 3 possible ideas I knew of: without/with PointToClient
,PointToScreen
but I can never get it right.
private void pictureBox2_Click(object sender, EventArgs e)
{
MouseEventArgs me = (MouseEventArgs)e;
txtpictureHeight.Text =(
(OriginalImage.GetImageHeight()*me.Location.Y)/ pictureBox2.Image.Height).ToString();
txtpictureWidth.Text = (
(OriginalImage.GetImageWidth()* me.Location.X)/ pictureBox2.Image.Width).ToString();
}
一定有一些我需要注意的因素,所以我想使用上面的双重结果,然后我关闭了,但是我的测试图像(1371x2221)的高度仍然有 80 像素.当我使用 Zoom
时,我的 pictureBox2
There must be some factor I need to take care of so I thought to use double result from above and I get closed but there is still 80px off for the height on my test image (1371x2221). As I use Zoom
so there are 2 extra spaces on my pictureBox2
推荐答案
注意,当 SizeMode
设置为 Zoom
时,PictureBox
保持方面比例,并使图像居中,因此除了计算调整后的坐标外,您还还必须考虑填充.
Note that with SizeMode
set to Zoom
, the PictureBox
keeps aspect ratio, and centers the image, so on top of calculating the adjusted coordinates, you also have to take padding into account.
我的建议,不要使用 Click
事件;它旨在检测按钮点击,而不是实际处理鼠标与对象的交互.改用 MouseDown
.
My advice, don't use the Click
event; it is meant to detect button clicks, not to actually process interaction of the mouse with an object. Use MouseDown
instead.
我们需要做的第一件事是获取原始图像的宽度和高度.正如我在评论中指出的,这只是 PictureBox
的 Image
属性内的对象.
The first thing we need to do is get the width and height of the original image. As I noted in my comment, this is simply the object inside the Image
property of the PictureBox
.
接下来,我们需要缩放图像的尺寸和位置.为此,我们可以从 PictureBox
的 ClientRectangle
的维度开始.将这些除以图像宽度和高度,您将获得水平和垂直缩放值.如果将 SizeMode
设置为 StretchImage
,这就是我们所需要的,但是由于纵横比是守恒的,您需要两个值中最小的一个才能获得实际的缩放系数.
Next, we need the dimensions and location of the zoomed image. For that, we can start from the dimensions of the ClientRectangle
of the PictureBox
. Divide those by the image width and height and you'll get the horizontal and vertical zoom values. If the SizeMode
would be set to StretchImage
, that'd be all we need, but since aspect ratio is conserved, you need the smallest of the two values to have the actual zoom factor.
一旦我们得到它,将原始宽度和高度乘以这个缩放系数以获得缩放后的宽度和高度,然后从实际的 ClientRectangle
尺寸中减去它并将其除以二以获得填充对于两个维度.这当然可以通过检查使用两个可能的缩放因子中的哪一个来简化,并且只计算另一个的填充,因为使用缩放因子的维度显然具有 0 填充.
Once we got that, multiply the original width and height by this zoom factor to get the zoomed width and height, then subtract that from the actual ClientRectangle
dimensions and divide it by two to get the padding for both dimensions. This can of course be simplified by checking which of the two possible zoom factors is used, and only calculating the padding for the other one, since the dimension of which the zoom factor was used obviously has 0 padding.
现在您获得了填充和缩放系数,剩下的很简单:从鼠标坐标中减去填充值,然后将两个结果除以缩放系数.
Now you got the padding and zoom factor, the rest is simple: subtract the padding values from the mouse coordinates, and then divide both results by the zoom factor.
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// Default check: left mouse button only
if (e.Button == MouseButtons.Left)
ShowCoords(e.X, e.Y);
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Allows dragging to also update the coords. Checking the button
// on a MouseMove is an easy way to detect click dragging.
if (e.Button == MouseButtons.Left)
ShowCoords(e.X, e.Y);
}
private void ShowCoords(Int32 mouseX, Int32 mouseY)
{
Int32 realW = pictureBox1.Image.Width;
Int32 realH = pictureBox1.Image.Height;
Int32 currentW = pictureBox1.ClientRectangle.Width;
Int32 currentH = pictureBox1.ClientRectangle.Height;
Double zoomW = (currentW / (Double)realW);
Double zoomH = (currentH / (Double)realH);
Double zoomActual = Math.Min(zoomW, zoomH);
Double padX = zoomActual == zoomW ? 0 : (currentW - (zoomActual * realW)) / 2;
Double padY = zoomActual == zoomH ? 0 : (currentH - (zoomActual * realH)) / 2;
Int32 realX = (Int32)((mouseX - padX) / zoomActual);
Int32 realY = (Int32)((mouseY - padY) / zoomActual);
lblPosXval.Text = realX < 0 || realX > realW ? "-" : realX.ToString();
lblPosYVal.Text = realY < 0 || realY > realH ? "-" : realY.ToString();
}
注意,我在这里使用了清晰的像素缩放来更好地显示效果.这是一个小技巧,您可以通过子类化 PictureBox
并覆盖其 OnPaint
方法来调整 PaintEventArgs
中的 Graphics
对象code> 对象并将其 InterpolationMode
设置为 NearestNeighbor
(也建议将 PixelOffsetMode
设置为 Half
;有一个错误其中锐度缩放会移动半个像素除非您这样做).然后使用调整后的事件参数对象调用 base.OnPaint()
.
Note, I used sharp pixel zoom here to better show the effect. It's a little trick you can do by subclassing PictureBox
and overriding its OnPaint
method, to adjust the Graphics
object from the PaintEventArgs
object and set its InterpolationMode
to NearestNeighbor
(It's also advised to set PixelOffsetMode
to Half
; there's a bug where sharp zoom is shifted half a pixel unless you do that). Then you call base.OnPaint()
with that adjusted event args object.
我还在此处添加了更多信息,但这只是您可以从像素坐标计算过程的中间值中获得的所有信息.
I also added some more info on it here, but that's all just stuff you can get from the in-between values of the pixel coordinates calculation process anyway.
这篇关于如何从PictureBox获取真实图像像素点x,y的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!