< Previous PageNext Page > Hide TOC

Working with Image Destinations

An image destination abstracts the data-writing task and eliminates the need for you to manage data through a raw buffer. An image destination can represent a single image or multiple images. It can contain thumbnail images as well as properties for each image. After creating a CGImageDestination object for the appropriate destination (URL, CFData object, or Quartz data consumer), you can add image data and set image properties. When you are finished adding data, call the function CGImageDestinationFinalize.

In this section:

Setting the Properties of an Image Destination
Writing an Image to an Image Destination


Setting the Properties of an Image Destination

The function CGImageDestinationSetProperties adds a dictionary (CFDictionaryRef) of properties (key-value pairs) to the images in an image destination. Although setting properties is optional, there are many situations for which you will want to set them. For example, if your application allows users to add keywords to images or change saturation, exposure, or other values, you’ll want to save that information in the options dictionary.

Image I/O defines an extensive set of keys to specify such things as compression quality, background compositing color, EXIF dictionary keys, Color model values, GIF Dictionary keys, Nikon and Canon camera keys, and many more. See CGImageProperties Reference.

When setting up the dictionary, you have two choices. You can either create a CFDictionary object or you can create an NSDictionary object, then cast it as a CFDictionaryRef when you pass the options dictionary to the function CGImageDestinationSetProperties. (CFDictionary and NSDictionaryare interchangeable, or toll-free bridged.) Listing 3-1 shows a code fragment that assigns key-value pairs for three properties, then creates a dictionary that contains those properties. Because this is a code fragment, the necessary calls to release the CFNumber and CFDictionary objects created by the code are not shown. When you write your code, you need to call CFRelease when you no longer need each of these objects.

When you set up a key-value pair for a property, you need to consult the reference documentation (see CGImageDestination Reference and CGImageProperties Reference) for the expected data type of the value. As you can see in Listing 3-1, numerical values typically need to be wrapped in a CFNumber object. When you use Core Foundation types for dictionary values, you can also supply the callback constants when you create the dictionary—kCFTypeDictionaryKeyCallBacks and kCFTypeDictionaryValueCallBacks. (See CFDictionary Reference.)

Listing 3-1  Setting the properties of an image destination

float compression = 1.0; // Lossless compression if available.
int orientation = 4; // Origin is at bottom, left
CFStringRef myKeys[3];
CFTypeRef   myValues[3];
CFDictionaryRef myOptions = NULL;
myKeys[0] = kCGImagePropertyOrientation;
myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
myKeys[1] = kCGImagePropertyHasAlpha;
myValues[1] = kCFBooleanTrue;
myKeys[2] = kCGImageDestinationLossyCompressionQuality;
myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 3,
                      &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Release the CFNumber and CFDictionary objects when you no longer need them.

Writing an Image to an Image Destination

To write an image to a destination, you first need to create an image destination object by calling the CGImageDestinationCreateWithURL, CGImageDestinationCreateWithData, or CGImageDestinationCreateWithDataConsumer functions. You need to supply the UTI of the resulting image file. You can either supply a UTI or the equivalent constant, if one if available. See Table 1-1.

After you create an image destination, you can add an image to it by calling the CGImageDestinationAddImage or CGImageDestinationAddImageFromSource functions. If the format of the image destination file supports multiple images, you can repeatedly add images. Calling the function CGImageDestinationFinalize signals Image I/O that you are finished adding images. Once finalized, you cannot add any more data to the image destination.

Listing 3-2 shows an implementation of the NSPersistentDocument method writeToURL:ofType:forSaveOperation:originalContentsURL:error: that sets up an image destination, adds an image along with options, and finalizes the destination. Although this listing shows how to use an image destination from within an Objective-C method, you can just as easily create and use an image destination in a procedural C function. In the listing, assume that saveMetadataAndOptions is an NSDictionary object that stores image metadata (such as camera settings) and options (such as compression settings and color profile name).

Listing 3-2   A method that writes an image to a URL

- (BOOL) writeToURL:(NSURL *)absURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOp originalContentsURL:(NSURL *)absOrigURL error:(NSError **)outError
{
    BOOL status = NO;
 
    CGImageRef image = [self currentCGImage];
    // Make sure the image exists before continuing.
    if (image==nil)
        goto bail;
 
    // Create a URL image destination for the given image type,
    // for one image, with no options.
    CGImageDestinationRef myImageDest =
            CGImageDestinationCreateWithURL((CFURLRef)absURL,
                       (CFStringRef)typeName, 1, nil);
    // Make sure the image destination exists before continuing.
    if (myImageDest==nil)
        goto bail;
 
    // Add the image to the destination using previously saved options.
    CGImageDestinationAddImage(myImageDest, image, myOptions);
    // Finalize the image destination.
    status = CGImageDestinationFinalize(myImageDest);
    // Release the image as soon as you no longer need it.
    CGImageRelease(image);
 
bail:
 
    if (status==NO && outError){
        *outError = [NSError errorWithDomain:NSCocoaErrorDomain
                                        code:NSFileWriteUnknownError
                                    userInfo:nil];
 
     }
    return status;
}


< Previous PageNext Page > Hide TOC


© 2001, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-07-02)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.