我需要渲染一个1027*768位图到客户端窗口(大小相同),我没有超过10-15毫秒来完成这个任务。我正在使用从BufferedGraphicsContect对象分配的BufferedGraphics,但仍然注意到巨大的性能问题。
我正在使用不安全的代码来执行复制操作,结果令人难以置信。我知道graphics/bufferedgraphics对象在内存中应该有某种绘图表面。我想知道是否有人能给我指出正确的方向,告诉我如何使用marshal或其他不安全的低级方法来写这个表面。
我正在移植一个旧的C图形应用程序。我知道c不是为繁重的图形设计的,而且有比gdi+更好的工具可用,不幸的是我没有这些奢侈品。
这就是我到目前为止想出来的…任何这样的洞见都会被极大地打动。

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()的低级替代品,更喜欢使用指针写入图形表面内存?再次感谢

最佳答案

注意位图的像素格式。在标准的32bpp视频硬件上,format32bpppargb的渲染速度是其他任何硬件的10倍。因为像素不需要任何转换。你现在使用的24bpp格式需要扩展到32bpp,这不是免费的。不要跳过pargb的p,不要忘记在代码中将alpha值设置为255。
使用bufferedgraphics是可疑的顺便说一句。你应该总是使用onpaint方法中免费得到的那个。而且你可能根本不需要一个,因为你这么快就闪现了。这是2倍的自动加速。

09-10 12:39