-
CIFilter
is a mutable object that represents an effect. A filter object has at least one input parameter and produces an output image. -
CIImage
is an immutable object that represents an image. You can synthesize image data or provide it from a file or the output of anotherCIFilter
object. -
CIContext
is an object through which Core Image draws the results produced by a filter. A Core Image context can be based on the CPU or the GPU.
The basics of applying a filter to an image
CIContext *context = [CIContext contextWithOptions:nil]; // 1 |
CIImage *image = [CIImage imageWithContentsOfURL:myURL]; // 2 |
CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"]; // 3 |
[filter setValue:image forKey:kCIInputImgeKey]; |
[filter setValue:[NSNumber numberWithFloat:0.8f] forKey:@"InputIntensity"]; |
CIImage *result = [filter valueForKey:kCIOutputImageKey]; // 4 |
CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]; |
Data Type | Object | Description |
---|---|---|
Strings | | Used for such things as display names |
Floating-point values | | Scalar values such as intensity levels and radii |
Vectors | | Specify positions, areas, and color values; can have 2, 3, or 4 elements, each of which is a floating-point number |
Colors | | Contain color values and a color space in which to interpret the values |
Images | | Lightweight objects that specify image “recipes” |
Transforms | | An affine transformation to apply to an image |
Creating a Core Image Context
Context | Renderer | Supported Platform |
---|---|---|
CPU or GPU | iOS | |
| CPU or GPU | OS X |
| GPU | iOS |
| GPU | OS X |
creating a Core Image Context on iOS When You Don’t Need Real-Time Performance
you can create a CIContext
object as follows:
CIContext *context = [CIContext contextWithOptions:nil]; |
Creating a Core Image Context on iOS When You Need Real-Time Performanc
myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; |
Creating a CIContext on iOS for real-time performance
NSMutableDictionary *options = [[NSMutableDictionary alloc] init]; |
[options setObject: [NSNull null] forKey: kCIContextWorkingColorSpace]; |
myContext = [CIContext contextWithEAGLContext:myEAGLContext options:options]; |
Creating a CIImage Object
Image source | Methods | Platform |
---|---|---|
URL | iOS, OS X | |
Quartz 2D image ( | iOS, OS X | |
Bitmap data | iOS, OS X | |
Encoded data (an image in memory) | iOS, OS X | |
| | iOS, OS X |
OpenGL texture | OS X, iOS 6.0 and later | |
| | iOS |
| | OS X |
| | OS X |
Quartz 2D layer ( | | OS X |
| | OS X |
Except where noted, iOS methods are available starting with iOS v5.0. |
Creating a CIFilter Object and Setting Values
ThefilterWithName:
method creates a filter whose type is specified by the
name
argument.Defaults are set for you on iOS but not on OS X.
inputKeys
. hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];
[hueAdjust setValue: myCIImage forKey: @"inputImage"]; |
[hueAdjust setValue: [NSNumber numberWithFloat: 2.094] |
forKey: @"inputAngle"]; |
hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"] keysAndValues: |
@"inputImage",myCIImage, |
@"inputAngle, [NSNumber numberWithFloat: 2.094], |
nil]; |
Getting the Output Image
You get the output image by retrieving the value for the outputImage
key:
CIImage *result = [hueAdjust valueForKey: @"outputImage"]; |
Rendering the Resulting Output Image
Method | Use |
---|---|
Renders a region of an image to a rectangle in the context destination. On iOS, this method renders only to a On OS X, the dimensions of the destination rectangle are in points if the | |
Create a Quartz 2D image from a region of a | |
Renders a | |
| Creates a |
Renders the |
[myContext drawImage:result inRect:destinationRect fromRect:contextRect];
Maintaining Thread Safety
CIContext
and CIImage
objects are immutable, which means each can be shared safely among threads. Multiple threads can use the same GPU or CPU CIContext
object to render CIImage
objects. However, this is not the case for CIFilter
objects, which are mutable. A CIFilter
object cannot be shared safely among threads. If your app is multithreaded, each thread must create its own CIFilter
objects. Otherwise, your app could behave unexpectedly.
Chaining Filters
Creating, setting up, and applying a gloom filter
gloom = [CIFilter filterWithName:@"CIGloom"]; |
[gloom setDefaults]; // 1 |
[gloom setValue: result forKey: @"inputImage"]; |
[gloom setValue: [NSNumber numberWithFloat: 25] |
forKey: @"inputRadius"]; // 2 |
[gloom setValue: [NSNumber numberWithFloat: 0.75] |
forKey: @"inputIntensity"]; // 3 |
result = [gloom valueForKey: @"outputImage"]; |
Detecting Faces
Creating a face detector
CIContext *context = [CIContext contextWithOptions:nil]; // 1 |
NSDictionary *opts = [NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh |
forKey:CIDetectorAccuracy]; // 2 |
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace |
context:context |
options:opts]; // 3 |
opts = [NSDictionary dictionaryWithObject: |
[[myImage properties] valueForKey:kCGImagePropertyOrientation; |
forKey:CIDetectorImageOrientation]]; // 4 |
NSArray *features = [detector featuresInImage:myImage |
options:opts]; // 5 |
Examining face feature bounds
for (CIFaceFeature *f in features) |
{ |
NSLog(NSStringFromRect(f.bounds)); |
|
if (f.hasLeftEyePosition) |
printf("Left eye %g %g\n", f.leftEyePosition.x. |
f.leftEyePosition.y); |
if (f.hasRightEyePosition) |
printf("Right eye %g %g\n", f.rightEyePosition.x. |
f.rightEyePosition.y); |
if (f.hasmouthPosition) |
printf("Mouth %g %g\n", f.mouthPosition.x. |
f.mouthPosition.y); |
} |