Export every frame as image from a Movie-File (QuickTime-API)

后端 未结 4 553
隐瞒了意图╮
隐瞒了意图╮ 2021-01-07 12:10

I want to open an existing Movie-File and export every frame of this file to an image like JPEG or TIFF. I got so far until now:

int main(int argc, char* a         


        
相关标签:
4条回答
  • 2021-01-07 12:50

    If you are working on OS X only I would stick with the QTKit APIs because they are much higher level and generally easier to work with.

    The general gist of what you want to do is:

    1. Step Through each frame in a movie
    2. Get a image representation for the current frame
    3. Save the current frame's image to a file on disk

    To step through the frames in a QuickTime movie, you can use the QTMovie class in QTKit to do this as follows:

    - (void)dumpFramesWithMovie:(QTMovie*)movie toFolder:(NSString*)folderPath
    {
        [movie setIdling:NO]; // Don't idle the movie
    
        [movie gotoEnd];
        QTTime endTime = [movie currentTime];
    
        [movie gotoBeginning];
    
        // Number of frames counted so far
        unsigned long numFrames = 0;
    
        // Turn off the Movie's looping so we are quaranteed to stop
        [movie setAttribute:[NSNumber numberWithBool:NO] forKey:QTMovieLoopsAttribute];
    
        // Construct a Dictionary of to use when reading frames from a movie
        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
        [attributes setObject:QTMovieFrameImageTypeNSImage forKey:QTMovieFrameImageType];    
        while (true)
        {
            QTTime curTime = [movie currentTime];
            if (QTTimeCompare(curTime, endTime) == NSOrderedSame)
            {
                // Reached end of file
                break;
            }
    
            // Get the Current Frame as an NSImage
            NSImage* image = [movie frameImageAtTime:curTime 
                                      withAttributes:attributes error:nil];
    
            // Get the bitmap representation of this image
            // NOTE: This code assumes the first image representation is a NSBitmapImageRep, which is true
            // by default in OS X 10.5 and later.  
            // Production code should do error checking here.
            NSBitmapImageRep *bitmap = [[image representations] objectAtIndex: 0];
    
            // Construct a filename based upon the folder path and number of frames read so far
            NSString* fileName = [NSString stringWithFormat:@"%@/frame%d.png", folderPath, numFrames];
    
            // Get an PNG representation of this file
            NSData *data = [bitmap representationUsingType: NSPNGFileType
                                                properties: nil];
    
            // Write to disk
            [data writeToFile: fileName
                   atomically: NO];
    
            // Step to the next Frame
            [movie stepForward];
            numFrames++;
        }
    
        [movie gotoBeginning];
    }
    @end
    

    This code compiles but has not been fully tested.

    One caveat with this approach is that MPEG-1 files will not decode properly on OS X 10.5 and earlier. This has been fixed as of 10.6 as far as I know. Also, if are writing a Windows application, you'll need to use the lower lever Quicktime-C APIs.

    Be sure to check the following reference pages while working on this:

    • QTKit Application Programming Guide
    • QTKit Frequently Asked Questions
    • QTMovie Class Reference
    • Quickies for NSImage
    • NSBitmapImageRep Reference
    • NSImage Reference
    0 讨论(0)
  • 2021-01-07 12:51

    These command line OSX utilities are really good at extracting the contents of a Quicktime movie without having to buy QTPro:

    qt_tools

    0 讨论(0)
  • 2021-01-07 12:51

    I usually just dump the decoded frames into a binary one after another and then use some YUV-Viewer to see if they look Ok. For that you have to know the exact color format and resolution of the decoded frames. If you have RGB, there are certainly also viewers for that.

    UPDATE:

    Link doesn't seem to work. You will have to google for a YUV-Viewer. Alternatively, you can buy one from Elecard.

    0 讨论(0)
  • 2021-01-07 12:57

    As a beginning, this article on Movie exporters should pretty much get you started:

    http://www.mactech.com/articles/mactech/Vol.16/16.05/May00QTToolkit/index.html

    Even though MacTech is a Mac resource, all described API functions should be available in the QuickTime for Windows SDK as well.

    I will slap some sample code together myself as a reference here as soon as I find the time.

    Edit

    See this book excerpt for additional info:

    QuickTime Toolkit - Basic Movie Playback and Media Types @ Google Books

    Edit 2 - The High-Level Approach: Movie Exporters

    If all you need to accomplish is to extract all video frames from a QuickTime Movie and convert them to another format supported by the QuickTime API you won't have to take any low-level actions whatsoever if using a Movie Exporter.

    The below sample code allows to extract and convert all video frames from a QuickTime Movie to, f.e., a bunch of JPEG files using a programmatically invoked Movie Export Dialog.

    Just select Movie to Image Sequence in the Export combo box of the dialog and select your desired image format by hitting Options.

    Note 1: If you need to do this non-interactively, just let me know.

    Note 2: error handling has been omitted for clarity

    #include "Movies.h"
    #include "QTML.h"
    #pragma comment (lib, "QTMLClient.lib")
    

    ...

    int  flags                  = createMovieFileDeleteCurFile 
        | showUserSettingsDialog 
        | movieToFileOnlyExport;
    ItemCount  movie_prop_count = 0;
    CFStringRef  cfpath         = 0;
    Boolean  bool_true          = true; 
    QTNewMoviePropertyElement  movie_props[ 2 ];
    Movie  movie;
    
    // initialize QuickTime API
    InitializeQTML( 0 );
    EnterMovies();
    
    // set up Core Foundation string for source path (argv[ 1 ]) contains the full path to the MOV file to convert
    cfpath = CFStringCreateWithCString( 0, argv[ 1 ], kCFStringEncodingASCII );
    movie_props[movie_prop_count].propClass        = kQTPropertyClass_DataLocation;
    movie_props[movie_prop_count].propID           = kQTDataLocationPropertyID_CFStringNativePath;
    movie_props[movie_prop_count].propValueSize    = sizeof(cfpath);
    movie_props[movie_prop_count].propValueAddress = (void*)&cfpath;            
    movie_props[movie_prop_count].propStatus       = 0;
    ++movie_prop_count;
    
    // make Movie active
    movie_props[movie_prop_count].propClass        = kQTPropertyClass_NewMovieProperty;
    movie_props[movie_prop_count].propID           = kQTNewMoviePropertyID_Active;
    movie_props[movie_prop_count].propValueSize    = sizeof(bool_true);
    movie_props[movie_prop_count].propValueAddress = &bool_true;
    movie_props[movie_prop_count].propStatus       = 0;
    ++movie_prop_count;
    
    // aquire Movie for our Movie file
    NewMovieFromProperties( movie_prop_count, movie_props, 0, 0, &movie );
    
    // invoke conversion dialog
    ConvertMovieToFile( movie, 0, 0, 0, 'TVOD', 0, 0, flags, 0 );
    
    // clean up
    DisposeMovie( movie );
    CFRelease( cfpath );
    
    ExitMovies();
    TerminateQTML();
    

    ...

    0 讨论(0)
提交回复
热议问题