简体   繁体   English

C#WindowsForms PictureBox:控件坐标和图像中像素位置之间的转换

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

I have a control with a PictureBox within it. 我有一个带有PictureBox的控件。 The PictureBox displays an image (in Zoom mode, at least in this particular case). PictureBox显示图像(至少在这种情况下,在“缩放”模式下)。 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. 在图片的给定列上的PictureBox上绘制一条垂直线。

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. 我可能找到的第一个(www.codeproject.com/Articles/20923/Mouse-Position-over-Image-in-a-PictureBox),反之则不然。 Any ideas? 有任何想法吗?

I can suggest a "workaround": you do not draw lines etc. on the PictureBox, but, instead, on the bitmap itself, using its Graphics. 我可以建议一个“解决方法”:您不要在PictureBox上绘制线条等,而是使用其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. 正如您提到的,另一种方法(从鼠标单击到行和列)已解决并可以使用。

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. 经过几次尝试在位图上而不是在包含PictureBox上绘制图形元素,我发现这种方法比较笨拙:它带来的问题多于解决的方法。 I returned to TaW's proposal ( This Posting, function SetImageScale(PictureBox pbox, out RectangleF rectImage, out float zoom) .) 我返回了TaW的建议( 此发布功能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: 如果您知道rectImage矩形( ImgArea在TAW的代码),既转换(到控件的坐标和图像的列和行是再简单:

    /// <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. 请记住 :仅当PictureBox处于“ Zoom模式时,这些转换才有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM