Introducing CGImage


Quartz 2D uses the same opaque data type to represent both images and image masks. That opaque data type is simply called CGImage. The CGImage object itself is a surprisingly lightweight entity. Rather than keeping track of a lot of data in and of itself, the CGImage class relies on other objects to manage many details on its behalf. The CGImage object's job is tie together these different objects into a single entity that the computer can draw on a CGContext.

The first important aspect of the image maintained by a CGImage object is its geometry. For a rectangular array of color samples, or pixels, that means that the CGImage keeps track of how many pixels high and how many pixels wide the image is. Because this is working with pixels, a discrete valued entity, CGImage uses integers (more specifically size_t) to represent the height and width of an image.

All of the color samples in the pixels of a CGImage come from a particular color space. The CGImage keeps track of this color space by using an instance of the CGColorSpace opaque data type. The primary job of the color space is to help the computer interpret the values of the pixels. As you will see, however, the color space has a more subtle duty in that it defines how many color components each pixel in the color should have.

A CGImage also needs some means of getting at the data structures that store the actual pixel information. In this task, the CGImage enters a partnership with the code that created it. The CGImage doesn't own any of the image data itself. Instead, it works with an opaque type called the CGDataProvider. A CGDataProvider is simply an object that knows how to supply a CGImage instance with pixel data. Some CGDataProviders own the data they pull pixels from. Others allow your application to maintain the image data. Altogether, these different data providers give you a lot of flexibility in locating, storing, and working with image data.

Quartz offers even more flexibility when it comes to the pixel data itself. The simplest way to store color samples is as ordered n-tuples. The number of values in each "tuple" is determined by the color space and whether or not the image contains an alpha channel. A grayscale image with no alpha would use a single value in each "tuple" (a single value for each pixel). An RGB image with an alpha channel would require four values for each pixel. Quartz gives you options in terms of the number and kinds of values that your image specifies for each component in a pixel. It also gives you a bit of wiggle room to select the ordering of the channels within a pixel (in particular the position of the alpha channel relative to the color components of each pixel).

All of this information comes together when your application creates a CGImage. More of this topic will be explored shortly. The true beauty of Quartz, however, is the fact that it encapsulates much of the underlying complexity of images behind a relatively simple API for drawing images. The next topic to cover is the way your application draw images with Quartz 2D, and afterward the question of how to create images will be revisited.

What about NSImage?

Cocoa contains a class known as NSImage. Although both CGImage and NSImage share the "image" moniker, the conceptual model of an NSImage really doesn't match that of a CGImage. NSImage, however, has some features beyond the functionality available through the CGImage interface. Fortunately, Cocoa developers can take advantage of both NSImage and CGImage within their applications.

To give you some idea of the differences, CGImage can only store one representation of an image, usually a compressed data stream or a pixel map. NSImage, in contrast, can store arbitrarily many representations of the same image. A single NSImage might contain the same graphic at a number of different resolutions or in a number of different color spaces. When you ask the computer to draw an NSImage, the system will decide which of the representations it will draw based on the characteristics of the destination device.

Another interesting difference is that your application can change the image stored in an NSImage by using the lockFocus method of an NSImage object and then drawing a new graphic. In contrast, once you've created a CGImage, the contents of that image are considered immutable and should not be changed.

Finally, an NSImage can also represent metafile contents; that is, an NSImage can be used to store and draw a PDF document. As we've mentioned, however, CGImage is strictly for working with pixel-based images.

For these and other reasons it would not be prudent to consider CGImage and NSImage to be equivalent classes. NSImage is a very rich class, and to do it justice would require quite a bit more space that we have here. We recommend that you look at the Cocoa documentation and Apple's sample code if you want to explore the fascinating behavior of the NSImage class.





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