5

1027 * 768ビットマップをクライアントウィンドウ(同じサイズ)にレンダリングする必要があり、このタスクを完了するのに10〜15ミリ秒以上ありません。bufferedGraphicsContectオブジェクトから割り当てられたbufferedGraphicsを使用していますが、それでも大きなパフォーマンスの問題に気づきます。

安全でないコードを使用してコピー操作を実行していますが、信じられないほどの結果が見つかりました。Graphics / BufferedGraphicsオブジェクトは、メモリ内にある種の描画面を持っている必要があることを私は知っています。マーシャルやその他の安全でない低レベルの方法を使用してこのサーフェスに書き込む方法について、誰かが私を正しい方向に向けることができるかどうか疑問に思いました。

古い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()の低レベルの代替手段を探していることを忘れてしまいました。できれば、ポインターを使用してGraphicsサーフェスメモリに書き込みますか?再度、感謝します

4

1 に答える 1

3

ビットマップのピクセルフォーマットに注意してください。標準の32bppビデオハードウェアでは、Format32bppPArgbは他のどのハードウェアよりも10倍高速にレンダリングします。ピクセルは変換を必要としないからです。現在使用している24bppフォーマットを32bppに拡張する必要がありますが、これは無料ではありません。PArgbのPをスキップしないでください。また、コードでアルファ値を255に設定することを忘れないでください。

BufferedGraphicsの使用は厄介です。OnPaintメソッドで無料で入手できるものを常に使用する必要があります。そして、これほど速くブリットしているので、おそらくまったく必要ありません。これは自動的に2倍のスピードアップです。

于 2012-03-24T10:32:51.617 に答える