在做绘图相关工作,由于对显示绘制结果实时性有要求,筛选了GDI , 与GDI+ 贴图性能。
这里假设在内存中已绘制完成一张图片,现需求显示在控件上,同时,总是更新全部区域。GDI+ 实现
private void PainDraw(Bitmap bitmap) { pictureBox1.Invalidate(); //只调用Invalidate() 并非实时更新, 它会合并多个无效区,且延时显示, Update() 强制更新 pictureBox1.Update(); } private void pictureBox1_Paint(object sender, PaintEventArgs e) { i++; if (i > 500) { i = 0; } e.Graphics.DrawImage(bitmap, new Rectangle(i, 0, bitmap.Width, bitmap.Height)); }
调用1000次,测帧速
private void button2_Click(object sender, EventArgs e) { System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); path = @"C:\Users\zhoupeng\Pictures\BackgroundDefault.bmp"; if (bitmap == null) bitmap = new Bitmap(path); stopWatch.Start(); for (int i = 0; i < 1000; i++) { PainDraw(bitmap); } stopWatch.Stop(); Console.WriteLine("帧率:{0}", 1000 / (stopWatch.ElapsedMilliseconds / 1000f)); }
结果:
帧率:88.81783帧率:91.14108帧率:92.28497帧率:83.167
GDI 实现
int i = 0; private void SnapShot(PictureBox c, Bitmap bitmapsrc, IntPtr dc1) { IntPtr dc2 = GetWindowDC(c.Handle); i++; if (i > 500) { i = 0; } BitBlt(dc2, i, 0, bitmapsrc.Width, bitmapsrc.Height, dc1, 0, 0, TernaryRasterOperations.SRCCOPY); DeleteDC(dc2); } private void button3_Click(object sender, EventArgs e) { System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); path = @"C:\Users\zhoupeng\Pictures\BackgroundDefault.bmp"; if (bitmap == null) bitmap = new Bitmap(path); stopWatch.Start(); Graphics g = Graphics.FromImage( bitmap); IntPtr dc1 = CreateCompatibleDC(g.GetHdc()); IntPtr dcbitmap; IntPtr pOrig = SelectObject(dc1, dcbitmap = bitmap.GetHbitmap()); for (int i = 0; i < 1000; i++) { SnapShot(pictureBox1, bitmap, dc1); } DeleteDC(dc1); DeleteObject(dcbitmap); g.ReleaseHdc(dc1); g.Dispose(); stopWatch.Stop(); Console.WriteLine("帧率:{0}", 1000 / (stopWatch.ElapsedMilliseconds / 1000f)); }
结果:
帧率:4651.163帧率:4385.965帧率:7812.5帧率:5208.333