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> <MediaTimelineSource="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.



April 6th, 2008 at 10:48 pm
Thomas,
Nice, very nice!
Cheers,
Karl
April 9th, 2008 at 10:38 pm
Hi Karl,
thanks.
Thomas
September 18th, 2008 at 3:12 pm
Hi in silverlight Process.Start(filename)
Can u please spacify in which library it is?
October 7th, 2008 at 12:29 pm
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.
November 19th, 2008 at 7:00 am
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.