Apr 00 QTToolkit
Volume Number: 16
Issue Number: 4
Column Tag: QuickTime Toolkit
Quick on the Draw
By Tim Monroe
Using QuickTime's Graphics Importers and Exporters
Introduction
QuickTime is perhaps best known for its ability to play movies, but over the years it
has gained the ability to handle quite a large number of other types of media, including
text, MIDI data, virtual reality, sprite animation, vector-defined images, and
streamed audio and video. QuickTime also provides a very powerful set of capabilities
for managing still images (or graphics) stored in any of a large number of common
image file formats. For instance, you can use QuickTime's application programming
interfaces to open and display PICT, TIFF, JPEG, BMP, PhotoShop, GIF, PNG, and
FlashPix files (to name only a handful of the supported formats). Moreover, you can
use QuickTime to save an image in any one of a number of image formats, including
PICT, TIFF, JPEG, BMP, PhotoShop, and PNG. These two aspects of handling images -
reading them from files and writing them to files - are handled by parts of QuickTime
known as graphics importers and graphics exporters. In this article, we'll investigate
the most fundamental ways of using graphics importers and exporters to manipulate
still images.
The most obvious benefit that graphics importers and exporters provide is to insulate
our applications from the nitty-gritty details of any particular image file format and
image compression scheme. We can use exactly the same routines to open and display a
JPEG file as we use to open and display a PICT file. In fact, our application never
really needs to know what kind of image file it has opened. We can always determine
this information about the image file if we want to, but for most uses that's
information we simply don't need. Graphics importers and exporters provide a host of
other services. We can change the image matrix used by a graphics importer when
drawing an image, thereby drawing the image at a different size or orientation. We can
also change the graphics mode used by a graphics importer; this allows us, for
instance to composite the image on top of other images or on top of QuickTime movies.
In this article, we'll see how to open an image file, read the image from it, and draw
that image in a window on the screen. We'll also see how to alter the image matrix to
draw the image at different sizes and orientations. Finally, we'll see how to export the
image into some other type of image format. To wrap this all up into a neat package,
let's set ourselves the goal of replicating as much of the functionality of QuickTime's
PictureViewer application as possible. Figure 1 shows PictureViewer's Image menu,
and Figure 2 shows the Image menu of our application, which we'll call QTGraphics.
Figure 1. The Image menu from the PictureViewer application.
Figure 2. The Image menu from the QTGraphics application.
As you can see, these menus are quite similar. The main difference is that QTGraphics
adds a check mark in the menu to indicate the current size of the image window. This is
a useful feature and it's relatively simple to add, given the way we've chosen to handle
our images. Another difference is that QTGraphics does not support the "Fill Screen
menu command. The reason for this is simply that fitting an image to the current
screen size is extremely platform-specific and not terribly enlightening, at least in
terms of using graphics importers. So I've left the implementation of that feature as an
exercise for the reader. Finally, the Image menu of QTGraphics contains the Export
item, which PictureViewer places in its File menu (where it more properly belongs).
Along the way, we'll take a few small detours to explore some other features of
graphics importers and exporters. We'll consider briefly how to handle image files
that contain more than one image, and we'll take a quick look at how to distinguish
image files from other kinds of files. So let's get started.
Importing Images
A graphics import component, or graphics importer, is a software component that
provides services for handling still images. Graphics importers were introduced in
QuickTime version 2.5 to facilitate opening and drawing images. Subsequent versions
of QuickTime have added new graphics importers and expanded the capabilities of
existing importers. For instance, QuickTime 4 added the ability to work with files that
contain multiple images or multiple image layers (such as FlashPix files or PhotoShop
files).
It's very simple to open an image file and display the image (or images) contained in
the file using the application programming interfaces provided by graphics importers.
Suppose that we've got a file system specification (that is, an FSSpec) that picks out an
image file. Then we can use the QTGraph_ShowImageFromFile function defined in
Listing 1 to display that image in a window on the screen.
______________________________
Listing 1: Opening an image file and displaying its image.
QTGraph_ShowImageFromFile
void QTGraph_ShowImageFromFile (FSSpec *theFSSpec)
{
GraphicsImportComponent myImporter = NULL;
Rect
myRect;
WindowPtr myWindow =
NULL;
GetGraphicsImporterForFile(theFSSpec, &myImporter);
if (myImporter != NULL) {
GraphicsImportGetNaturalBounds(myImporter, &myRect);
MacOffsetRect(&myRect, 50, 50);
myWindow = NewCWindow(NULL, &myRect, NULL, true,
[TOKEN:28271]GrowDocProc, (WindowPtr)-1L,
true, 0);
if (myWindow != NULL) {
GraphicsImportSetGWorld(myImporter, (CGrafPtr)myWindow,
NULL);
GraphicsImportDraw(myImporter);
CloseComponent(myImporter);
}
}
}
QTGraph_ShowImageFromFile first calls the GetGraphicsImporterForFile function,
which opens the specified image file and determines which graphics import component
(if any) can handle the image data contained in that file. If
GetGraphicsImporterForFile finds a suitable graphics importer, it returns an instance
of that importer in the myImporter parameter. We'll use that graphics importer
instance, of type GraphicsImportComponent, in all our subsequent calls to graphics
importer functions. The type GraphicsImportComponent is simply a component
instance:
typedef ComponentInstance GraphicsImportComponent;
As a result, we shall eventually need to close the component instance by calling
CloseComponent (as shown in the final line of Listing 1).
GetGraphicsImporterForFile uses a fairly straightforward algorithm for deciding what
kind of image a file contains. First, on Macintosh systems, it looks at the file's type.
For instance, if the specified file is of type 'PICT', then GetGraphicsImporterForFile
opens an instance of the PICT image importer. Otherwise, if it cannot find a suitable
importer based on the file's type, GetGraphicsImporterForFile inspects the filename
extension, if it has one. So, for example, a file whose name ends with '.gif' would be
imported as a GIF image. Finally, if neither of these steps reveals the type of the image
in the file, then GetGraphicsImporterForFile sequentially opens an instance of each
available graphics importer and instructs it to examine some of the data in the file to
see whether it can handle that kind of data. (Image files often contain a header that