WinForms PictureBox でスクリーン空間座標からイメージ空間座標に変換するにはどうすればよいですか?
-
08-06-2019 - |
質問
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)
画像内のピクセル位置を取得するには、実際の画像ピクセルの寸法を掛けるだけですが、正規化された座標を使用することで、曖昧さの解決に関する元のレスポンダーのポイントにケースバイケースで対処できます。