Home

How to use WPF to create a frame grabber

edited January 2015
I cannot use WPF features to show a webcam video source in the output.

I don't understand which is the problem, LP does not give more feedback about "warnings".

The script here.

Thank you.

Comments

  • This is a great example of when a debugger is invaluable.

    Your "NewFrame" event handler is throwing an exception, but because the source is an unmanaged callback, the exception goes nowhere and silently disappears.

    Do you have a premium license? If so, download the latest beta of LINQPad, which has as an integrated debugger:
    http://www.linqpad.net/beta.aspx

    Click the blue bug ("Break when exception is thrown") and run your script. A dialog will pop up right where the exception occurs.

    The cause of the error is using Application.Current which is null in LINQPad because there is no current WPF application. Instead, use Dispatcher.CurrentDispatcher - or better - the Dispatcher property of the image control itself.

    To make your script work, you must also clone the image that comes back, because the image is not immutable. Also, I notice that you're struggling with a ReadLine to keep the query alive while the message loop runs. The newest beta has a Util.ReadLineAsync method which makes life easier. Even better, there's also now a Cleanup event in the LINQPad.Util class:
    var captureDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
    var videoCapture = new VideoCaptureDevice(captureDevice[0].MonikerString);
    var image = new PictureBox().Dump();
    
    videoCapture.NewFrame += (s, e) =>
    {
       // The first frame may materialize before the WinForms message loop starts:
       if (!image.IsHandleCreated) return;
    
       // The frame is mutable, so we need to clone it before exiting the handler:
       var clone = (Bitmap) e.Frame.Clone();
       
       image.BeginInvoke (new Action (() => image.Image = clone));
    };
    
    videoCapture.Start();
    Util.Cleanup += (sender, args) => videoCapture.SignalToStop();
    This example uses Windows Forms. The WPF version is similar except for the conversion from Bitmap into an ImageSource:

    http://share.linqpad.net/7sua3s.linq

  • Joe, you are really great!

    Yes, I've the premium license and always I the latest beta using this script (that from some versions does not work) :smile:.

    How can I use the ReadLineAsync to stop the acquiring without close the script?

    I tried the Dispatcher.CurrentDispatcher but it does not work and I don't understand why, I use it in all WPF applications (wrapped by my package, of the old), insted control.Dispatcher is ok.

    Thank you!
  • To use Util.ReadLineAsync:
    await Util.ReadLineAsync();
    videoCapture.SignalToStop();
    Make sure your script is "C# Statements", or if it's "C# Program", make the main method signature "async Task Main()".

    Do the examples that I gave work for you? Tell me what happens when you run:
    http://share.linqpad.net/7sua3s.linq
  • Yes the example works and also the ReadLineAsync in my WPF script.

    I will publish the script under my LINQPad examples.
  • It should be useful to can execute some code for all uncatched exceptions, of external AppDomain also, in my case I must call the videoCapture.SignalToStop() otherwise the webcam will remain opened. Something like Util.Cleanup.

    P.S. have you any idea of why my LINQPad autoupdater cannot close the LP instance from an external on-fly application, at the beginning it worked.
Sign In or Register to comment.