C # WindowsForms PictureBox: преобразование координат управления и положения пикселя в изображении - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть элемент управления с PictureBox внутри.PictureBox отображает изображение (в режиме Zoom, по крайней мере, в этом конкретном случае).Мне нужно сделать два вида вещей:

  • Щелкните мышью и выясните, к какому пикселю изображения я попал
  • Нарисуйте вертикальную линию над PictureBox в указанном столбце вthe image.

Очевидно, мне нужны какие-то преобразования координат между контрольными координатами и (строкой, столбцом) пикселя в изображении.Первый, который я мог бы найти (www.codeproject.com/Articles/20923/Mouse-Position-over-Image-in-a-PictureBox), но не наоборот.Есть идеи?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

После нескольких попыток нарисовать графические элементы на растровом изображении, а не на содержащем PictureBox, я нашел этот подход неуклюжим: он создает больше проблем, чем решает. Я вернулся к предложению TaW ( This Posting, function SetImageScale(PictureBox pbox, out RectangleF rectImage, out float zoom).)

Если вы знаете прямоугольник 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);
    }

Функции были протестированы и, похоже, делают то, что должны.

Помните : эти преобразования действительны, только если PictureBox находится в режиме Zoom.

0 голосов
/ 12 сентября 2018

Я могу предложить «обходной путь»: вы не рисуете линии и т. Д. На PictureBox, а вместо этого на самом растровом изображении, используя его Graphics.Тогда вы можете использовать только координаты изображения (строка, столбец) и не нужно конвертировать из контроля в изображение.Обратный путь (от щелчка мыши до строки и столбца), как вы упоминаете, решен и может быть использован.

...