【问题标题】:Export every frame as image from a Movie-File (QuickTime-API)从电影文件(QuickTime-API)中将每一帧导出为图像
【发布时间】:2010-12-23 23:37:04
【问题描述】:

我想打开一个现有的电影文件并将该文件的每一帧导出为 JPEG 或 TIFF 等图像。我到现在为止:

int main(int argc, char* argv[]) {
    char filename[255]; // Filename to ping.
    OSErr e;            // Error return.
    FSSpec filespec;    // QT file specification
    short filemovie;    // QT movie handle.
    Movie movie;        // QT movie "object".

    InitializeQTML(0);
    EnterMovies();
    // Because of QT's Mac origin, must convert C-string filename 
    // to Pascal counted string, then use that to make a filespec.
    c2pstr(filename); 
    FSMakeFSSpec(0, 0L, (ConstStr255Param)filename, &filespec);

    OpenMovieFile(&filespec, &filemovie, fsRdPerm);
    NewMovieFromFile(&movie, filemovie, nil, nil, newMovieActive, nil);
    ...

到目前为止,它工作正常(我用TimeValue movietime = GetMovieDuration(movie); 测试并打印它),但现在我想获取电影的每一帧并将其导出到一个文件(首先,稍后我只想将数据保存在内存可以使用它,但我必须知道它是否真的有效,所以现在导出到图像文件更好)。
我怎么做?我需要 GWorld 还是 PixMap?如何从电影文件中获取 GWorld/PixMap,尤其是其中的每一帧?

编辑:我的平台是WinXP

【问题讨论】:

  • 您希望在哪个平台上执行此操作(Windows、Mac 或两者)?

标签: c++ export quicktime movie


【解决方案1】:

这些命令行 OSX 实用程序非常擅长提取 Quicktime 电影的内容,而无需购买 QTPro:

qt_tools

【讨论】:

    【解决方案2】:

    首先,这篇关于电影导出器的文章应该可以帮助您入门:

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

    尽管 MacTech 是一种 Mac 资源,但所有描述的 API 函数也应该在 QuickTime for Windows SDK 中可用。

    一有时间我会自己整理一些示例代码作为参考。

    编辑

    有关更多信息,请参阅本书摘录:

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

    编辑 2 - 高级方法:电影导出器

    如果您需要完成的只是从 QuickTime 电影中提取所有视频帧并将它们转换为 QuickTime API 支持的另一种格式,那么如果使用 电影,您将无需执行任何低级操作出口商

    下面的示例代码允许使用以编程方式调用的电影导出对话框从 QuickTime 电影中提取所有视频帧并将其转换为一组 JPEG 文件。

    只需在对话框的导出组合框中选择电影到图像序列,然后通过点击选项选择所需的图像格式。 p>

    注意 1:如果您需要以非交互方式执行此操作,请告诉我。

    注意 2:为清楚起见,省略了错误处理

    #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();
    

    ...

    【讨论】:

      【解决方案3】:

      如果您只在 OS X 上工作,我会坚持使用 QTKit API,因为它们级别更高,通常更易于使用。

      您想要做的一般要点是:

      1. 逐帧浏览影片中的每一帧
      2. 获取当前帧的图像表示
      3. 将当前帧的图像保存到磁盘上的文件中

      要逐步浏览 QuickTime 影片中的帧,您可以使用 QTKit 中的 QTMovie 类来执行此操作,如下所示:

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

      此代码可以编译,但尚未经过全面测试。

      这种方法的一个警告是 MPEG-1 文件在 OS X 10.5 和更早版本上无法正确解码。据我所知,这已在 10.6 中修复。此外,如果正在编写 Windows 应用程序,则需要使用较低级别的 Quicktime-C API。

      在处理此问题时,请务必查看以下参考页面:

      【讨论】:

        【解决方案4】:

        我通常只是将解码后的帧一个接一个地转储到二进制文件中,然后使用一些 YUV-Viewer 来查看它们是否看起来不错。为此,您必须知道解码帧的确切颜色格式和分辨率。如果你有 RGB,肯定也有观看者。

        更新:

        链接似乎不起作用。您将不得不在谷歌上搜索 YUV-Viewer。或者,您可以从Elecard 购买。

        【讨论】:

        • 抱歉,我没用过 QuickTime。
        猜你喜欢
        • 1970-01-01
        • 2010-11-17
        • 2012-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-04
        相关资源
        最近更新 更多