WPF: как эффективно обновлять изображение 30 раз в секунду - PullRequest
13 голосов
/ 16 марта 2010

Я пишу приложение WPF, которое использует компонент, и этот компонент возвращает указатель (IntPtr) на пиксели растрового изображения (высота шага *). Я заранее знаю, что растровое изображение - это 24-битный RGB, его ширина и высота.

Обновление элемента управления изображением с помощью этих растровых изображений создает видео для пользователя, но я не уверен, каков наиболее эффективный способ сделать это, большую часть времени загрузка ЦП достигает 75% + и изменение памяти с 40 МБ до 500 МБ, и я думаю, что GC начинает работать, а затем снова падает до 40 мм. Приложение начинает не реагировать.

Что мне делать?

спасибо!

Ответы [ 2 ]

16 голосов
/ 16 марта 2010

Скорее всего, вы выделяете новые растровые изображения, которые не являются одноразовыми. Вы должны выделить один WriteableBitmap и обновить его. В связанной документации описан процесс блокировки, обновления и разблокировки WriteableBitmap

В программном обеспечении, в котором я работаю с использованием живых ультразвуковых изображений в WPF, я получаю растровое изображение Windows Forms, которое копирую в WriteableBitmap напрямую, используя собственный метод CopyMemory. Даже с этой более сложной работой, процессор не сильно напрягается, и использование памяти никогда не меняется, пока я правильно распоряжаюсь тем, что могу. Надеюсь, этот пример поможет вам:

// DLL returns images as a WinForms Bitmap
Bitmap bmp = myClass.getWinFormsBitmap();

// In my situation, the images are always 640 x 480.
BitmapData data = bmp.LockBits(new Rectangle(0, 0, 640, 480), ImageLockMode.ReadOnly,  System.Drawing.Imaging.PixelFormat.Format32bppArgb);
this.writeableBitmap.Lock();

// Copy the bitmap's data directly to the on-screen buffers
NativeMethods.CopyMemory(this.writeableBitmap.BackBuffer, data.Scan0, ImageBufferSize);

// Moves the back buffer to the front.
this.writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, 640, 480));
this.writeableBitmap.Unlock();

bmp.UnlockBits(data);

// Free up the memory of the WinForms bitmap
bmp.Dispose();

Где CopyMemory определяется как:

[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
4 голосов
/ 23 апреля 2014

Используя вспомогательный метод, называемый WritePixels на WriteableBitmap, мы можем написать его немного короче, например:

// DLL returns images as a WinForms Bitmap
// It's disposed even if an exception is thrown
using (Bitmap bmp = myClass.getWinFormsBitmap())
{
    // In my situation, the images are always 640 x 480.
    BitmapData data = bmp.LockBits(new Rectangle(0, 0, 640, 480), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    writeableBitmap.WritePixels(new Int32Rect(0, 0, 640, 480), data.Scan0, ImageBufferSize, data.Stride);
    bmp.UnlockBits(data);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...