2012-03-24 39 views
5

我需要将1027 * 768位图呈现给客户端窗口(相同大小),并且我没有超过10-15 ms来完成此任务。我正在使用bufferedGraphics分配缓冲的图形接触对象,仍然会注意到巨大的性能问题。通过指针手写向缓冲图形表面写入

我使用不安全的代码来执行我的复制操作发现令人难以置信的结果。我知道Graphics/BufferedGraphics对象在内存中应该有某种绘图表面。我想知道是否有人能够指出我如何使用元帅或其他一些不安全的低级方法写入这个表面的正确方向。

我正在移植一个较旧的c#图形应用程序。我知道c#不是为重型图形设计的,并且有比GDI +更好的工具,但不幸的是我没有那些奢侈品。

这就是我到目前为止......任何洞察力,所以永远是大大apperciated。

byte[] _argbs = null; 
static readonly Bitmap _bmUnderlay = Properties.Resources.bg; 
static Bitmap _bmpRender = new Bitmap(1024, 768, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
int bmpHeight = Properties.Resources.bg.Height; 
int bmpWidth = Properties.Resources.bg.Width; 
static BufferedGraphicsContext _bgc = new BufferedGraphicsContext(); 

internal unsafe void FillBackBuffer(Point cameraPos) 
{ 
     // lock up the parts of the original image to read (parts of it) 
     System.Drawing.Imaging.BitmapData bmd = _bmUnderlay.LockBits(
      new Rectangle(cameraPos.X, cameraPos.Y, 1024, 768), 
      System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
     // get the address of the first line. 
     IntPtr ptr = bmd.Scan0; 

     //if (_argbs == null || _argbs.Length != bmd.Stride * bmd.Height) 
     // _argbs = new byte[bmd.Stride * bmd.Height]; 
     if (_argbs == null || _argbs.Length != 1024 * 3 * 768) 
      _argbs = new byte[1024 * 3 * 768]; 

     // copy data out to a buffer 
     Marshal.Copy(ptr, _argbs, 0, 1024 * 3 * 768); 

     _bmUnderlay.UnlockBits(bmd); 

     // lock the new image to write to (all of it) 
     System.Drawing.Imaging.BitmapData bmdNew = _bmpRender.LockBits(
      new Rectangle(0, 0, 1024, 768), 
      System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
     // copy data to new bitmap 
     Marshal.Copy(_argbs, 0, bmdNew.Scan0, 1024 * 3 * 768); 
     _bmpRender.UnlockBits(bmdNew); 
} 

private unsafe void _btnGo_Click(object sender, EventArgs e) 
{ 
    // less than 2 ms to complete!!!!!!!! 
    FillBackBuffer(new Point()); 

    using (BufferedGraphics bg = _bgc.Allocate(CreateGraphics(), ClientRectangle)) 
    { 
     System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
     sw.Start(); 
     ///// 
     /// 
     // This method takes over 17 ms to complete 
     bg.Graphics.DrawImageUnscaled(_bmpRender, new Point()); 
     // 
     /// 
     ///// 
     sw.Start(); 
     this.Text = sw.Elapsed.TotalMilliseconds.ToString(); 

     bg.Render(); 
    } 
} 

编辑:

忘记提到我正在寻找一个低级别的替代Graphics.DrawImage(),preferrably写入图形表面内存,使用指针?再次感谢

+0

我编辑了代码缩进,并且在末尾似乎有一个跳动的大括号。如果这是我的结束问题,请回滚我的编辑 – puk 2012-03-24 00:55:00

+0

感谢您的帮助,我觉得括号是我搞砸了的一部分,恩,对不起:) – OverMars 2012-03-24 00:57:15

回答

3

注意位图的像素格式。在标准的32bpp视频硬件上,Format32bppPArgb比其他任何硬件渲染速度快十倍。因为像素不需要任何翻译。你现在使用的24bpp格式现在需要扩展到32bpp,并且不是免费的。不要跳过PArgb的P,并且不要忘记在代码中将alpha值设置为255。

使用BufferedGraphics是可疑的btw。您应该始终使用OnPaint方法中免费获得的那个。而且你可能根本就不需要一个,因为你这么快速地传球。这是一个自动的2x加速。

+0

这有助于超出我的预期,得益于 我使用bufferedGraphics因为在填充客户端窗口之后,我添加了其他几个位图层! :(C#是SOOO并不意味着这个... – OverMars 2012-03-24 16:26:55

+0

嗯,没有什么关系。你只是使用的语言不到理想的图形库。GDI +是非常兼容的,但如果你想PERF那么你需要一个用于管理视频内存的库,例如DirectX,SlimDX有一个托管包装器。 – 2012-03-24 16:53:54