У меня есть метод, который обновляет содержимое WriteableBitmap (FrameDataNew), которое является свойством в моей viewmodel (VM):
public WriteableBitmap FrameDataNew
{
get { return frameDataNew; }
set
{
frameDataNew = value;
OnProptertyChanged("FrameDataNew");
}
}
private WriteableBitmap frameDataNew = null;
Когда я получаю новое растровое изображение из класса gstreamer, который я написалЯ обновляю FrameDataNew, чтобы показать последний кадр на экране.окно представляет собой простой элемент управления Image, источник которого привязан к FrameDataNew.
Следующий код прекрасно работает для этого в моем обработчике событий:
/// <summary>
/// BitmapCaptured event handler for when a new video frame is received from the IP source
/// </summary>
/// <param name="sender">The originating source of the event</param>
/// <param name="NewBitmap">The new frame in Bitmap form</param>
private void PipeLine_BitmapCaptured(object sender, Bitmap NewBitmap)
{
// render to the screen
Dispatcher.Invoke(() =>
{
// check the existence of the WriteableBitmap and also the dimensions, create a new one if required
if ((VM.FrameDataNew == null) || (VM.FrameDataNew.Width != NewBitmap.Width) || (VM.FrameDataNew.Height != NewBitmap.Height))
VM.FrameDataNew = new WriteableBitmap(NewBitmap.Width, NewBitmap.Height, NewBitmap.HorizontalResolution, NewBitmap.VerticalResolution, PixelFormats.Bgr24, null);
// lock the bitmap data so we can use it
BitmapData data = NewBitmap.LockBits(new Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// lock the backbuffer of the WritebaleBitmap so we can modify it
VM.FrameDataNew.Lock();
// Copy the bitmap's data directly to the on-screen buffers
CopyMemory(VM.FrameDataNew.BackBuffer, data.Scan0, (data.Stride * data.Height));
// Moves the back buffer to the front.
VM.FrameDataNew.AddDirtyRect(new Int32Rect(0, 0, data.Width, data.Height));
// unlock the back buffer again
VM.FrameDataNew.Unlock();
//
//NewBitmap.UnlockBits(data);
});
}
[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
Теперь я хочу обновить свою программудля обработки нескольких конвейеров и WriteableBitmaps, чтобы я мог показать несколько видео каналов.Первым делом я создал класс статических утилит, чтобы я мог передать новое растровое изображение (NewBitmap) и WriteableBitmap (VM.FrameDataNew), которые я хочу обновить.Затем я вызывал его по мере необходимости, когда приходит новый кадр:
Класс утилит (только код, связанный с моим вопросом):
public static class Utils
{
/// <summary>
/// Inject the source Bitmap into the Destination WriteableBitmap
/// </summary>
/// <param name="Src">The source Bitmap</param>
/// <param name="Dest">The destination WriteableBitmap</param>
public static void InjectBitmap(Bitmap Src, WriteableBitmap Dest)
{
if ((Dest == null) || (Dest.Width != Src.Width) || (Dest.Height != Src.Height))
Dest = new WriteableBitmap(Src.Width, Src.Height, Src.HorizontalResolution, Src.VerticalResolution, PixelFormats.Bgr24, null);
BitmapData data = Src.LockBits(new Rectangle(0, 0, Src.Width, Src.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Dest.Lock();
// Copy the bitmap's data directly to the on-screen buffers
CopyMemory(Dest.BackBuffer, data.Scan0, (data.Stride * data.Height));
// Moves the back buffer to the front.
Dest.AddDirtyRect(new Int32Rect(0, 0, data.Width, data.Height));
Dest.Unlock();
//
Src.UnlockBits(data);
}
[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
}
... и способ, которым я его называю:
/// <summary>
/// BitmapCaptured event handler for when a new video frame is received from the IP source
/// </summary>
/// <param name="sender">The originating source of the event</param>
/// <param name="NewBitmap">The new frame in Bitmap form</param>
private void PipeLine_BitmapCaptured(object sender, Bitmap NewBitmap)
{
// render to the screen
Dispatcher.Invoke(() =>
{
Utils.InjectBitmap(NewBitmap, VM.FrameDataNew);
});
}
Изображение больше не появляется на экране.Пошаговое выполнение кода выглядит каждый раз, когда InjectBitmap () называется целевым объектом. WriteableBitmap имеет значение null?Код создает новый в первом операторе if, но VM.FrameDataNew остается нулевым?
Я определенно нахожусь на грани своего опыта с этим, поэтому любая помощь будет высоко ценится.
Редактировать: Цель состоит в том, чтобы иметь наблюдаемую коллекцию WriteableBitmaps, чтобы я мог обрабатывать несколькоэто эффективно.