3

I'm trying to paint images on a PictureBox from a camera that I insert with a WindowsFormsHost. The code is as simple as follows:

<Window x:Class="videoTEst.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="583" Width="1132"
    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
<StackPanel Background="LightBlue" Height="513" Width="1077">
    <StackPanel HorizontalAlignment="Center" Width="450" Orientation="Horizontal">
        <Button Name="ButtonOpen" Content="Load" Click="ButtonOpen_OnClick" />
        <Button Name="ButtonLoadImage" Content="Load image" Click="ButtonLoadImage_OnClick" />
        </StackPanel>
    <StackPanel Orientation="Horizontal">
        <WindowsFormsHost Name="WinFormsHost" Height="440" Width="690" HorizontalAlignment="Left">
                <wf:PictureBox x:Name="PictureBoxvideo" SizeMode="Normal" Paint="PictureBoxvideo_Paint"></wf:PictureBox>
        </WindowsFormsHost>
        <ListBox Name="ListBoxLog" />
    </StackPanel>
</StackPanel>

And I paint from the camera like this:

 private void asyncVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        Image temp = PictureBoxvideo.Image;
        Bitmap bitmap = eventArgs.Frame;
        PictureBoxvideo.Image = new Bitmap(bitmap);
        if (temp != null) temp.Dispose();
        bitmap.Dispose();
   }

This code works perfectly.

But when I change the <Window> tags to <UserControl> (as I want it to be embeded on my own UserControl), it doesn't paint!!

Why isn't it painting on a UserControl?

Why I'm not using Image from WPF? Image has a threading use really confusing, and whenever I try to paint on the Image, the Bitmap was disposed before.

Sonhja
  • 8,230
  • 20
  • 73
  • 131
  • 1
    There is nothing confusing about creating a WPF BitmapImage in another thread. Just call `Freeze` before using it in the UI thread. StackOverflow has a lot of answers that show how to do that, and of course also how to create a BitmapImage from a Bitmap. – Clemens Aug 08 '13 at 15:49
  • @Clemens I tried to assign the Bitmap to an Image, but then it says that the process is in another thread. How can I paint the BitmapImage if I can't return to the main UI? Could you provide a link to read about that? I didn't have knoweldege about what you say. – Sonhja Aug 08 '13 at 16:05

1 Answers1

4

Instead of a PictureBox in a WindowsFormsHost you could simply use a WPF Image control:

<StackPanel Orientation="Horizontal">
    <Image x:Name="image" Height="440" Width="690" HorizontalAlignment="Left"/>
    ...
</StackPanel>

You would now create a BitmapImage from the Bitmap object using code as shown in this answer or in this answer, with an additional call to Freeze that makes it accessible in the UI thread:

Bitmap bitmap = eventArgs.Frame; // your NewFrameEventArgs
BitmapImage bitmapImage = new BitmapImage();

using (var stream = new MemoryStream())
{
    bitmap.Save(stream, ImageFormat.Bmp);
    stream.Seek(0, SeekOrigin.Begin);

    bitmapImage.BeginInit();
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
    bitmapImage.StreamSource = stream;
    bitmapImage.EndInit();
}

bitmapImage.Freeze();

Finally you would update the Image control in the UI thread by calling its Dispatcher:

image.Dispatcher.Invoke((Action)(() => image.Source = bitmapImage));
Community
  • 1
  • 1
Clemens
  • 123,504
  • 12
  • 155
  • 268