Pergunta

Eu quero abrir um filme-File existente e exportar cada quadro deste arquivo para uma imagem como JPEG ou TIFF. Eu fiquei tão longe até agora:

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);
    ...

Até agora ele funciona muito bem (eu testei com TimeValue movietime = GetMovieDuration(movie); e imprimi-lo), mas agora eu quero começar cada frame do filme e exportá-lo para um arquivo (por primeiro, depois eu só quero manter os dados na memória para trabalho com ele, mas eu tenho que saber se ele realmente funciona, então exportação para um arquivo de imagem é melhor para agora).
Como faço isso? Preciso de um GWorld ou um PixMap? Como faço para obter um GWorld / PixMap a partir de um filme de arquivo, especialmente cada quadro dele?

Editar: Minha plataforma é WinXP

Foi útil?

Solução

Como um começo, este artigo sobre os exportadores de cinema deve muito bonito você começar:

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

Mesmo que MacTech é um recurso Mac, todas as funções da API descritos devem estar disponíveis no QuickTime para Windows SDK também.

Vou bater um código de exemplo junto a mim mesmo como uma referência aqui assim que eu encontrar o tempo.

Editar

Veja este trecho do livro para informações adicionais:

QuickTime Toolkit - reprodução de filmes básica e Tipos de mídia @ Google Books

Editar 2 - A abordagem de Alto Nível: Filme Exportadores

Se tudo que você precisa para realizar é extrair todos os quadros de vídeo a partir de um filme QuickTime e convertê-los para outro formato suportado pela API do QuickTime que você não tem que tomar quaisquer ações de baixo nível que seja, se usando um Movie exportador .

A seguir código de exemplo permite extrair e converter todos os quadros de vídeo a partir de um filme QuickTime para, F. E., um monte de arquivos JPEG usando um Filme Export diálogo programaticamente invocado.

Basta selecionar Filme para Sequência de Imagens na Exportar caixa de combinação da caixa de diálogo e selecione o formato de imagem desejado pressionando Opções .

Nota 1:. Se você precisar fazer isso de forma não interativa, é só me avisar

Nota 2: tratamento de erros foi omitida para maior clareza

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

...

Outras dicas

Se você está trabalhando em OS X somente eu iria ficar com as APIs QTKit porque eles são muito mais elevados nível e geralmente mais fácil de trabalhar com ele.

A essência geral do que você quer fazer é:

  1. passo através de cada quadro em um filme
  2. Obter uma representação de imagem para o quadro atual
  3. imagem Excepto o quadro atual para um arquivo no disco

para percorrer os quadros em um filme QuickTime, você pode usar o QTMovie classe em QTKit fazer isso da seguinte forma:

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

Este compila o código, mas não foi totalmente testada.

Uma advertência com esta abordagem é que os arquivos MPEG-1 não irá decodificar corretamente no OS X 10.5 e versões anteriores. Isso foi corrigido a partir de 10,6, tanto quanto eu sei. Além disso, se estiver escrevendo um aplicativo do Windows, você precisará usar o menor alavanca Quicktime-C APIs.

Certifique-se de verificar os seguintes páginas de referência, enquanto trabalhava sobre isso:

Estes utilitários OSX linha de comando são realmente bons em extrair o conteúdo de um filme Quicktime sem ter que comprar QTPro:

qt_tools

Normalmente, eu simplesmente despejar os quadros decodificados em um binário após o outro e, em seguida, usar algum YUV-Viewer para ver se eles olham Ok. Para isso você tem que saber o formato de cor exata e resolução dos quadros decodificados. Se você tiver RGB, certamente há também os espectadores para isso.

UPDATE:

Link não parecem funcionar. Você vai ter que Google para uma YUV-Viewer. Alternativamente, você pode comprar um de Elecard .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top