Using a Core Image Filter


You've just seen the basic steps an application goes through to use Core Image. Now you'll see some of the details by looking at sample code. This code sample builds and renders the CIImage that applies a Gaussian blur to an image. The results of the Gaussian blur are illustrated in Figure 10.1.

Figure 10.1. The Image Before and After Blurring


In this case Core Image has been asked to take the lovely beach image and apply a Gaussian Blur filter with a radius of 10. This complete code sample is called CoreImageBasics and is a Carbon application that simply displays the blurred image in a window. The portion of the application that generates the blurred image is given in Listing 10.1.

Listing 10.1. Code Using Core Image to Blur an Image

void DrawBlurredImage(CGContextRef outputContext,            const CGRect &viewBounds) {     // Create an autorelease pool to catch autoreleased objects     // from Objective-C     NSAutoreleasePool *autoreleasePool =             [[NSAutoreleasePool alloc] init];     // Obtain the source image and create a CIImage with that     // set of pixels     CGImageRef sourceCGImage = CreateSourceImage();     CIImage *sourceCIImage = [CIImage imageWithCGImage: sourceCGImage];     CGRect sourceBounds = CGRectMake(0, 0,                    CGImageGetWidth(sourceCGImage),                    CGImageGetHeight(sourceCGImage));     // We've done with the source image.     CFRelease(sourceCGImage);     sourceCGImage = NULL;     // Create a filter and assign the parameters     CIFilter *gaussianBlur =             [CIFilter filterWithName: @"CIGaussianBlur"];     [gaussianBlur setValue: sourceCIImage forKey: @"inputImage"];     [gaussianBlur setValue: [NSNumber numberWithFloat: 10]                    forKey: @"inputRadius"];     // extract the resulting CIImage from the blur filter.     CIImage *result = [gaussianBlur valueForKey: @"outputImage"];     // Create a CIContext on our graphics context and     // render the image into it.     CIContext *outputCIContext = [CIContext             contextWithCGContext: outputContext options: NULL];     [outputCIContext drawImage: result                    inRect: viewBounds fromRect: sourceBounds];     // release the autorelase pool     [autoreleasePool release];     autoreleasePool = NULL; } 

The code begins by creating an NSAutoreleasePool. This is a small concession that Carbon applications must make when working with Objective-C APIs. The autorelease pool catches objects that your application, or the operating system, might autorelease in the course of its run. If this code were running inside of a Cocoa application, the autorelease pool would be part of the main application event loop. The source code releases the autorelease pool at the bottom, which frees any autoreleased objects.

For more information on using Objective-C methods from Carbon applications, please visit the Carbon-Cocoa integration guide at

http://developer.apple.com/documentation/Cocoa/Conceptual/CarbonCocoaDoc/Articles/CocoaUIInCarbon.html

The code calls an external routine, CreateSourceImage, that loads the beach scene from a file in the application's resources using Image I/O (see Chapter 9, "Importing and Exporting Images"). The code uses this CGImage to create a CIImage. The CIImage that it creates has a single instruction which is, essentially, "collect these specific pixels." If you were to draw this CIImage, it would do little more than draw the pixels of the CGImage.

The code extracts a bounding rectangle for the CGImage as well, and at that point we're done with it. By the rules of object ownership, if the CIImage wants the CGImage any more, it should have retained it, but you're done with the image now, so you release it.

The image program has been started and you're ready to filter the image. You create the CIFilter using the filterWithName method of that class. Filters are also organized into categories. Using the methods of the CIFilter class, your application can obtain lists of categories and lists of all the filters in a particular category. The built-in categories are listed in the CIFilter.h header file. You can use these routines to allow your users to create the filter of their choice.

Next, the code sets the parameters for the blur filter. In writing the sample code, the input parameters for the filter in the documentation were looked up.

A CIFilter also includes methods that let you ask them for a list of the input parameter keys for the filter. This might be helpful if your application wants to generate a custom UI to let the user specify values for the input parameters. The Core Image Fun House sample code mentioned earlier in the chapter demonstrates how to do this.

In this case, the Gaussian blur filter accepts two parameters, an image (the image to blur) and the blur radius. Blur radius is simply a value that indicates how blurry you want the image to be. CIFilters use an Objective-C programming technique called "key-value coding" to change the input parameters of the filter. Essentially this means that your code sets the input parameters by name. The method setValue:forKey: is used here to establish the CIImage that is the input to the filter, as well as the inputRadius for the blur filter.

Key-Value Coding is a popular technique for several of the Objective-C based technologies that Apple provides. The basic idea behind key-value coding is that you can access the fields of an object by name rather than having to add accessor methods to your class for every field. If you would like to learn more about key-value coding in Objective-C and Java, please visit the following documentation:

http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/index.html


At this point, you are ready to construct the CIImage that contains both drawing commands. To do this, you ask the filter for its outputImage property, again using the techniques of key-value coding. This property combines the input parameters and generates a new CIImage. This new CIImage knows how to draw the results of applying that filter.

The final step of the sample draws the results of the filtering step into the CGContext that was passed to the routine as a parameter. To draw on the CGContext you have to first create a CIContext that the computer will execute the CIImage's image program in. You can use the contextWithCGContext: method of CIContext to create an appropriate drawing environment and then ask that environment to draw the CIImage.

This sample code runs through all these steps every time the computer wants to draw the image. Ideally, however, the code would cache the CIImage retrieved from the Gaussian blur filter and reuse it to draw the same image each time it was asked to.




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