Нарисуйте прямоугольник внутри графического блока SizeMode Zoom - PullRequest
0 голосов
/ 13 мая 2018

У меня есть графическое окно в проекте WindowsForms с его SizeMode равным "Zoom".

Я хочу нарисовать прямоугольник внутри изображения и получить его координаты относительно изображения, а не к графическому блоку.

Проблема в том, что координаты прямоугольника не совпадают с тем же прямоугольником, выбранным в приложении Windows Paint.

Вот используемый код:

  1. Начать рисование:

    /// <summary>
    /// Starts drawing.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        backupImage = pictureBox1.Image;
        _once = true;
        RectStartPoint = e.Location;
        pictureBox1.Invalidate();
    }
    
  2. При перемещении мыши:

    /// <summary>
    /// While moving mouse event, paint rectangle
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (_once) //Only draw rectangle while drawing mode
        {
            Point tempEndPoint = e.Location;
            Rect.Location = new Point(Math.Min(RectStartPoint.X, tempEndPoint.X),
                Math.Min(RectStartPoint.Y, tempEndPoint.Y));
    
            Rect = new Rectangle(
                Math.Min(tempEndPoint.X, Rect.Left),
                Math.Min(tempEndPoint.Y, Rect.Top),
                Math.Min(e.X - RectStartPoint.X, pictureBox1.ClientRectangle.Width - RectStartPoint.X),
                Math.Min(e.Y - RectStartPoint.Y, pictureBox1.ClientRectangle.Height - RectStartPoint.Y));
    
            pictureBox1.Refresh();
            pictureBox1.CreateGraphics().DrawRectangle(cropPen, Rect);
        }
    }
    
  3. При 2 щелчках закончить прямоугольник рисования:

    /// <summary>
    /// When mouse click is released, write in texbox the rectangle's coordinates.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        if (_once)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                Point tempEndPoint = e.Location;
    
                _once = false;
                string sAux = string.Format("Left: {0}; Top: {1}; Width: {2}; Height: {3} \r\n", Math.Min(tempEndPoint.X, Rect.Left), Math.Min(tempEndPoint.Y, Rect.Top),
                        Math.Min(e.X - RectStartPoint.X, pictureBox1.ClientRectangle.Width - RectStartPoint.X), Math.Min(e.Y - RectStartPoint.Y, pictureBox1.ClientRectangle.Height - RectStartPoint.Y));
    
                textBox1.Text += sAux;
            }
        }
    }
    

Результаты:

Изображение Windows Windows Image

Изображение краски enter image description here

Как видно на обоих изображениях, слева, сверху, ширине и высоте не совпадают.

Можете ли вы сказать мне, как получить тот же результат?

Example2

1 Ответ

0 голосов
/ 14 мая 2018

Вот функция, которая поможет с различными вычислениями:

void SetImageScale(PictureBox pbox, out RectangleF ImgArea , out float zoom)
{
    SizeF sp = pbox.ClientSize;
    SizeF si = pbox.Image.Size;
    float rp = sp.Width / sp.Height;   // calculate the ratios of
    float ri = si.Width / si.Height;   // pbox and image

    if (rp > ri)
    {
        zoom = 1f * sp.Height / si.Height;
        float width = si.Width * zoom;
        float left = (sp.Width - width) / 2;
        ImgArea = new RectangleF(left, 0, width, sp.Height);
    }
    else
    {
        zoom = 1f * sp.Width / si.Width;
        float height = si.Height * zoom;
        float top = (sp.Height - height) / 2;
        ImgArea = new RectangleF(0, top, sp.Width, height);
    }
}

Вот как вы можете использовать его, учитывая Rectangle Rect, который вы создали из координат мыши:

float zoom = 1f;
RectangleF ImgArea = Rectangle.Empty;

SetImageScale(pictureBox1, out ImgArea, out zoom);

Point RLoc = Point.Round(new PointF( (Rect.X - ImgArea.X) / zoom, 
                                     (Rect.Y - ImgArea.Y) / zoom ));
Size RSz = Size.Round(new SizeF(Rect.Width / zoom, Rect.Height / zoom));

label1.Text =  "Selection in mouse coordinates: "  + Rect.ToString();
label2.Text =  "Selection in image coordinates: "  + new Rectangle(RLoc, RSz).ToString();

Это должно работать независимо от того, являются ли изображения альбомными или портретными или какое отношение больше, если оно есть, к изображениям или PictureBox.

enter image description here

Примечаниечто с сильно увеличенным изображением трудно сделать выбор пикселя с дефектом ..

Эта функция является вариантом из этого поста .

...