Как мне перевести координаты экранного пространства в координаты пространства изображения в WinForms PictureBox?

У меня есть приложение, которое отображает изображение внутри элемента управления Windows Forms PictureBox . Для SizeMode элемента управления установлено значение, Zoom так что изображение, содержащееся в, PictureBox будет отображаться с правильным соотношением сторон независимо от размеров PictureBox .

Это отлично подходит для внешнего вида приложения, потому что вы можете изменять размер окна, как хотите, и изображение всегда будет отображаться в наиболее подходящем для него размере. К сожалению, мне также необходимо обрабатывать события щелчка мыши в окне изображения и иметь возможность переводить из координат экранного пространства в координаты пространства изображения.

Похоже, что легко перевести из пространства экрана в пространство управления, но я не вижу очевидного способа перевести из пространства управления в пространство изображения (то есть координату пикселя в исходном изображении, которое было масштабировано в поле изображения).

Есть ли простой способ сделать это, или я должен просто продублировать математику масштабирования, которую они используют внутри, чтобы расположить изображение и сделать перевод самостоятельно?

Ответов (2)

Решение

В зависимости от масштабирования относительный пиксель изображения может находиться в любом месте в нескольких пикселях. Например, если изображение значительно уменьшено, пиксель 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)

Чтобы получить положение в пикселях в изображении, вам нужно просто умножить их на фактические размеры в пикселях изображения, но нормализованные координаты позволяют учитывать точку зрения исходного респондента о разрешении неоднозначности в каждом конкретном случае.