Click here to Skip to main content
Licence 
First Posted 23 Feb 2005
Views 276,464
Bookmarked 105 times

Extracting still pictures from movie files, with C#

By | 23 Feb 2005 | Article
Sample application to extract still pictures from most movie file formats.

Sample Image

Introduction

Pressing the "Print Screen" key while playing a movie file in Windows Media Player will not allow you to save the current frame. The sample application will save frames to JPEG files. It can extract frames from most movie file formats including *.wm? (Windows Media Player), *.avi, *.mpeg, *.mov (QuickTime), and *.dat (DivX). Commercial and shareware applications that provide this functionality exist but the code that I will show will let you build your own application that fits your exact needs.

Background

Pressing the "Print Screen" key while playing a movie file in Windows Media Player will not allow you to save the current frame. So I started to look for a simple way to grab a frame from movie files playing in the most common media applications (e.g., Windows Media Player, QuickTime, or DivX Player). It turned out to be more complicated than I originally thought. Hence, I decided to write up a sample application and submit it to CodeProject since I have used their resources quite often; it was a way to thank the people behind this site.

Microsoft approach to this problem would be using DirectShow but there is no managed equivalent of it. By digging in the DirectX documentation, I discovered the MediaDet class that is used in some VB samples. It is not the ideal solution but it is good enough for many situations. By wrapping the qedit.dll from the DirectShow Developer Runtime (which is included in the Extras of the DirectX SDK) in a managed assembly, I could make calls to MediaDetClass::WriteBitmapBits method that saves a frame from a movie file to a bitmap file.

Using the code

As already mentioned, the workhorse of the application is the WriteBitmapBits method of the class MediaDetClass. In order to be able to access this method, you need to add a reference (from Visual Studio menu, Project/Add Reference if you are using Visual Studio, or use tlbimp from the .NET Framework tools) to the qedit.dll. In the code for this application, I have included the managed assembly (named interop.dexterlib.dll which was created using VS).

To declare an object of the MediaDetClass, you'll see code like:

          MediaDetClass md = new MediaDetClass();
          md.Filename = "sample.mov";      
          md.CurrentStream = 0;
          string fBitmapName = "sample" + ".bmp" ;
          md.WriteBitmapBits( 0, 320, 240, fBitmapName );

After having called WriteBitmapBits, the MediaDetClass object is, as the DirectShow documentation says, in bitmap grab mode. The important thing to know about this is that you need to create a new MediaDetClass instance anytime you need to load a new movie (it is a little as if the properties of this class are "read only").

I have set the property CurrentStream to 0 and it was working with all the samples I have tried. Moreover, it seems that you can only write to a bitmap file. So in order to save disk space, I have added code to convert the bitmap file to a JPEG one. You have to remember that, even with our 100 Gig hard disks, you can chew up the gigabytes pretty quickly if you want to save a frame every 0.1 second on a 30 minutes movie.

Points of Interest

The "Save" button saves the current frame to a JPEG file in the "tmp" subdirectory. The "Scan" button loops through the whole movie and saves a frame every second (or 0.1 second).

The MediaDetClass as imported with Visual Studio is not a Windows control, its base class is System.Object, and it seems that after calling the method WriteBitmapBits, a handle to the bitmap file just created stays open. Therefore, the application, sometimes, complains that a file is already being used. I have just increased a variable counter to avoid most of these situations; an alternative solution would have been to wrap the MediaDetClass a second time in a more sophisticated implementation.

As mentioned, this is not an ideal solution. DirectShow is not going to appear in a managed version (as opposed to the rest of the DirectX API). I imagine it is for performance reasons. But as this application shows, an interop version will do the job; as they say "It Just Works!", which is fine for many situations.

I have included a file ("build.cmd" ) with the command line needed to compile the application in a shell window where the C# compiler must be found on the path.

Limitations and known issues

The application extracts a frame every second, by default. Under the Options menu, you can choose to extract a frame every one tenth of a second. This is only taken in consideration when you press the "Scan" button.

The application only saves a bitmap with the resolution 320 x 240. And they are saved in the "tmp" subdirectory (that will be created when you run the application).

The application is meant to extract pictures from movie files and is a poor application for viewing movies. The creation of new instances of the MediaDetClass type makes this restriction unavoidable.

