c#绘制图像(无闪烁、图像大小随着控件尺寸等比例缩放、截图保存图片)

150 篇文章 161 订阅

class MyPictureBox : PictureBox
{
public Point StartPoint { get; set; }

    public Point currentPoint { get; set; }
    public bool mouseDownSuccess { get; set; }
    public Image oriImage { get; set; }

    public MyPictureBox()
    {
        this.SetStyle(ControlStyles.ResizeRedraw, true);//空间大小改变时,控件会重绘
        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

    }


    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        int width = Math.Abs(currentPoint.X - StartPoint.X);
        int height = Math.Abs(currentPoint.Y - StartPoint.Y);

        Graphics graphics = e.Graphics;
        Rectangle rectangle = new Rectangle(StartPoint.X, StartPoint.Y, width, height);
        graphics.Clear(Color.FromArgb(255, 240, 240, 240));
        graphics.SmoothingMode = SmoothingMode.AntiAlias;//消除锯齿
        if (this.Image != null)
        {
            Rectangle newRectangle = fitInside(new Rectangle(0, 0, this.Width, this.Height), new Size(this.Image.Width, this.Image.Height));//获取图像等比例缩放所需的控件中绘图的区域
            graphics.DrawImage(this.Image, newRectangle);
        }

        Pen pen = new Pen(Color.Red, 2);//指定画笔的颜色和线宽
        graphics.DrawRectangle(pen, rectangle);//绘制圆的边界

        pen.Dispose();
    }
    Rectangle fitInside(Rectangle controlRectangle, Size imgSize)
    {
        int w = controlRectangle.Width;//先以控件宽度作为图像宽度,然后图像高度按照比例缩放
        int h = w * imgSize.Height / imgSize.Width;
        if (h > controlRectangle.Height)
        {
            //只能以控件高度作为图像高度了
            h = controlRectangle.Height;
            w = h * imgSize.Width / imgSize.Height;
        }


        int startX = controlRectangle.X + (controlRectangle.Width - w) / 2;
        int startY = controlRectangle.Y + (controlRectangle.Height - h) / 2;
        return new Rectangle(startX, startY, w, h);

    }
    double[] GetScale(Rectangle controlRectangle, Size imgSize  ,ref int scale)
    {
        int w = controlRectangle.Width;//先以控件宽度作为图像宽度,然后图像高度按照比例缩放
        int h = w * imgSize.Height / imgSize.Width;
        if (h > controlRectangle.Height)
        {
            //只能以控件高度作为图像高度了
            h = controlRectangle.Height;
            w = h * imgSize.Width / imgSize.Height;
            scale = imgSize.Height / controlRectangle.Height;
            return new  double[]{ ((controlRectangle .Width -w)*1.0/ 2),0};//返回截图的起始坐标点需要减去的X、Y
           
        }
        else
        {

            scale = imgSize.Width / controlRectangle.Width;
            return new double[] { 0,((controlRectangle.Height  - h) * 1.0 / 2), 0 };
        }



        }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (!mouseDownSuccess)
        {
            mouseDownSuccess = true;
            StartPoint = e.Location;
        }
    }


    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (mouseDownSuccess)
        {
            if (e != null)
            {
                currentPoint = e.Location;
            }
            this.Invalidate();//鼠标滑动则强制图面刷新,会触发OnPaint事件
        }
    }


    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);
        if (mouseDownSuccess)
        {
            #region 保存截取的图片
            int width = Math.Abs(currentPoint.X - StartPoint.X);
            int height = Math.Abs(currentPoint.Y - StartPoint.Y);

            mouseDownSuccess = false;
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(StartPoint.X, StartPoint.Y, width, height);
            if (rect.Width > 0 && rect.Height > 0)
            {
                if (this.Image != null)
                {
                    int scale = default;

                    double[] array = GetScale(new Rectangle(0, 0, this.Width, this.Height), new Size(this.Image.Width, this.Image.Height),ref scale );

                    int centerX = StartPoint.X + width / 2 - Convert.ToInt32(array[0]);//求截图区域中心点X在控件中图像的坐标
                    int centerY = StartPoint.Y + height / 2 - Convert.ToInt32(array[1]);

                    int newCenterX = Convert.ToInt32(centerX * scale);//求截图区域中心点X在实际图像的坐标
                    int newCenterY = Convert.ToInt32(centerY * scale);
                    int newWidth = Convert.ToInt32(width * scale);//求截图区域在真实图像中的宽度
                    int newHeight = Convert.ToInt32(height * scale);


                    int newStartX = newCenterX - newWidth / 2;//求截图区域起始点在实际图像的坐标
                    int newStartY = newCenterY - newHeight / 2;


                    rect = new System.Drawing.Rectangle(newStartX, newStartY, newWidth, newHeight);
                   
                    Bitmap bmp = new Bitmap(this.Image);
                    Image<Gray, byte> oriImage = new Image<Gray, byte>(bmp);

                    Image<Gray, byte> dstImage = oriImage.GetSubRect(rect);//获取原始图像指定区域的图像

                    Image<Gray, byte> CropImage = new Image<Gray, byte>(dstImage.Size);
                    CvInvoke.cvCopy(dstImage, CropImage, IntPtr.Zero);
                    CropImage.Save("d:\\1.bmp");
                }

            }
            #endregion 
        }
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c#上位机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值