WinForm使用鼠標裁剪圖像

之前做一個試卷識別的項目的時候需要預先將各個部分裁剪開然後進行識別,而網上的裁剪函數都是記錄鼠標的位置然後進行裁剪

public static Bitmap PartDraw(Image src, Rectangle cutpart)//切割圖片
        {
            Bitmap rectbmp = new Bitmap(cutpart.Width, cutpart.Height, PixelFormat.Format24bppRgb);
            using (Graphics g = Graphics.FromImage(rectbmp))
            {
                g.DrawImage(src, new Rectangle(0, 0, cutpart.Width, cutpart.Height), cutpart, GraphicsUnit.Pixel);
                g.Dispose();
            }
            return rectbmp;
        }

但是這樣做又帶來了一個問題就是如果圖片是zoom了的那麼鼠標的位置和實際圖像的位置就會出現偏移,導致實際截圖的位置和你想截圖的位置完全不一樣。

最後採用了座標比例換算的方法解決了這個問題。

本方法主要關聯四個圖片控件的事件

座標換算的原型函數如下

int originalWidth = this.PicSource.Image.Width;
            int originalHeight = this.PicSource.Image.Height;

            PropertyInfo rectangleProperty = this.PicSource.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
            Rectangle rectangle = (Rectangle)rectangleProperty.GetValue(this.PicSource, null);

            int currentWidth = rectangle.Width;
            int currentHeight = rectangle.Height;

            double rate = (double)currentHeight / (double)originalHeight;

            int black_left_width = (currentWidth == this.PicSource.Width) ? 0 : (this.PicSource.Width - currentWidth) / 2;
            int black_top_height = (currentHeight == this.PicSource.Height) ? 0 : (this.PicSource.Height - currentHeight) / 2;

            int zoom_x = e.X - black_left_width;
            int zoom_y = e.Y - black_top_height;

            double original_x = (double)zoom_x / rate;
            double original_y = (double)zoom_y / rate;

可以使用實際座標來換算得出源座標

所用到的全局變量如下

        bool blnDraw;
        Point start; //畫框的起始點
        Rectangle rect;
        Point Pstart; //原圖的起始點
        Rectangle Orect;//在原圖中尺寸

然後爲圖片控件添加以下事件

 

private void PicSource_MouseDown(object sender, MouseEventArgs e)
        {
            int originalWidth = this.PicSource.Image.Width;
            int originalHeight = this.PicSource.Image.Height;

            PropertyInfo rectangleProperty = this.PicSource.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
            Rectangle rectangle = (Rectangle)rectangleProperty.GetValue(this.PicSource, null);

            int currentWidth = rectangle.Width;
            int currentHeight = rectangle.Height;

            double rate = (double)currentHeight / (double)originalHeight;

            int black_left_width = (currentWidth == this.PicSource.Width) ? 0 : (this.PicSource.Width - currentWidth) / 2;
            int black_top_height = (currentHeight == this.PicSource.Height) ? 0 : (this.PicSource.Height - currentHeight) / 2;

            int zoom_x = e.X - black_left_width;
            int zoom_y = e.Y - black_top_height;

            double original_x = (double)zoom_x / rate;
            double original_y = (double)zoom_y / rate;

            Pstart = new Point((int)original_x, (int)original_y);

            start = e.Location;
            Invalidate();
            blnDraw = true;
        }
private void PicSource_MouseMove(object sender, MouseEventArgs e)
        {
            if (blnDraw)
            {
                if (e.Button != MouseButtons.Left)//判斷是否按下左鍵
                    return;
                Point tempEndPoint = e.Location; //記錄框的位置和大小
                rect.Location = new Point(
                Math.Min(start.X, tempEndPoint.X),
                Math.Min(start.Y, tempEndPoint.Y));
                rect.Size = new Size(
                Math.Abs(start.X - tempEndPoint.X),
                Math.Abs(start.Y - tempEndPoint.Y));
                //記錄繪製大小

                int originalWidth = this.PicSource.Image.Width;
                int originalHeight = this.PicSource.Image.Height;

                PropertyInfo rectangleProperty = this.PicSource.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                Rectangle rectangle = (Rectangle)rectangleProperty.GetValue(this.PicSource, null);

                int currentWidth = rectangle.Width;
                int currentHeight = rectangle.Height;

                double rate = (double)currentHeight / (double)originalHeight;

                int black_left_width = (currentWidth == this.PicSource.Width) ? 0 : (this.PicSource.Width - currentWidth) / 2;
                int black_top_height = (currentHeight == this.PicSource.Height) ? 0 : (this.PicSource.Height - currentHeight) / 2;

                int zoom_x = e.X - black_left_width;
                int zoom_y = e.Y - black_top_height;

                double original_x = (double)zoom_x / rate;
                double original_y = (double)zoom_y / rate;

                Orect.Location = new Point(
                Math.Min(Pstart.X, (int)original_x),
                Math.Min(Pstart.Y, (int)original_y));
                Orect.Size = new Size(
                Math.Abs(Pstart.X - (int)original_x),
                Math.Abs(Pstart.Y - (int)original_y));

                PicSource.Invalidate();

            }
        }
private void PicSource_MouseUp(object sender, MouseEventArgs e)
        {
            blnDraw = false; //結束繪製
        }
private void PicSource_Paint(object sender, PaintEventArgs e)
        {
            if (blnDraw)
            {
                if (PicSource.Image != null)
                {
                    if (rect != null && rect.Width > 0 && rect.Height > 0)
                    {
                        e.Graphics.DrawRectangle(new Pen(Color.Red, 3), rect);//重新繪製顏色爲紅色
                    }
                }
            }
        }

最後效果如圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章