Запись в буферизованную графическую поверхность с помощью указателя - PullRequest
5 голосов
/ 24 марта 2012

Мне нужно отобразить растровое изображение 1027 * 768 в окно клиента (того же размера), и у меня не больше, чем 10-15 мс для выполнения этой задачи.Я использую bufferedGraphics , выделенный из объекта bufferedGraphicsContect , и все еще замечаю огромные проблемы с производительностью.

Я использую небезопасный код для выполнения моих операций копирования и нашел невероятные результаты .Я знаю, что объекты 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 (), предпочтительно для записи в память поверхности Graphics, используяуказатели?Еще раз спасибо

1 Ответ

3 голосов
/ 24 марта 2012

Обратите внимание на пиксельный формат растрового изображения.Format32bppPArgb на стандартном видеооборудовании 32 бит / с отрисовывает в десять раз быстрее, чем любой другой.Потому что пиксели не нуждаются в переводе.Формат 24bpp, который вы используете сейчас, должен быть расширен до 32bpp, и это не бесплатно.Не пропустите P of PArgb и не забудьте установить в своем коде значение альфа 255.

Использование BufferedGraphics, кстати, очень сложно.Вы всегда должны использовать тот, который вы получаете бесплатно в методе OnPaint.И вам, вероятно, он вообще не нужен, потому что вы так быстро блеете.Это автоматическое ускорение в 2 раза.

...