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

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 
        }
    }

}
当需要修改Jar包中的文件而又不希望重启服务时,可以使用 Arthas,一个Java诊断工具,来实现动态修改文件的目的。下面是具体的操作流程和细节: 1. 在 Linux 服务器上安装 Arthas:可以从 Arthas GitHub 页面下载最新版本的 Arthas。解压后,进入解压后的目录。 2. 运行 Arthas:执行以下命令来启动 Arthas: ``` ./as.sh ``` 3. 选择目标进程:如果你的服务是通过 Jar 包运行的,使用 `java -jar` 命令启动,那么可以直接选择进程 ID 或者输入 Jar 包的路径来选择目标进程。 4. 进入 Arthas 控制台:选择目标进程后,你将进入 Arthas 控制台。 5. 使用 `sc` 命令查找对应的 Class:使用 `sc` 命令结合类名、方法名、或者文件名的关键字来查找包含需要修改的文件的 Class。 ``` sc *Mapper.xml ``` 6. 使用 `jad` 命令反编译 Class:使用 `jad` 命令加上需要反编译的 Class 的全限定名来反编译该 Class。 ``` jad com.example.MyMapper ``` 7. 编辑反编译后的文件:Arthas 会将反编译后的 Java 文件保存在 `/tmp/arthas` 目录下。你可以使用任何文本编辑器来修改这个文件。 ``` vim /tmp/arthas/com/example/MyMapper.java ``` 8. 重新编译并替换原始 Class:在 Arthas 控制台中,使用 `mc` 命令来编译修改后的 Java 文件,并替换原始 Class。 ``` mc /tmp/arthas/com/example/MyMapper.java ``` 9. 退出 Arthas 控制台:完成修改后,你可以使用 `quit` 命令来退出 Arthas 控制台。 10. 验证修改是否生效:通过访问服务或者执行相关操作,验证你的修改是否生效。 请注意,在使用 Arthas 进行动态修改时,需要谨慎操作,确保你对代码的修改是正确的,并且在生产环境中测试修改是否符合预期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

上位机马工

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

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

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

打赏作者

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

抵扣说明:

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

余额充值