如何在WinForms PictureBox中将屏幕空间坐标转换为图像空间坐标?

时间:2020-03-05 18:37:51  来源:igfitidea点击:

我有一个在Windows窗体" PictureBox"控件中显示图像的应用程序。控件的" SizeMode"设置为" Zoom",因此无论" PictureBox"的尺寸如何," PictureBox"中包含的图像都将以正确的方式显示。

这对于应用程序的视觉外观非常有用,因为我们可以根据需要调整窗口大小,并且始终会以最适合的方式显示图像。不幸的是,我还需要处理图片框上的鼠标单击事件,并且需要能够从屏幕空间坐标转换为图像空间坐标。

从屏幕空间转换为控件空间似乎很容易,但是我看不到任何从控件空间转换为图像空间的明显方法(即在图片框中缩放的源图像中的像素坐标)。

有没有简单的方法可以做到这一点,还是我应该复制他们在内部使用的缩放比例数学来定位图像并自己翻译?

解决方案

回答

根据缩放比例,相对图像像素可能在多个像素中的任何位置。例如,如果图像大幅缩小,像素2、10可能代表2、10,一直到20、100),因此我们必须自己做数学运算,并对任何错误承担全部责任! :-)

回答

我只是手动实施翻译。该代码还不错,但确实让我希望他们直接为其提供支持。我可以看到这种方法在许多不同的情况下都是有用的。

我想这就是他们添加扩展方法的原因:)

用伪代码:

// Recompute the image scaling the zoom mode uses to fit the image on screen
imageScale ::= min(pictureBox.width / image.width, pictureBox.height / image.height)

scaledWidth  ::= image.width * imageScale
scaledHeight ::= image.height * imageScale

// Compute the offset of the image to center it in the picture box
imageX ::= (pictureBox.width - scaledWidth) / 2
imageY ::= (pictureBox.height - scaledHeight) / 2

// Test the coordinate in the picture box against the image bounds
if pos.x < imageX or imageX + scaledWidth < pos.x then return null
if pos.y < imageY or imageY + scaledHeight < pos.y then return null

// Compute the normalized (0..1) coordinates in image space
u ::= (pos.x - imageX) / imageScale
v ::= (pos.y - imageY) / imageScale
return (u, v)

要获得图像中的像素位置,只需将其乘以实际图像像素尺寸,但归一化的坐标可以让我们解决原始响应者关于解决歧义的问题。