Home > C++ Classes, Programming > Loading Images using QuickTime

Loading Images using QuickTime

August 1st, 2009 Leave a comment Go to comments

QuickTime can be used to open a variety of image files on Mac OS and Windows. I have put together a simple C++ class that will open image and read image files. By default, QuickTime will read jpeg, tiff, png, gif, bmp, targa, sgi, pdf (first page) and others such as JPEG 2000 (depending on the version and on what components are installed).

Basically, here is how you can proceed to open an image with QuickTime:

Initialize QuickTime

1
2
3
4
5
6
7
8
OSStatus err = noErr;
#ifdef _WIN32
err = InitializeQTML(0); // on windows, call InitializeQTML first
if (err)    return err;  // QuickTime is probably not installed
#endif // _WIN32

err = EnterMovies();
if (err)    return err;  // Failed to initialize QuickTime

Obtain a Graphics Importer ComponentInstance

Opening an image file happens in two steps. First find an image importer within QuickTime, then process the file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
OSStatus OpenQuickTimeImageFile(const char *path)
{
    //--------------------------------------------------------------------------
    //  Obtain a file reference
#ifdef _WIN32
    const CFStringBuiltInEncodings kNativeEncoding = kCFStringEncodingWindowsLatin1
#else
    const CFStringBuiltInEncodings kNativeEncoding = kCFStringEncodingMacRoman;
#endif // _WIN32

    CFStringRef cfPath = CFStringCreateWithCString(kCFAllocatorDefault, path, kNativeEncoding);
    Handle dataRef = NewHandle(sizeof(AliasHandle));
    OSType dataRefType;

    OSStatus err = QTNewDataReferenceFromFullPathCFString(cfPath, kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);
    CFRelease(cfPath);

    //--------------------------------------------------------------------------
    //  Find the image importer

    ComponentInstance fileImporter;
    err = GetGraphicsImporterForDataRef(dataRef, dataRefType, &fileImporter);
    DisposeHandle(dataRef);

Obtain Image Information

Once the image importer is found and loaded, information about the image can be obtained from the image description:

1
2
3
4
5
6
7
    ImageDescriptionHandle imageInfo = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
    err = GraphicsImportGetImageDescription(fileImporter, &mImageInfo);

    int width = (**imageInfo).width;
    int height = (**imageInfo).height;

    DisposeHandle((Handle)imageInfo);

Load the Image

Finally, loading the image has to be done within a GWorld:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    Rect bounds;
    bounds.left = 0;
    bounds.top = 0;
    bounds.right = width;
    bounds.bottom = height;

    int bpp = 4; // bytes per pixel
    int rowBytes = bpp*width;
    unsigned char *data = new unsigned char[height*rowBytes];

    GWorldPtr buffer = NULL;
    err = QTNewGWorldFromPtr(&buffer, k32RGBAPixelFormat, &bounds, NULL, NULL, 0, data, rowBytes);

    err = GraphicsImportSetGWorld(fileImporter, buffer, NULL);
    err = GraphicsImportDraw(fileImporter);

    DisposeGWorld(offscreenBuffer);
    CloseComponent(fileImporter);
}

Special Case – 8bit Grayscale Images

In case you are reading an 8 bit grayscale image (with k8IndexedPixelFormat or k8IndexedGrayPixelFormat instead of k32RGBAPixelFormat), you have to know that QuickTime uses a color table that’s inverted (black is 255 and white is 0). One option is to invert the grayscale image after it has been drawn in the gworld (i.e. data[i] = 255-data[i];) but a more efficient way is to provide QuickTime with a correct color table before drawing in the GWorld:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    if (format == k8IndexedPixelFormat) // we're in 8 bit grayscale
    {
        // the default color table is inverted, so let's create
        CTabHandle grayCTab = GetCTable(40);// gray clut ID = color clut ID +32

        // invert the default color table
        for (int i = 0; i < 256; ++i)
        {
            (**grayCTab).ctTable[i].rgb.red = ~(**grayCTab).ctTable[i].rgb.red;
            (**grayCTab).ctTable[i].rgb.green = ~(**grayCTab).ctTable[i].rgb.green;
            (**grayCTab).ctTable[i].rgb.blue = ~(**grayCTab).ctTable[i].rgb.blue;
        }

        err = QTNewGWorldFromPtr(&buffer, k8IndexedPixelFormat, &bounds, grayCTab, NULL, 0, data, rowBytes);
        DisposeCTable(grayCTab);
    }
}
Categories: C++ Classes, Programming Tags:
  1. No comments yet.
  1. No trackbacks yet.
*

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 158,454 bad guys.