Как перевести с координаты экрана на координаты пространства изображения в WinForms PictureBox?
У меня есть приложение, которое отображает изображение внутри элемента управления Windows Forms PictureBox
. Элемент SizeMode
элемента управления установлен на Zoom
, так что изображение, содержащееся в PictureBox
, будет отображаться с учетом аспектности независимо от размеров PictureBox
.
Это отлично подходит для визуального внешнего вида приложения, потому что вы можете размер окна, но вы хотите, и изображение всегда будет отображаться с использованием наилучшего соответствия. К сожалению, мне также необходимо обрабатывать события щелчка мыши на окне изображения и им нужно иметь возможность переводить из координаты экранного пространства в координаты пространства изображения.
Похоже, что легко перевести из пространства экрана в пространство управления, но я не вижу очевидного способа перевода из пространства управления в пространство изображения (то есть координаты пикселя в исходном изображении, которое было масштабировано на изображении коробка).
Есть ли простой способ сделать это, или я просто дублирую математику масштабирования, которую они используют внутри, чтобы разместить изображение и сделать сам перевод?
Ответы
Ответ 1
В зависимости от масштабирования относительный пиксель изображения может находиться где угодно в нескольких пикселях. Например, если изображение значительно уменьшено, пиксель 2, 10 может составлять 2, 10 вплоть до 20, 100), поэтому вам придется самостоятельно выполнять математику и нести полную ответственность за любые неточности!: -)
Ответ 2
Я только что осуществил перевод вручную. Код не так уж плохо, но он оставил меня желающим, чтобы они обеспечивали его поддержку напрямую. Я мог видеть, что такой метод полезен во многих разных обстоятельствах.
Я думаю, почему они добавили методы расширения:)
В псевдокоде:
// 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)
Чтобы получить положение пикселя в изображении, вы просто умножаетесь на фактические размеры пикселя изображения, но нормализованные координаты позволяют вам обратиться к исходной точке ответа об устранении двусмысленности в каждом конкретном случае.