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 (17)

  • 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
  • URW Reply

    Great example, but I need to get an image from a video when the video is NOT playing. Is that possible and can you show me how to do that?

    June 6, 2017 at 6:11 pm
    • Thomas Claudius Huber Reply

      Hi URW,

      I haven’t tested that case to get an image without showing the video. I think somehow it should be possible, but currently I don’t have the (spare)time to look for a solution for that case.

      June 8, 2017 at 11:18 am
      • URW Reply

        Thanks for your reply Thomas. I found a way to do it, using ffmpeg but I am stilling hoping to find a way to get that picture within wpf, so we don;t have to install another executable and don’t run into licensing issues. If I find a way, would you like me to let you know?

        Loooking at your name, I believe you understand the following

        Schoenes Wochenende
        Tschuess

        Ute

        June 8, 2017 at 5:56 pm
  • Terence Reply

    Hi Thomas,

    Thanks for the example. I have a question: is it possible to take a snapshot of the video with the size being the video’s resolution? For example, if the video’s resolution is 1920×1080, I want to take the video snapshot at 1920×1080 resolution, NOT at the size of the mediaelement.

    I have tried passing 1920 and 1080 to “RenderTargetBitmap”, but it still gives me 300×200 snapshot with the rest area being white

    Thanks

    July 10, 2018 at 2:46 am
    • Thomas Claudius Huber Reply

      Hi Terence,

      yes, that should be possible. Did you get it working now?

      Cheers,
      Thomas

      January 21, 2019 at 5:19 pm
  • Ali Reply

    thanks :)

    August 1, 2018 at 2:15 pm
  • Zahk Reply

    Hi, i just bumped on this good solution but my problem is, the screenshot is not according to the original video size (width and height).

    Is there any way to fix this? Ive been fiddling around with some settings but still cant get it work.

    Thank you.

    July 13, 2020 at 3:45 am

Leave a Reply

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

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.