抓取位图-图像(Winforms)并转换为WPF-Image失败

时间:2022-05-18 20:54:02

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();
    }