Take Snapshots of Videos with WPF

With WPF’s Imaging-Classes you can take snapshots of any Visual. The snapshot can be saved in any common Image-Format, like e.g. JPG. Let’s take a look at a pretty short example, that shows how easy this can be done. The example takes snapshots of a Video.

The following Window contains a MediaElement and a Button. The MediaElement plays the Video thomasOnBoard.wmv. The Button defines an Eventhandler for the Click-Event. It takes a snapshot of the video, when you click it.

<Window x:Class="SnapShots.Window1"
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/...
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"

 ResizeMode="NoResize">
  <StackPanel>
   <MediaElement x:Name="media" Height="200" Stretch="Fill">
      <MediaElement.Triggers>
       <EventTrigger RoutedEvent="MediaElement.Loaded">
        <BeginStoryboard>
         <Storyboard>
          <MediaTimeline
Source="thomasOnBoard.wmv"
           RepeatBehavior="Forever"/>
         </Storyboard>
        </BeginStoryboard>
       </EventTrigger>
      </MediaElement.Triggers>
     </MediaElement>
     <Button Click="Button_Click" Content="Snapshot"/>
  </StackPanel>
</Window>

Let’s look at the Eventhandler of the Button. An instance of the RenderTargetBitmap-class is created with some parameters about image-size, dots per inch (dpi) and Pixelformat. The Render-Method gets the MediaElement as a parameter, so MediaElements visual appearance is stored in the RenderTargetBitmap in memory. With a JpegBitmapEncoder and a FileStream the Image is written as a JPG to disk. That’s it.

void Button_Click(object sender, RoutedEventArgs e)
{
  Size dpi = new Size(96,96);
  RenderTargetBitmap bmp = 
    new RenderTargetBitmap(300, 200, 
      dpi.Width, dpi.Height, PixelFormats.Pbgra32);
  bmp.Render(media);

  JpegBitmapEncoder encoder = new JpegBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bmp));

  string filename = Guid.NewGuid().ToString()+".jpg";
  FileStream fs = new FileStream(filename,FileMode.Create);
  encoder.Save(fs);
  fs.Close();

  Process.Start(filename);
}

Instead of taking the picture in the Button_Click eventhandler, you could create a Timer and take an Image every 0.1s. That allows you to extract an image-sequence of your videos. As it works for any Visual, and everything that’s on the screen in a WPF-Application is a visual, there are many things you can do with it. You could create a snapshot of an Image drawn to an inkCanvas, upload it to a webserver to display it on a webpage etc.

Share this post

Comments (8)

  • Karl Shifflett Reply

    Thomas,

    Nice, very nice!

    Cheers,

    Karl

    April 6, 2008 at 10:48 pm
  • hubethom Reply

    Hi Karl,

    thanks. :-)

    Thomas

    April 9, 2008 at 10:38 pm
  • jitendra Reply

    Hi in silverlight Process.Start(filename)
    Can u please spacify in which library it is?

    September 18, 2008 at 3:12 pm
  • Pradyut Reply

    Hi,
    Its really nice n smart work,else I did it using Directshow by writting long long code.
    By inspiring your work,
    Do you have any idea about how we can get all frames of given video files using your approch ?

    I am looking for some replacement of ISamplegrabber of Directshow, in which I can get all frames one by one from file and I do have event after each frame arrive so I can put my processing logic in between.

    Can we do similer in WPF ?

    Any kind of hint, link..will be gr8 help for me.

    thnx.

    October 7, 2008 at 12:29 pm
  • Nada Reply

    Hello,

    Thanks for this post, it’s really great and useful.
    I have a question, can I do this streaming (extracting these snapshots) while I’m recording the video ? I mean I need it at run time .. recording a video and every frame recorded is converted to still image to process on it without the need to wait till the end of the rec ordering ?

    Thanks in advance.

    November 19, 2008 at 7:00 am
  • sridhar Reply

    nice but pls tell me how to decompress an image in wpf(.bmp) or(.jpg)

    November 1, 2012 at 6:44 am
  • SRR Reply

    nicely explained. But is it possible to make the snapshot’s width and height similar to it’s natural video width and height (which we get from mediaelement)?

    January 16, 2014 at 6:07 am

Leave a Reply

Your email address will not be published. Required fields are marked *

*