| public.jpeg | com.compuserve.gif | public.png | public.jpeg-2000 |
| com.nikon.raw-image | com.pentax.raw-image ( | com.sony.arw-raw-image | com.adobe.raw-image |
| public.tiff | com.canon.crw-raw-image | com.canon.cr2-raw-image | com.canon.tif-raw-image |
| com.sony.raw.image | com.olympus.raw-image | com.konicaminolta.raw-image | com.panasonic.raw-image |
| com.fuji.raw-image | com.adobe.photoshop-image | com.adobe.illustrator.ai-image | com.adobe.pdf |
| com.microsoft.ico | com.microsoft.bmp | com.truevision.tga-image | com.sgi.sgi-image |
| com.apple.quicktime-image | com.apple.icns | com.apple.pict | com.apple.macpaint-image |
| com.kodak.flashpix-image | public.xbitmap-image | com.ilm.openexr-image | public.radiance |
Table 1: Supported CGImageSourceRef UTIs on Mac OS X 10.4.8
These are all the uniform type identifiers for the types of image data that the ImageIO framework knows how to read. Notice that ImageIO can read some camera raw formats as well as the usual formats like jpeg, png, and gif.
The CGImageSourceRef data type encapsulates the information needed to move image data into Quartz. Once you have created and read image data into a CGImageSourceRef
object, you can then pass it to CGImageSoure functions. CGImageSource functions let you to perform operations on the image data, such as getting thumbnails,
image properties, and of course, creating a CGImageRef from the source image data.
Listing 2 shows the four functions in the ImageIO framework that let you create a CGImageSourceRef object:
CGImageSourceRef CGImageSourceCreateWithData(CFDataRef data, CFDictionaryRef options); CGImageSourceRef CGImageSourceCreateWithURL(CFURLRef url, CFDictionaryRef options); CGImageSourceCreateIncremental(CFDictionaryRef options); CGImageSourceRef CGImageSourceCreateWithDataProvider(CGDataProviderRef provider, CFDictionaryRef options);
Listing 2: CGImageSourceRef Creation APIs
Code listing 3 shows the simplest case of creating a CGImageSourceRef first from an NSData object, and then from a file. After creating the CGImageSourceRef object,
the code then uses it to create a CGImageRef object.
/* Create a CGImageSourceRef from raw data */
CGImageRef CreateCGImageFromData(NSData* data)
{
CGImageRef imageRef = NULL;
CGImageSourceRef sourceRef;
sourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL);
if(sourceRef) {
imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
CFRelease(sourceRef);
}
return imageRef;
}
/* Create a CGImageSourceRef from a file */
CGImageRef CreateCGImageFromFile(NSString* path)
{
NSURL* url = [NSURL fileURLWithPath:path];
CGImageRef imageRef = NULL;
CGImageSourceRef sourceRef;
sourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
if(sourceRef) {
imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
CFRelease(sourceRef);
}
return imageRef;
}
Listing 3: Creating a CGImageSourceRef Object
After creating the CGImageSourceRef object, the code in listing 3 uses the CGImageSourceCreateImageAtIndex function to create a
CGImageRef object. Let's look at the signature of that function:
CGImageRef CGImageSourceCreateImageAtIndex( CGImageSourceRef isrc, size_t index, CFDictionaryRef options );
The first argument is the CGImageSourceRef object, which we created from either a URL, or a file. An CGImageSourceRef can contain data for more than one image. That is the purpose of
the second argument. The index argument is a zero-based location of the image within the image source object. The options argument allows you to specifiy more
image
creation options using a CFDictionaryRef. This argument is optional, and may be NULL, as shown in listing 3.
Another way to create an CGImageSourceRef object is to use the CGImageSourceRefCreateIncremental function. With this function, the resulting CGImageSourceRef is empty. You then add
data using either the CGImageSourceUpdateDataProvider function, or the CGImageSourceUpdateData function. This way, you create the image as data becomes available,
for example, an image viewed over the web.
In listing 3, we saw that an image source can contain more than one image. This is shown by the index argument of the CGImageSourceCreateImageAtIndex function.
How do you determine how many images an image source contains? With the CGImageSourceGetCount function. This function takes one argument, a CGImageSourceRef
object:
size_t CGImageSourceGetCount( CGImageSourceRef isrc );
Table 2 shows the additional functions you can use for getting information about an image source:
| Function | Purpose |
|---|---|
| CGImageSourceGetTypeID | Returns the unique type identifier for the image source. |
| CGImageSourceGetType | Returns the UTI for the image source. |
| CGImageSourceCopyTypeIdentifiers | Returns an array of supported UTIs. |
| CGimageSourceGetCount | Returns the number of images (not including thumbnails) for the image source. |
| CGImageSourceCopyProperties | Returns a dictionary containing the properties of the image source. |
| CGImageSourceCopyPropertiesAtIndex | Returns a dictionary containing the properties of the image at a specified index. |
| CGImageSourceGetStatus | Returns the status of the image source. |
| CGImageSourceGetStatusAtIndex | Returns the status of the image at a specified index. |
Table 2: Information Retrieval functions in the ImageIO Framework
First, let's look at the image formats that ImageIO knows how to write.
The CGImageDestinationCopyTypeIdentifiers function retrieves all the UTIs for the kinds of
image data that the ImageIO framework knows how to write. Listing 4 shows some code to call CGImageDestinationCopyTypeIdentifiers and log the resulting array to the
debugger console:
CFArrayRef types = CGImageDestinationCopyTypeIdentifiers(); CFShow(types);
Listing 4: Reading Supported CGImageDestination UTIs
Table 3 shows the results of calling CGImageDestinationCopyTypeIdentifiers on a system running Mac OS X 10.4.8:
| public.jpeg | com.compuserve.gif | public.png | public.jpeg-2000 |
| public.tiff | com.adobe.photoshop.image | com.adobe.pdf | com.microsoft.bmp |
| com.truevision.tga-image | com.sgi.sgi-image | com.apple.pict | com.ilm.openexr-image |
Table 3: Supported CGImageDestinationRef UTIs on Mac OS X 10.4.8
After you have read the image data and performed the required operations on it, you will want to move the data out of Quartz. The CGImageDestinationRef data type is used to accomplish this
task. CGImageDestinationRef objects are similar to CGImageSourceRef objects in that they can represent a variety of image data, including one or more images, thumbnails,
as well as storing various properties.
Similar to creating a CGImageSourceRef object, there are three ImageIO functions for creating a CGImageDestinationRef object:
CGImageDestinationRef CGImageDestinationCreateWithData(CFMutableDataRef data, CFStringRef type, size_t count, CFDictionaryRef options); CGImageDestinationRef CGImageDestinationCreateWithURL(CFURLRef url, CFStringRef type, size_t count, CFDictionaryRef options); CGImageDestinationRef CGImageDestinationCreateWithDataConsumer(CGDataConsumerRef consumer, CFStringRef type, size_t count, CFDictionaryRef options);
A CGImageDestinationRef object can contain one or more images, as you can see from the count argument of the creation functions.
Once you have created a CGImageDestinationRef object, you can add images to it using the CGImageDestinationAddImage function.
void CGImageDestinationAddImage( CGImageDestinationRef idst, CGImageRef image, CFDictionaryRef properties );
You can also add an image to a destination directly from a source:
void CGImageDestinationAddImageFromSource( CGImageDestinationRef idst, CGImageSourceRef image, size_t index, CFDictionaryRef properties );
Note the two functions are almost identical, except when adding from a CGImageSourceRef object, you must specify the index within the source container, because a source can also
contain more than one image.
After you have added all the images to the destination, you must call CGImageDestinationFinalize to write the data to the destination object (URL, data, or data consumer).
Once you call this function, you cannot add any more images to the destination.
void CGImageDestinationFinalize( CGImageDestinationRef idst );
Reading and writing data to and from Quartz is only part of the picture. Mac OS X has many other imaging technologies built in that you can take advantage of. For example, you can take full advantage of the Core Image API to perform near real-time video and still image processing on Quartz image data.
In this section we will branch out from ImageIO just a bit, to demonstrate how you can exchange image data between different imaging technologies on Mac OS X.
The Core Image framework was built into Mac OS X 10.4 to support near real-time operations on video and still image data. You can use Core Image functions to correct color, blur and sharpen, and to
perform geometric distortions. The Core Image API is built to use its own data types, namely the CIImage type; it cannot operate on Quartz images, which are of type CGImageRef.
You will have to convert your Quartz CGImageRef objects to Core Image CIImage objects.
Quartz 2D does not provide any functions for performing the conversion. They are instead found in the Core Image framework itself, implemented as methods on CIImage. Two methods
provide a way to create a CIImage object from a CGImageRef object:
+ (CIImage *)imageWithCGImage:(CGImageRef)image; + (CIImage *)imageWithCGImage:(CGImageRef)image options:(NSDictionary *)d;
Converting back to a Quartz image is done using a method on the Core Image CIContext class:
- (CGImageRef *)createCGImage:(CIImage *)im fromRect:(CGRect)r;
Updated: 2006-12-05