I grab an image from a external camera. The winforms application works so far. Now I need to transfer it to WPF. Therefore I converted the bitmap-image to WPF like this:
我从外部摄像机获取图像。winforms应用程序到目前为止运行良好。现在我需要把它转移到WPF上。因此我将位图-图像转换为WPF:
GrabHandler frameCallbackDelegate;
void frameCallBack(IntPtr lpUserData, ref VCECLB_FrameInfoEx frameInfo)
{
if (frameInfo.dma_status != 0) return;
// fill image
Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
BitmapData bmdata = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
UInt32 outputBitDepth;
IntPtr stride = new IntPtr(bmdata.Stride);
VCECLB_Error err = NativeFunctions.VCECLB_UnpackRawPixelsEx(ref pRawPixelInfo, frameInfo.lpRawBuffer, bmdata.Scan0, ref stride, VCECLB_Output_Format.VCECLB_EX_FMT_TopDown | VCECLB_Output_Format.VCECLB_EX_FMT_3Channel, out outputBitDepth);
image.UnlockBits(bmdata);
Dispatcher.Invoke(new Action(() =>
{
// Convert bitmap to WPF-Image
var bmp = new Bitmap(image);
var hBitmap = bmp.GetHbitmap();
ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
image_LowLight.Source = wpfBitmap;
DeleteObject(hBitmap);
image.Dispose();
}));
GC.Collect();
}
private void StartGrab(object sender, RoutedEventArgs e)
{
start_button.IsEnabled = true;
stop_button.IsEnabled = false;
frameCallbackDelegate = new GrabHandler(frameCallBack);
m_ImageAquisition.StartGrab(frameCallbackDelegate);
}
When I enter for the first time the frameCallBack from the StartGrab, the image.Width and image.Height have a valid value (not 0) and it seems correct. When the frameCallBack is entered for the second time all image-data (width and height) are 0 and therefore rect gives an error.
当我第一次从StartGrab中输入帧回图像时。宽度和形象。高度有一个有效值(不是0),看起来是正确的。当第二次输入frameCallBack时,所有的图像数据(宽度和高度)都为0,因此rect会产生错误。
Is there something wrong in the way I am using the Dispatcher.Invoke to get a valid bitmap-image?
我使用调度员的方式有问题吗?调用以获取有效的位图映像?
Thanks!
谢谢!
1 个解决方案
#1
0
Avoid using volatile data in an Action() which gets executed some time later by the Dispatcher.
避免在操作()中使用volatile数据,该操作将在稍后由分派器执行。
Refactor your code like this:
重构代码如下:
GrabHandler frameCallbackDelegate;
void frameCallBack(IntPtr lpUserData, ref VCECLB_FrameInfoEx frameInfo)
{
if (frameInfo.dma_status != 0) return;
// fill image
Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
BitmapData bmdata = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
UInt32 outputBitDepth;
IntPtr stride = new IntPtr(bmdata.Stride);
VCECLB_Error err = NativeFunctions.VCECLB_UnpackRawPixelsEx(ref pRawPixelInfo, frameInfo.lpRawBuffer, bmdata.Scan0, ref stride, VCECLB_Output_Format.VCECLB_EX_FMT_TopDown | VCECLB_Output_Format.VCECLB_EX_FMT_3Channel, out outputBitDepth);
image.UnlockBits(bmdata);
// Convert bitmap to WPF-Image
var bmp = new Bitmap(image);
var hBitmap = bmp.GetHbitmap();
ImageSource wpfBitmap =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
image.Dispose();
Dispatcher.Invoke(new Action(() =>
{
image_LowLight.Source = wpfBitmap;
}));
GC.Collect();
}
#1
0
Avoid using volatile data in an Action() which gets executed some time later by the Dispatcher.
避免在操作()中使用volatile数据,该操作将在稍后由分派器执行。
Refactor your code like this:
重构代码如下:
GrabHandler frameCallbackDelegate;
void frameCallBack(IntPtr lpUserData, ref VCECLB_FrameInfoEx frameInfo)
{
if (frameInfo.dma_status != 0) return;
// fill image
Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
BitmapData bmdata = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
UInt32 outputBitDepth;
IntPtr stride = new IntPtr(bmdata.Stride);
VCECLB_Error err = NativeFunctions.VCECLB_UnpackRawPixelsEx(ref pRawPixelInfo, frameInfo.lpRawBuffer, bmdata.Scan0, ref stride, VCECLB_Output_Format.VCECLB_EX_FMT_TopDown | VCECLB_Output_Format.VCECLB_EX_FMT_3Channel, out outputBitDepth);
image.UnlockBits(bmdata);
// Convert bitmap to WPF-Image
var bmp = new Bitmap(image);
var hBitmap = bmp.GetHbitmap();
ImageSource wpfBitmap =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
image.Dispose();
Dispatcher.Invoke(new Action(() =>
{
image_LowLight.Source = wpfBitmap;
}));
GC.Collect();
}