简体   繁体   中英

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

I have been trying to write a program, to be able to load an image on a form and select a rectangle on it, then load that rectangle onto another picture box (pictureBox2), and I also want to be able to highlight what I have selected on the original picture, in pictureBox1, as I move my mouse.

So far I have this code, but it doesn't properly respond to the mouseMove event, the rectangle that I highlight isn't selected properly. What is the problem?

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();
    }
}

I think your problem is the 'original' image size which is not the same as the picturebox size. Try this code to compensate for the zoom ratio between your 'original' image and the picturebox size:

            // 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
                    );
            }

This fixes the red rectangle in my case. But the copied part in picturebox2 is still not correct...

And this fixes the copy to the second picturebox:

            // 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);
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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