在绘图过程中,可能存在局部绘制,需要把一个图片区域块 copy 到另一图形内部。
针对常用的几种操作方式对比。

本次比较对象为 BitBlt 与 LockBits 方式

BitBlt 实现:

	private void SnapShot(Bitmap des, Bitmap bitmapsrc)
        {
            IntPtr dc;
            IntPtr dc1;
            IntPtr dcbitmap;
            Graphics g;

            //绘制目标区域
            Graphics g1 = System.Drawing.Graphics.FromImage(des);
            dc1 = g1.GetHdc();

            //源图与设备关联
            g = System.Drawing.Graphics.FromImage(bitmapsrc);
            dc = CreateCompatibleDC(g.GetHdc());
            IntPtr pOrig = SelectObject(dc, dcbitmap = bitmapsrc.GetHbitmap());

            for (int i = 0; i < redraw; i++)
                BitBlt(dc1, 0, 0, bitmapsrc.Width, bitmapsrc.Height, dc, 0, 0, TernaryRasterOperations.SRCCOPY);

            DeleteDC(dc);
            DeleteObject(dcbitmap);
            g1.ReleaseHdc(dc1);
            g1.Dispose();
        }

 

调用代码:

        private void button4_Click(object sender, EventArgs e)
        {
            Bitmap bitmapCopy = new Bitmap(bitmap.Width, bitmap.Height);
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            stopWatch.Start();
            SnapShot(bitmapCopy, bitmap);
            stopWatch.Stop();
            Console.WriteLine("bitblt 时间刻度:{0} {1}ms", stopWatch.ElapsedTicks, stopWatch.ElapsedMilliseconds);
            bitmapCopy.Save(@"C:\Users\zhoupeng\Pictures\testbitblt.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        }

 

LockBits 方式实现:

        private void CopyImage(Bitmap des, Bitmap bitmapsrc) {
            Rectangle rect = new Rectangle(0, 0, des.Width, des.Height);
            System.Drawing.Imaging.BitmapData bmpData =
                des.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                bitmapsrc.PixelFormat);


            System.Drawing.Imaging.BitmapData bmpDataSrc =
                bitmapsrc.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                bitmapsrc.PixelFormat);

            unsafe
            {
                for (int j = 0; j < redraw; j++)
                {
                    byte* ptrdes = (byte*)bmpData.Scan0;
                    byte* ptrsrc = (byte*)bmpDataSrc.Scan0;
                    int width = bmpDataSrc.Stride;
                    for (int i = 0; i < rect.Height; i++)
                    {
                        for (int l = 0; l < width; l++)
                        {
                            ptrdes[l] = ptrsrc[l];
                        }

                        ptrdes += width;
                        ptrsrc += width;
                    }
                }
            }
                bitmapsrc.UnlockBits(bmpDataSrc);
            des.UnlockBits(bmpData);

        }

 

LockBits 方式 调用:

        private void button5_Click(object sender, EventArgs e)
        {
            Bitmap bitmapCopy = new Bitmap(bitmap.Width, bitmap.Height);
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            stopWatch.Start();
            CopyImage(bitmapCopy, bitmap);
            stopWatch.Stop();
            Console.WriteLine("bit copy 时间刻度:{0} {1}ms", stopWatch.ElapsedTicks, stopWatch.ElapsedMilliseconds);

            bitmapCopy.Save(@"C:\Users\zhoupeng\Pictures\testbitcopy.jpg", System.Drawing.Imaging.ImageFormat.Bmp);
        }

 

由于两种方式 初使化方式不一样,本例尝试乎略这些步骤,这里使用 redraw 变量差异化工作量,分别测试两种性能.

redraw = 1 结果:
bitblt 时间刻度:818184 81ms
bit copy 时间刻度:401926 40ms

redraw = 2 结果:
bitblt 时间刻度:652939 65ms
bit copy 时间刻度:588758 58ms

redraw = 3 结果:
bitblt 时间刻度:689693 68ms
bit copy 时间刻度:804597 80ms

redraw = 5 结果:
bitblt 时间刻度:858016 85ms
bit copy 时间刻度:1196078 119ms

redraw = 15 结果:
bitblt 时间刻度:1062028 106ms
bit copy 时间刻度:3279949 327ms

redraw = 100 结果:
bitblt 时间刻度:1707719 170ms
bit copy 时间刻度:19362181 1936ms

 

 posted on 2016-06-15 16:41  仰光  阅读(494)  评论(0编辑  收藏  举报