QTKitPlayerにフレームを画像として保存する

QTKitPlayerで再生中の動画の、現フレームを画像として保存する方法。ここではpngに限定してる。MovieDocument.hに次のコードを追加。

- (IBAction)doSaveCurrentFrameAsImage:(id)sender
{
    NSSavePanel *savePanel;

    QTTime qtCurrentTime = [mMovie currentTime];
    float currentTime = qtCurrentTime.timeValue / qtCurrentTime.timeScale;

    NSString *baseName = [[[self fileName] lastPathComponent] stringByDeletingPathExtension];
    NSString *fileName = [NSString stringWithFormat:@"%@-%07.2f.%@", baseName, currentTime, @"png"];

    // init
    savePanel = [NSSavePanel savePanel];

    // run the export sheet
    [savePanel beginSheetForDirectory:nil file:fileName modalForWindow:mMovieWindow modalDelegate:self
                       didEndSelector:@selector(saveCurrentFrameAsImagePanelDidEnd: returnCode: contextInfo:) contextInfo:nil];
}

    - (void)saveCurrentFrameAsImagePanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
    if (returnCode == NSOKButton) {

        // 現在のフレームの画像をNSImageで取得
        // 本来の画像サイズで取得するためにオプションにQTMovieNaturalSizeAttributeを追加
        NSArray *keys = [NSArray arrayWithObjects:QTMovieFrameImageType, QTMovieFrameImageSize, nil];
        NSArray *objects = [NSArray arrayWithObjects:QTMovieFrameImageTypeNSImage, [mMovie attributeForKey:QTMovieNaturalSizeAttribute], nil];
        NSDictionary *attrs = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
        NSImage             *image = [(NSImage *)[mMovie frameImageAtTime:[mMovie currentTime] withAttributes:attrs error:NULL] retain];

        // 画像データの変換
        // < http://www15.plala.or.jp/NovemberKou/programming/2ndGeneration/2ndHome/ImagePanelController/createPictureData.html >
        NSBitmapImageRep    *bitmapImageRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
        NSDictionary        *properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
                                                                      forKey:NSImageInterlaced];
        NSData *pngData = [bitmapImageRep representationUsingType:NSPNGFileType
                                                       properties:properties];
        // export
        if (![pngData writeToFile:[sheet filename] atomically:YES])
            NSRunAlertPanel(@"Error", @"Error saving current frame as image.", nil, nil, nil);

        [image release];
    }
}

ちなみにwindowControllerDidLoadNib:あたりで[[mMovieView window] setContentAspectRatio:contentSize];をしておけば、QTMovieViewのアスペクト比も固定されるので便利。