Image IO


Image I/O

Image I/O is part of Core Graphics and follows the Core Graphics API conventions. Strictly speaking, it is not part of Quartz 2D, but it does integrate closely with Quartz 2D and is an invaluable asset. The two primary opaque data types that make up the Image I/O system are CGImageSource and CGImageDestination. The CGImageSource class represents an abstract source for image data. Conceptually, the image source contains one or more images. An image file, a network stream, or a block of memory are all valid image sources. Each CGImageSource knows how to extract images from a particular source. After creating a CGImageSource, you can ask it to return any of those images as a CGImageRef.

Not surprisingly, the CGImageDestination represents an object that knows how to take one or more CGImages, encode them in a particular format, and store the results, or even transfer them elsewhere. After creating an image destination attached to a storage device, your application can pass it one or more images and then ask the destination to encode and save the graphics.

The image source and image destination classes don't concern themselves with the details of interacting with the file system or the network. Instead the CGImageSource opaque data type uses the familiar CGDataProvider opaque data type that we explored when creating images, and CGImageDestination uses its companion, the CGDataConsumer opaque data type. These objects offer your application a lot of flexibility in deciding where the image data is coming from. It can read from the network or from a local file, or it can generate the image data on-the-fly if that makes sense.

Import Image Example

The first sample will demonstrate using a CGImageSource. This code performs the same task as the QuickTime example earlier in the chapter. It is included with the sample code as part of an application called ImageIOImport. Listing 9.3 recreates the image import routine from listing 9.1 using a CGImageSource instead of a QuickTime import component:

Listing 9.3. Importing an Image with a CGImageSource

void OpenImageFile(FSRef &whichFile) {     CFURLRef fileURL = CFURLCreateFromFSRef(NULL, &whichFile);     // Create a data provider for the image source     CGDataProviderRef dataProvider =             CGDataProviderCreateWithURL(fileURL);     CFRelease(fileURL);     fileURL = NULL;     // Create the image source itself     CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider(             dataProvider, NULL);     CGDataProviderRelease(dataProvider);     dataProvider = NULL;     // extract the first image (0 based index) from the image source     CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource,             0, 0);     CFRelease(imageSource);     imageSource = NULL;     // if we got an image, then create a new window and put     // the image into it.     if(image) {             CreateImageWindow(image);             CGImageRelease(image);             image = NULL;     } } 

This code sample demonstrates the basic technique of using an image source. It first creates a data provider that points to the image data we want to import. It then creates a data source from that data provider. With the data source in hand, the code simply asks for the first image in that source (the images are indexed starting at 0). When the image has been imported, the computer creates a window to display the results.

This code sample ignores a simplifying utility provided by the Image I/O API. The utility routine, CGImageSourceCreateWithURL, will create a data provider and an image source in one step. We avoided this routine for the code sample to make it clear that you can use any data provider you like.


Image I/O includes additional functionality related to the loading of images. Of particular interest may be the fact that it can retrieve image thumbnails from file formats that provide them, and it supports the incremental loading of large images. Those topics will not be covered here, but you can read more about them in Apple's documentation.

Export Image Example

It's just as easy to export an image using Image I/O as it is to read one in. By now the process should be pretty obvious. The duality of creating a CGDataProvider for an image import operation is creating a CGDataConsumer for the results of compressing an image. The CGDataConsumer is responsible for taking the compressed image data and doing something with it, be it storing the data on a disk or writing it into a block of memory. Once you've decided what to do with the image data, you create a CGImageDestination that connects to the data consumer. You can pass the images you want to store in the destination to that object, and the system will handle compressing the image and shipping it off to the data consumer. Listing 9.4 demonstrates the technique of writing a CGImage into a file using a CGImageDestination.

Listing 9.4. Exporting an Image Using Image I/O

void ExportPNGImage(CGImageRef image) {     // We're all set up to save. Ask the user where we should save the file     CFURLRef saveLocation = CopySaveLocation();     if(NULL != saveLocation) {             // Create a data consumer that saves into the file the user             // selected             CGDataConsumerRef dataConsumer =                     CGDataConsumerCreateWithURL(saveLocation);             // Create an image destination attached to the data consumer             CGImageDestinationRef imageDestination =                     CGImageDestinationCreateWithDataConsumer(                             dataConsumer, kUTTypePNG, 1, NULL);             CGDataConsumerRelease(dataConsumer);             // Add an image to the destination             CGImageDestinationAddImage(imageDestination, image, NULL);             // Finish the export             CGImageDestinationFinalize(imageDestination);             CFRelease(imageDestination);             imageDestination = NULL;     } } 

One interesting point to note about this code sample and Image I/O is that you specify the type of file you want to export using a Uniform Type Identifier (UTI). In this case the UTI we use is kUTTypePng. Uniform Type Identifiers are a mechanism for specifying the type of various and sundry things that have distinguishable types. That's a bit of a vague description for an odd concept. In this case there are a number of different types of files you might export to using Image I/O. You use image file type UTIs to tell Image I/O what type of file you want to use. For more information on UTI's, you can read Apple's documentation on the subject at

<http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/understand_utis_intro/chapter_1_section_1.html>

Note that after adding the image, the code calls CGImageDestinationFinalize. If you do not call this method, the computer may not finish writing the data to the output properly. Also once you have called this routine, you will be unable to add more files to the CGImageDestination.




Quartz 2D Graphics for Mac OS X Developers
Quartz 2D Graphics for Mac OS X Developers
ISBN: 0321336631
EAN: 2147483647
Year: 2006
Pages: 100

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net