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
.
Setting the Properties of an Image Destination
Writing an Image to 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 NSDictionary
are 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. |
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; |
} |
© 2001, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-07-02)