WPF 中的大图像更新被延迟以进行实时监控
Large image update in WPF is delayed for real time monitoring
我从 USB 获取图像序列,抓取每张图像后,我将抓取的结果转换为 System.Drawing.Bitmap,然后将其转换为 System.Windows.Mesia.Imging.BitmapImage,以便能够将其分配给 Imagesource,最后在dispatcher线程中更新UI,这个过程比较耗时,并没有上线,相机公司(Basler)的示例代码使用了C#,直接将System.Drawing.Bitmap赋值给图片框就可以显示了即时取景,毫不拖延。
处理它的最佳解决方案是什么?值得一提的是,2048*2000像素大小的帧率接近50fps
PixelDataConverter converter = new PixelDataConverter();
Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
converter.OutputPixelFormat = PixelType.BGRA8packed;
IntPtr ptrBmp = bmpData.Scan0;
converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
bitmap.UnlockBits(bmpData);
BitmapImage bitmapimage = new BitmapImage();
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
bitmapimage.Freeze();
}
Dispatcher.Invoke(new Action(() =>
{
imgMain.Source = bitmapimage;
}));
这是公司的 c# 示例代码:
Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
// Lock the bits of the bitmap.
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
// Place the pointer to the buffer of the bitmap.
converter.OutputPixelFormat = PixelType.BGRA8packed;
IntPtr ptrBmp = bmpData.Scan0;
converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult); //Exception handling TODO
bitmap.UnlockBits(bmpData);
// Assign a temporary variable to dispose the bitmap after assigning the new bitmap to the display control.
Bitmap bitmapOld = pictureBox.Image as Bitmap;
// Provide the display control with the new bitmap. This action automatically updates the display.
pictureBox.Image = bitmap;
if (bitmapOld != null)
{
// Dispose the bitmap.
bitmapOld.Dispose();
}
}
enter code here
使用 Dispatcher.BeginInvoke 而不是 Dispatcher.Invoke(...
来设置图像异步。
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
imgMain.Source = bitmapimage;
}));
我从 USB 获取图像序列,抓取每张图像后,我将抓取的结果转换为 System.Drawing.Bitmap,然后将其转换为 System.Windows.Mesia.Imging.BitmapImage,以便能够将其分配给 Imagesource,最后在dispatcher线程中更新UI,这个过程比较耗时,并没有上线,相机公司(Basler)的示例代码使用了C#,直接将System.Drawing.Bitmap赋值给图片框就可以显示了即时取景,毫不拖延。 处理它的最佳解决方案是什么?值得一提的是,2048*2000像素大小的帧率接近50fps
PixelDataConverter converter = new PixelDataConverter();
Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
converter.OutputPixelFormat = PixelType.BGRA8packed;
IntPtr ptrBmp = bmpData.Scan0;
converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
bitmap.UnlockBits(bmpData);
BitmapImage bitmapimage = new BitmapImage();
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
bitmapimage.Freeze();
}
Dispatcher.Invoke(new Action(() =>
{
imgMain.Source = bitmapimage;
}));
这是公司的 c# 示例代码:
Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
// Lock the bits of the bitmap.
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
// Place the pointer to the buffer of the bitmap.
converter.OutputPixelFormat = PixelType.BGRA8packed;
IntPtr ptrBmp = bmpData.Scan0;
converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult); //Exception handling TODO
bitmap.UnlockBits(bmpData);
// Assign a temporary variable to dispose the bitmap after assigning the new bitmap to the display control.
Bitmap bitmapOld = pictureBox.Image as Bitmap;
// Provide the display control with the new bitmap. This action automatically updates the display.
pictureBox.Image = bitmap;
if (bitmapOld != null)
{
// Dispose the bitmap.
bitmapOld.Dispose();
}
}
enter code here
使用 Dispatcher.BeginInvoke 而不是 Dispatcher.Invoke(...
来设置图像异步。
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
imgMain.Source = bitmapimage;
}));