I have created a thread to be able to keep track of the progress so far (which is displayed on a static label) when scanning a whole movie. The thread only updates the label.

The length of the movie is immediately overwritten when opening a second movie with the current position.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

daniel049



United States United States

Member

You can read my blog entries at:
http://wwww.informikon.com/blog/

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralRe: Label On This Screen Pinmemberdaniel0497:06 25 Sep '07  
GeneralRe: Label On This Screen Pinmemberkarl alexander8:43 26 Sep '07  
GeneralGreat work. Useful for AI research. PinmemberJim Carnicelli8:46 20 Sep '07  
GeneralRe: Great work. Useful for AI research. Pinmemberdaniel0496:14 22 Sep '07  
GeneralRe: Great work. Useful for AI research. Pinmembercslxxwilliam22:49 23 Feb '10  
GeneralExcellent work PinmvpNishant Sivakumar15:28 27 Aug '07  
General"Logon failure: unknown user name or bad password" PinmemberMIke Gorgone4:00 14 Jun '07  
Hi All,
 
I'm currently trying to grab a frame from a video stream and I'm receiving the following two erros when I try to set the Det.Filename property:
 
1) When trying to access 123.wmv which is located on a network drive
 
"Logon failure: unknown user name or bad password"
 
2) When I tried to access the file after copying it to the root of my C: drive
 
Message: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
 
Source: DexterLib
 
StackTrace:
at DexterLib.MediaDetClass.set_Filename(String pVal)
at VideoProcess.PictureU.clsVideo.CreateVideoThumbnail(String ThumbSavePath, String VideoSrcPath, String sBatch, String sPhotoSet, Int32 iThumbStartSec) in D:\Projects\VS 2005 Apps\VideoProcess\VideoProcess\clsVideoProcess.vb:line 27
 

Not really sure what the heck is going on if anyone has any ideas I'd greatly appreciate it.
 
The entire procedure mimics the code segment here:
 
http://doc.51windows.net/Directx9_SDK/?url=/Directx9_SDK/htm/filenamepropertymediadetobject.htm
 
Thanks in advance.
 
Michael Gorgone
Senior Software Engineer
PictureU

GeneralQUICK UPDATE PinmemberMIke Gorgone7:09 14 Jun '07  
GeneralRe: "Logon failure: unknown user name or bad password" PinmemberMember 366472117:38 12 May '10  
QuestionCapture a Single Frame and search the same one from a *.mpg? Pinmember999ny99913:39 28 May '07  
GeneralException from HRESULT: 0x80040217 PinmemberKhunglongbeo21:10 20 May '07  
GeneralRe: Exception from HRESULT: 0x80040217 Pinmemberdaniel0493:21 21 May '07  
GeneralRe: Exception from HRESULT: 0x80040217 PinmemberKhunglongbeo19:06 21 May '07  
GeneralRe: Exception from HRESULT: 0x80040217 PinmemberKhunglongbeo21:26 21 May '07  
GeneralRe: Exception from HRESULT: 0x80040217 Pinmemberdaniel0498:37 24 May '07  
GeneralRe: Exception from HRESULT: 0x80040217 PinmemberRobyNova3:50 19 Dec '07  
GeneralExtracting still pictures from movie files Pinmembernir golan3:44 19 Apr '07  
Generalvideo compression PinmemberMember #382314319:59 21 Mar '07  
GeneralRe: video compression Pinmemberdaniel0493:34 29 Mar '07  
QuestionGetting the number of frames in the video Pinmembermary ann1:15 19 Mar '07  
AnswerRe: Getting the number of frames in the video Pinmemberdaniel04913:43 19 Mar '07  
QuestionHow to make it work if I am using 64bit server? Pinmembernizanne22:43 16 Feb '07  
AnswerRe: How to make it work if I am using 64bit server? Pinmemberdaniel0495:36 18 Feb '07  
GeneralSave to MemoryStream PinmemberC470212:48 17 Jan '07  
GeneralRe: Save to MemoryStream Pinmemberdaniel04912:55 18 Jan '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120529.1 | Last Updated 24 Feb 2005
Article Copyright 2005 by daniel049
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid