centos 下 r graphics绘图如何保存_C#图形编程之GDI绘图:(三) 商用级之双缓冲

在上一篇文章 C#图形编程之GDI绘图:(三) 普通级之双缓冲 中我们介绍了两种双缓冲的机制,通过编码实现了第一种方式,在计算量较少的场景下得到了比较满意的效果。但是当计算了较大时,刷新就出现了卡顿。

本篇文章介绍第二种双缓冲方式。再来回顾下我们的代码:

        private void panel1_Paint(object sender, PaintEventArgs e)        {            //黑色底清屏            e.Graphics.Clear(Color.Black);            //第一次输出fps            //实际上这里是不需要的,但由于入门级的绘制太慢,如果不在绘制前输出,就看不到了            e.Graphics.DrawString(string.Format("fps: {0}", (int)fps), Font, Brushes.Yellow, 10, 20);            //绘制小方格,并根据坐标变化实现上移滚动效果            int size = 1;            int xCount = panel1.Width / size + 1;            int yCount = panel1.Height * 2 / size + 1;            for (int i=0; i< xCount; i++)            {                for (int j = 0; j < yCount; j++)                {                    int left = i * size * 2;                    int top = j * size * 2 - start_top - size * 2;                    Rectangle rectItem = new Rectangle(left, top, size, size);                    e.Graphics.FillRectangle(Brushes.AliceBlue, rectItem);                }            }            //计算fps            calculateFPS();            //第二次输出fps            e.Graphics.DrawString(string.Format("fps: {0}", (int)fps), Font, Brushes.Yellow, 10, 20);        }

最耗时间的无疑是两个for循环,如果是500*500像素的界面大小,每次刷新都要做25万次的操作,这太恐怖了。所以这里是我们要优化的关键点。事实上,每次重复的绘制工作都是一样的,只是坐标不同,我们完全可以把绘制工作一次做完,然后保存成一张图到内存中。每次刷新我们只要调整这张图的起始坐标不就可以了吗?这样做,即便是计算量更大也无所谓,因为我只要绘制一次就OK,输出就是一张屏,效率非常稳定。这也正是我们在上一篇文章中提及的第二种方式的双缓冲。原理说清楚了,下面开始设计:

(1)调用刷新,如果内存图为空,则执行绘制;

(2)输出时,分上下两个部分。根据坐标变化,上半部分输出的是剩余的部分,下半部分输出的是超出屏幕的部分,这样就可以完美拼接了;

下面直接上代码:

        Bitmap bmpMem = null;        private void panel1_Paint(object sender, PaintEventArgs e)        {            if (bmpMem == null)            {                bmpMem = new Bitmap(panel1.Width, panel1.Height);                Graphics g = Graphics.FromImage(bmpMem);                int size = 5;                //绘制小方格,并根据坐标变化实现上移滚动效果                int xCount = panel1.Width / size + 1;                int yCount = panel1.Height * 2 / size + 1;                for (int i = 0; i < xCount; i++)                {                    for (int j = 0; j < yCount; j++)                    {                        int left = i * size * 2;                        int top = j * size * 2 - start_top - size * 2;                        Rectangle rectItem = new Rectangle(left, top, size, size);                        g.FillRectangle(Brushes.AliceBlue, rectItem);                    }                }                g.Dispose();            }            //黑色底清屏            e.Graphics.Clear(Color.Black);            //第一次输出fps            //实际上这里是不需要的,但由于入门级的绘制太慢,如果不在绘制前输出,就看不到了            e.Graphics.DrawString(string.Format("fps: {0}", (int)fps), Font, Brushes.Yellow, 10, 20);            if (bmpMem != null)            {                int step = scroll_top % panel1.Height;                Rectangle rectDestTop = new Rectangle(0, 0, panel1.Width, panel1.Height - step);                Rectangle rectSrcTop = new Rectangle(0, step, panel1.Width, panel1.Height - step);                e.Graphics.DrawImage(bmpMem, rectDestTop, rectSrcTop, GraphicsUnit.Pixel);                Rectangle rectDestBottom = new Rectangle(0, panel1.Height - step, panel1.Width, step);                Rectangle rectSrcBottom = new Rectangle(0, 0, panel1.Width, step);                e.Graphics.DrawImage(bmpMem, rectDestBottom, rectSrcBottom, GraphicsUnit.Pixel);                scroll_top++;            }            //计算fps            calculateFPS();            //第二次输出fps            e.Graphics.DrawString(string.Format("fps: {0}", (int)fps), Font, Brushes.Yellow, 10, 20);        }

效果看下图演示:

da0cc7ba77e59c36ee739fdd5c9c326e.gif

由于视频转Gif软件的限制,每帧最少要100ms,所以效果不是很明显,可以看到左上的fps达到了63帧左右。无论是放大还是更小的size,都能够保持稳定。细心的读者也许会发现,在两屏衔接的地方稍有瑕疵,因为这个不是本文要介绍的重点,就不展开了,喜欢钻研的读者可以思考下为什么,如何能够改进。

至此,C#图形编程之GDI绘图系列就讲完了。学会了这个,基本可以达到商用级了。

写在后面

美帝对我们进行了工业软件的封锁,工业软件会涉及到大量的图形化编程。C#做工控软件运行效率比Java高,界面开发比C++容易,笔者做过很多工控方面的项目都是用的C#。希望此文能够给有此方面兴趣的读者带来些许帮助,也祝福我们的国产工业软件早日踏上征途,领先世界。

记录工作和生活中的干货,感兴趣的朋友转发+关注。任何想法可在评论留言。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值