C# WindowsForms PictureBox: Transformation between control coordinates and pixel position in image

倖福魔咒の 提交于 2021-02-10 16:07:28

问题


I have a control with a PictureBox within it. The PictureBox displays an image (in Zoom mode, at least in this particular case). I need to do two kinds of things:

  • Click with the mouse and find out which pixel of the image I hit
  • Draw a vertical line over the PictureBox at a given column in the image.

Obviously, I need some kind of coordinate transformations between the control coordinates and the (row, column) of the pixel in the image. The first one I may have found (www.codeproject.com/Articles/20923/Mouse-Position-over-Image-in-a-PictureBox), but not the vice versa. Any ideas?


回答1:


I can suggest a "workaround": you do not draw lines etc. on the PictureBox, but, instead, on the bitmap itself, using its Graphics. Then you can only use the image coordinates (row, column) and do not need to convert from control to image. The other way round (from mouse click to row and column), as you mention, is solved and can be used.




回答2:


After a few attempts to draw graphical elements on the bitmap rather than on containing PictureBox I found this approach clumsy: it poses more problems than it solves. I returned to TaW's proposal (This Posting, function SetImageScale(PictureBox pbox, out RectangleF rectImage, out float zoom).)

If you know the rectImage rectangle (ImgArea in TaW's code), both conversions (to the control's coordinates and to the column and row of the image are then rather simple:

    /// <summary>
    /// Converts coordinates of a point from the picture box grid into column and row of its image.
    /// </summary>
    /// <param name="pb">The PictureBox.</param>
    /// <param name="ptControl">The point in picture box coordinates (X, Y).</param>
    /// <returns>Point in image coordinates (column, row).</returns>
    private Point ToImageCoordinates(PictureBox pb, Point ptControl)
    {
        if (pb.Image == null)
        {
            return new Point(Int32.MinValue, Int32.MinValue);
        }

        float deltaX    = ptControl.X - rectImage.Left;
        float deltaY    = ptControl.Y - rectImage.Top;

        int column      = (int)(deltaX * (pb.Image.Width / rectImage.Width) + 0.5);
        int row         = (int)(deltaY * (pb.Image.Height / rectImage.Height) + 0.5);

        return new Point(column, row);
    }

    /// <summary>
    /// Converts coordinates of a point from the grid (column, row) into the coordinate system of the picture box.
    /// </summary>
    /// <param name="pb">The PictureBox.</param>
    /// <param name="ptImage">The point in image coordinates (column, row).</param>
    /// <returns>Point in control coordinates (X, Y).</returns>
    private PointF ToControlCoordinates(PictureBox pb, Point ptImage)
    {
        if (pb.Image == null)
        {
            return new Point(Int32.MinValue, Int32.MinValue);
        }

        float deltaX    = ptImage.X * (rectImage.Width / pb.Image.Width);
        float deltaY    = ptImage.Y * (rectImage.Height / pb.Image.Height);

        return new PointF(deltaX + rectImage.Left, deltaY + rectImage.Top);
    }

The functions were tested and seem to do what they should.

Remember: these conversions are only valid if the PictureBox is in the Zoom mode.



来源:https://stackoverflow.com/questions/52278722/c-sharp-windowsforms-picturebox-transformation-between-control-coordinates-and

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!