Technical: QuickTime
Advanced Search
Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

Exporting Images

Dispatch 14

Question: How can I use QuickTime to export a picture as an image file?

Graphics importer components provide a simple, flexible and extensible way for you to draw pictures that are stored in a wide variety of image file formats. They also turn out to be the easiest way to export pictures to several file formats.

Normally you create a graphics importer instance with the GetGraphicsImporterForFile call, or one of its relatives. Afterwards you can call GraphicsImportExportImageFile to export that image to a new file:

GetGraphicsImporterForFile(
                &theExistingFile, 
                &gi);
                
GraphicsImportExportImageFile(
                gi, 
                kQTFileTypeJPEG,      // or one of several other file types
                0,                    // ie, the default creator for this type
                &theNewFile, 
                theScriptCode);

The file type determines the data format for the exported file. For example, if you pass kQTFileTypeJPEG, a JPEG file will be created.

If the picture you want to export isn't already in a file, it doesn't make sense to call GetGraphicsImporterForFile. Instead, you can create an instance of the "picture file" graphics importer yourself and give it a handle that contains a "source picture file".

OpenADefaultComponent(
                GraphicsImporterComponentType,
                kQTFileTypePicture,
                &gi);

GraphicsImportSetDataHandle(
                gi,
                thePictureFileHandle);

GraphicsImportExportImageFile(
                gi, 
                kQTFileTypeJPEG,
                0, 
                &theNewFile, 
                theScriptCode);

Picture files are just like picture handles, except that they have an extra 512-byte header at the front. (Any data in this header is usually ignored, but it must be there for historical reasons.) The graphics importer for picture files expects and skips this 512-byte header, so you must insert it.

PicHandle thePicture = /* create a picture */;
Handle thePictureFileHandle;

thePictureFileHandle = NewHandleClear(512);
HandAndHand((Handle)thePicture,thePictureFileHandle);

Finally, here's a function that puts it all together. This function exports a picture to a file. The new file is described by its type, creator, specification and script code. If you don't know what script code to use, it's usually safe to use smSystemScript.

#include <OSUtils.h>
#include <ImageCompression.h>
#include <QuickTimeComponents.h>

OSErr ExportPicHandleToFile(
    PicHandle thePicture, 
    OSType filetype,
    OSType filecreator,
    FSSpec *filespec, 
    ScriptCode filescriptcode)
{
    Handle h;
    OSErr err;
    GraphicsImportComponent gi = 0;
    
    // Convert the picture handle into a PICT file (still in a handle) 
    // by adding a 512-byte header to the start.
    h = NewHandleClear(512);
    err = MemError();
    if(err) goto bail;
    err = HandAndHand((Handle)thePicture,h);
    
    err = OpenADefaultComponent(
                GraphicsImporterComponentType,
                kQTFileTypePicture,
                &gi);
    if(err) goto bail;
    
    err = GraphicsImportSetDataHandle(gi, h);
    if(err) goto bail;
    
    err = GraphicsImportExportImageFile(
                gi, 
                filetype, 
                filecreator, 
                filespec, 
                filescriptcode);
    if(err) goto bail;
    
bail:
    if(gi) CloseComponent(gi);
    if(h) DisposeHandle(h);
    return err;
}

Extra credit

One problem with using HandToHand to add the 512-byte header to the picture handle is that you make an extra copy of the picture data. If you don't need the original picture handle after the export, you could fix this by using Munger to insert the header into the handle:

PicHandle thePicture = /* create a picture */;
Handle thePictureFileHandle = (Handle)thePicture;
char randomData[512];

Munger(thePictureFileHandle, 0, nil, 0, randomData, 512);

(Munger is documented in Inside Macintosh: Operating System Utilities. It rhymes with "plunger.")

Could you write my user interface for me? Please?

If you've been gazing hungrily at the "Export..." command in PictureViewer Pro and wishing you could implement a matching user experience, you're in luck. This command is actually implemented by a single call, GraphicsImportDoExportImageFileDialog. All of the parameters after the component are optional, so you can call it as simply as this:

err = GraphicsImportDoExportImageFileDialog(
            gi, nil, nil, nil, nil, nil, nil);

What were those export formats again?

Under QuickTime 3.0, the available still image export formats are BMP, JPEG, Photoshop, Picture and QuickTime Image. However, future versions may bring more formats and extensibility.

Your application can find out more information about available export formats by calling the GraphicsImportGetExportImageTypeList function. This function returns an atom container (which your application must dispose of) containing several kGraphicsExportGroup atoms. Each of these represents one export format, and has child atoms which indicate the file type (kGraphicsExportFileType), human-readable format name (kGraphicsExportDescription), file extension (kGraphicsExportExtension) and optionally MIME type (kGraphicsExportMIMEType).

Here's a code fragment showing how you could find out the available export file types. Error-handling code has been removed.

QTAtomContainer theExportInfo = nil;
short theNumberOfExportTypes, i;

GraphicsImportGetExportImageTypeList(
                gi,
                &theExportInfo);

theNumberOfExportTypes = QTCountChildrenOfType(
                theExportInfo,
                kParentAtomIsContainer,
                kGraphicsExportGroup);        // 'expo'

for(i = 1; i <= theNumberOfExportTypes; i++) {
    QTAtom groupAtom, fileTypeAtom;
    OSType fileType;
    
    groupAtom = QTFindChildByIndex(
                    theExportInfo,
                    kParentAtomIsContainer,
                    kGraphicsExportGroup,
                    i,
                    nil);
    
    fileTypeAtom = QTFindChildByIndex(
                    theExportInfo,
                    groupAtom,
                    kGraphicsExportFileType,  // 'ftyp'
                    1,
                    nil);
    
    QTCopyAtomDataToPtr(
                    theExportInfo,
                    fileTypeAtom,
                    false,
                    sizeof(fileType),
                    &fileType,
                    nil);
    
    fileType = EndianU32_BtoN(fileType);      // data in QT atoms is always big-endian
}

QTDisposeAtomContainer(theExportInfo);

See Also

QuickTime 3 Reference - Graphics Importers

Change History

28 Apr 98 - jsam - First published
15 May 98 - jsam - Revised
Topics
Previous | Next