Tilt-shift
A tilt-shift effect can be used to simulate a miniature scene:
QuartzComposer
Using QuartzComposer1 we can build a filter chain to apply this effect and play around with it.
As described in the CoreImage Documentation the first step is to setup a blur filter. Since the blur filter makes the image slightly larger, we need to crop it back to the original size.
The gradient mask is built by combining two linear gradients and is then used to blend the blurred image with the original image. Note that we need to crop the gradients to the correct size since the output image from CIGradientFilter has infinite size.
Download the QuartzComposer composition
CoreImage
This same filter chain can be implemented using CoreImage:
- (CIImage *)outputImage { CGRect cropRect = self.inputImage.extent; CGFloat height = cropRect.size.height; CIFilter *blur = [CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:@"inputImage", self.inputImage, @"inputRadius", @(self.inputRadius), nil]; blur = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", blur.outputImage, @"inputRectangle", [CIVector vectorWithCGRect:cropRect], nil]; CIFilter *topGradient = [CIFilter filterWithName:@"CILinearGradient" keysAndValues:@"inputPoint0", [CIVector vectorWithX:0 Y:(self.inputTop * height)], @"inputColor0", [CIColor colorWithRed:0 green:1 blue:0 alpha:1], @"inputPoint1", [CIVector vectorWithX:0 Y:(self.inputCenter * height)], @"inputColor1", [CIColor colorWithRed:0 green:1 blue:0 alpha:0], nil]; CIFilter *bottomGradient = [CIFilter filterWithName:@"CILinearGradient" keysAndValues:@"inputPoint0", [CIVector vectorWithX:0 Y:(self.inputBottom * height)], @"inputColor0", [CIColor colorWithRed:0 green:1 blue:0 alpha:1], @"inputPoint1", [CIVector vectorWithX:0 Y:(self.inputCenter * height)], @"inputColor1", [CIColor colorWithRed:0 green:1 blue:0 alpha:0], nil]; topGradient = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", topGradient.outputImage, @"inputRectangle", [CIVector vectorWithCGRect:cropRect], nil]; bottomGradient = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", bottomGradient.outputImage, @"inputRectangle", [CIVector vectorWithCGRect:cropRect], nil]; CIFilter *gradients = [CIFilter filterWithName:@"CIAdditionCompositing" keysAndValues:@"inputImage", topGradient.outputImage, @"inputBackgroundImage", bottomGradient.outputImage, nil]; CIFilter *tiltShift = [CIFilter filterWithName:@"CIBlendWithMask" keysAndValues:@"inputImage", blur.outputImage, @"inputBackgroundImage", self.inputImage, @"inputMaskImage", gradients.outputImage, nil]; return tiltShift.outputImage; }
The full source code for the TiltShiftFilter can be found at https://gist.github.com/4327330.
From here on we can easily modify this. Instead of having the gradients along the Y-axis we could pass in vectors to control the direction of the gradients and have vertical or diagonal fields in focus. Another option would be to use a CIRadialGradient
instead of two linear gradients and have a circular field.
-
You can find QuartzComposer in the Graphics Tools for Xcode package on https://developer.apple.com/downloads ↩
You can contact me on Twitter or at julien@caffeine.lu