Simple Transforms with Core Image

Using transforms with CIImage objects is easier than I thought. Up until recently, I would create a NSAffineTransform and wrap it in an affine transform filter object, pipe the image in and get the result. Here's what that looks like:
CIImage* inputImage; // assume this exists
float factor = 0.5;

CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform"];
[filter setValue:inputImage forKey:@"inputImage"];
NSAffineTransform *trans = [NSAffineTransform transform];
[trans scaleXBy:factor yBy:factor];
[filter setValue:trans forKey:@"inputTransform"];
CIImage * outputImage = [filter valueForKey:@"outputImage"];

This is all very straightforward, but there's an even easier way:
CIImage* inputImage; // assume this exists
float factor = 0.5;

CGAffineTransform trans = CGAffineTransformMakeScale(factor,factor);
CIImage* outputImage = [inputImage imageByApplyingTransform:trans];

How great is that? You can use this with any of the CGAffineTransform functions, some of which are listed here:

The complete list is in CoreGraphics/Headers/CFAffineTransform.h. CoreGraphics itself is in the ApplicationServices framework.

Of course, you're still better off using the CIFilter approach if the transform is one of a stack of changes you're making to an image. In that case, all of the changes will be combined and the final rendering is finished much more quickly.
Design Element
Simple Transforms with Core Image
Posted Mar 14, 2007 — 8 comments below


Steven Canfield — Mar 14, 07 3724

Through the magic of RSS I see that you wrote it as soon as it happened and get the opportunity to tell you that in your second example you've change the name of the scale factor to "scaleFactor" in the declaration but not when you use it later on.

I'm like the editor of your nightmares.

Vickie — Mar 14, 07 3725

I have only ever had success using 'concat' with NSAffineTransform. I find the choice between editing an image or editing the context confusing, I must admit. I don't have any idea what the criteria would be to choose between them.

After you have added all of the desired transformations to the transform object, you call the concat method to apply them to the current context. Calling concat adds your transformations to the CTM of the current graphics context. The modifications stay in effect until you explicitly undo them, as described in “Undoing a Transformation”, or a previous graphics state is restored.

Documentation link

Dave Arter — Mar 14, 07 3726

Am I being stupid, or does the last line in the first example make reference to a non-existant 'transform' object?

TC — Mar 14, 07 3727

Long time lurker and appreciate all your help with Cocoa. In that second example, you changed the float to be called scaleFactor, but when you create the transform you still use the old variable name factor.

Andy Lee — Mar 14, 07 3728

Seems like a good place for some category methods on CIImage -- -imageByScalingByFactor:(float)scaleFactor, and so forth.

Philip Orr — Mar 14, 07 3729

I'm actually just learning about all this from David Gelphman & Bunny Ladens book Programming with Quartz. It's a fantastic book and full of examples. Both Carbon and Cocoa setups are included.

The typos in your examples as pointed out above seem to be exercises. Why do you think these won't work?


Scott Stevenson — Mar 14, 07 3734 Scotty the Leopard

Sorry for the typos, gang. It was late.

David Gelphman — Apr 26, 07 3972

Glad you like the Programming with Quartz book!


Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.

Copyright © Scott Stevenson 2004-2015