如何在 C# 中正确 select 图片框内的图像的特定部分并突出显示它?

How do I properly select a certain part of an image inside a picture box in C# and highlight it?

我一直在尝试编写一个程序,以便能够在表单上加载图像并在其上 select 一个矩形,然后将该矩形加载到另一个图片框 (pictureBox2) 上,而且我还希望能够在我移动鼠标时突出显示我在 pictureBox1 中的原始图片上 select编辑的内容。

到目前为止我有这段代码,但它没有正确响应 mouseMove 事件,我突出显示的矩形未正确 selected。有什么问题?

public partial class Form1 : Form
{
    Bitmap original;
    bool isSelecting;
    int x0, y0, x1, y1;
    public Form1()
    {
        InitializeComponent();
        pictureBox1.MouseDown += new MouseEventHandler(picOriginal_MouseDown);
        pictureBox1.MouseMove += new MouseEventHandler(picOriginal_MouseMove);
        pictureBox1.MouseUp   += new MouseEventHandler(picOriginal_MouseUp);
    }

    #region helpder methods

    // Start selecting the rectangle.
    private void picOriginal_MouseDown(object sender, MouseEventArgs e)
    {
        if(original != null)
        {
            isSelecting = true;
            // Save the start point.
            x0 = e.X;
            y0 = e.Y;
        }
    }

    // Continue selecting.
    private void picOriginal_MouseMove(object sender, MouseEventArgs e)
    {
        if(original != null)
        {
            // Do nothing it we're not selecting an area.
            if(!isSelecting) return;

            // Save the new point.
            x1 = e.X;
            y1 = e.Y;

            // Make a Bitmap to display the selection rectangle.
            Bitmap bm = new Bitmap(original);

            // Draw the rectangle.
            using(Graphics gr = Graphics.FromImage(bm))
            {
                gr.DrawRectangle(Pens.Red,
                    Math.Min(x0, x1), Math.Min(y0, y1),
                    Math.Abs(x0 - x1), Math.Abs(y0 - y1)
                    );
            }

            // Display the temporary bitmap.
            pictureBox1.Image = new Bitmap(bm, new Size(pictureBox1.Width, pictureBox1.Height));
        }
    }

    // Finish selecting the area.
    private void picOriginal_MouseUp(object sender, MouseEventArgs e)
    {
        if(original != null)
        {
            // Do nothing it we're not selecting an area.
            if(!isSelecting) return;
            isSelecting = false;

            // Display the original image.
            pictureBox1.Image = original;

            // Copy the selected part of the image.
            int wid = Math.Abs(x0 - x1);
            int hgt = Math.Abs(y0 - y1);
            if((wid < 1) || (hgt < 1)) return;

            Bitmap area = new Bitmap(wid, hgt);
            using(Graphics gr = Graphics.FromImage(area))
            {
                Rectangle source_rectangle =
                    new Rectangle(Math.Min(x0, x1), Math.Min(y0, y1),
                        wid, hgt);
                Rectangle dest_rectangle =
                    new Rectangle(0, 0, wid, hgt);
                gr.DrawImage(original, dest_rectangle,
                    source_rectangle, GraphicsUnit.Pixel);
            }

            // Display the result.
            pictureBox2.Image = area;
        }
    }

    #endregion

    private void button1_Click(object sender, EventArgs e)
    {
        if(original != null)
        {

        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        OpenFileDialog dialog = new OpenFileDialog();
        dialog.Filter = "jpg files (*.jpg)|*.jpg|All files(*.*)|*.*";
        if(dialog.ShowDialog() == DialogResult.OK)
        {
            original = new Bitmap(dialog.FileName);
            pictureBox1.Image = new Bitmap(original, new Size(pictureBox1.Width,     pictureBox1.Height));
        }
        dialog.Dispose();
    }
}

我认为您的问题是 'original' 图片大小与图片框大小不同。尝试使用此代码来补偿 'original' 图像和图片框大小之间的缩放比例:

            // Draw the rectangle.
            float zoomX = (float)original.Size.Width / pictureBox1.Width;
            float zoomY = (float)original.Size.Height / pictureBox1.Height;

            using (Graphics gr = Graphics.FromImage(bm))
            {
                gr.DrawRectangle(Pens.Red,
                    Math.Min(x0, x1) * zoomX, Math.Min(y0, y1) * zoomY,
                    Math.Abs(x0 - x1) * zoomX, Math.Abs(y0 - y1) * zoomY
                    );
            }

这修复了我的红色矩形。但是picturebox2中复制的部分还是不正确...

这会将副本修复到第二个图片框:

            // Copy the selected part of the image.
            float zoomX = (float)original.Size.Width / pictureBox1.Width;
            float zoomY = (float)original.Size.Height / pictureBox1.Height;
            int wid = (int)(zoomX * Math.Abs(x0 - x1));
            int hgt = (int)(zoomY * Math.Abs(y0 - y1));
            if ((wid < 1) || (hgt < 1)) return;

            Bitmap area = new Bitmap(wid, hgt);
            using (Graphics gr = Graphics.FromImage(area))
            {
                Rectangle source_rectangle =
                    new Rectangle((int)(zoomX * Math.Min(x0, x1)), (int)(zoomY * Math.Min(y0, y1)),
                        wid, hgt);
                Rectangle dest_rectangle =
                    new Rectangle(0, 0, wid, hgt);
                gr.DrawImage(original, dest_rectangle,
                    source_rectangle, GraphicsUnit.Pixel);
            }