Selectively Focusing on an Image
Focus on a part of an image by applying Gaussian blur and gradient masks.
Overview
You can selectively blur areas of an image using maskedVariableBlur() filter.
[Image]
You specify the region to blur by applying a mask image; the shape and values of the mask image determine the location and strength of the blurring. Creating this effect involves the following steps:
To focus on a strip across the image, create two linear gradients representing the portions of the image to blur.
To focus on a circular region in the image, create a radial gradient centered on the region to keep sharp.
Composite the gradients into a mask.
Apply Core Image’s maskedVariableBlur() filter to the original image, inputting the created mask.
Focusing on a Strip of the Image
You can build your mask in any shape, but the general strategy remains the same: leave the mask transparent where you want the original image to stay sharp and focused. This section covers focusing on a horizontal strip.
To build a mask that leaves out a stripe, create linear gradients from a single color, such as green or gray. Our goal is to build the mask shown in Figure 2.
[Image]
The linear gradients cause the blur to taper smoothly as it approaches the focused stripe of the image. The Core Image CIFilter named linearGradient() generates filters of the desired color. The linear gradient has four parameters:
point0A CGPoint representing the starting position of the gradient.
point1A CGPoint representing the ending position of the gradient.
color0A CIColor representing the first color to use in the gradient.
color1A CIColor representing the sexond color to use in the gradient.
Compute the start and stop points of the gradient as fractions of the image height, as obtained through extent. For this particular mask and example image, focus on the area near the middle, in the second quarter of the image. Set the linear gradient’s point0 and point1 to reflect the region through which the gradient tapers.
const CGFloat h = inputImage.extent.size.height;
CIFilter<CILinearGradient>* topGradient = CIFilter.linearGradientFilter;
topGradient.point0 = CGPointMake(0, 0.85 * h);
topGradient.color0 = CIColor.greenColor;
topGradient.point1 = CGPointMake(0, 0.6 * h);
topGradient.color1 = [CIColor colorWithRed:0 green:1 blue:0];The lower gradient should complement the upper gradient, so that their combined coverage delineates the entire area to blur. Express the starting inputPoint0 y-value at 0.35 of the image height and taper to 0.6, where the top gradient began. This leaves a gap in the combined mask through which the sharp image will show.
CIFilter<CILinearGradient>* bottomGradient = CIFilter.linearGradientFilter;
bottomGradient.point0 = CGPointMake(0, 0.35 * h);
bottomGradient.color0 = CIColor.greenColor;
bottomGradient.point1 = CGPointMake(0, 0.6 * h);
bottomGradient.color1 = [CIColor colorWithRed:0 green:1 blue:0 alpha:0];Creating a Mask by Compositing Linear Gradients
To create a mask that dilineates where and how strong a blur to apply, combine the two linear gradients.
[Image]
Since the gradients themselves are CIFilter objects, compositing them is as simple as concatenating their filter outputs to a compositing filter. Use the built-in CIFilter named additionCompositing() to composite two images additively.
CIFilter<CICompositeOperation> *gradientMask = CIFilter.additionCompositingFilter
gradientMask.inputImage = topGradient.outputImage;
gradientMask.backgroundImage = bottomGradient.outputImage;The resulting mask is now ready to be applied as part of the maskedVariableBlur() filter.
Focusing on a Circular Region
In order to focus on a circular region of an image, you can create a Core Image radialGradient() filter.
The filter takes four parameters:
- center
A CGPoint representing the center of the effect as x and y coordinates.
- color0
A CIColor representing the first color to use in the gradient.
- color1
A CIColor representing the second color to use in the gradient.
- radius0
A
floatrepresenting the radius of the starting circle to use in the gradient.- radius1
A
floatrepresenting the radius of the ending circle to use in the gradient.
Set the
centerto a CGPoint pointing to the center of the region you want to leave unblurred.Set the
radius0to a fraction of the image’s dimension, like0.2*hin this example. You can tweak this parameter to determine the size of the sharp region.Set the
radius1to a larger fraction of the image’s dimension, like0.3*hin this example. Tweaking this parameter changes the extent of the blur’s tapering effect; a larger value makes the blur more gradual, whereas a smaller value makes the image transition more abruptly from sharp (atinputRadius0) to blur (atinputRadius1).As with the linear gradients, set
color0to transparency, andcolor1to a solid opaque color, to indicate the blur’s gradation from nonexistent to full.
CIFilter<CIRadialGradient> *radialMask = CIFilter.radialGradientFilter;
radialMask.center = CGPointMake(0.55 * w, 0.6 * h);
radialMask.radius0 = 0.2 * h;
radialMask.radius1 = 0.3 * h;
radialMask.color0 = [CIColor colorWithRed:0 green:1 blue:0 alpha:0];
radialMask.color1 = [CIColor colorWithRed:0 green:1 blue:0 alpha:1];This yields a circular mask to use with the maskedVariableBlur() filter.
[Image]
Masking the Blurred Image to Apply Selective Focus
The final step is applying your choice of mask with the input image. The maskedVariableBlur() built-in CIFilter accomplishes this task with the following input parameters:
inputImageSet to the original, unprocessed CIImage.
radiusA float representing the area of effect.
maskAn image that masks an area on the input image with the type CIImage
CIFilter<CIMaskedVariableBlur> *maskedVariableBlur = CIFilter.maskedVariableBlurFilter;
maskedVariableBlur.inputImage = inputImage;
maskedVariableBlur.mask = radialMask.outputImage;
maskedVariableBlur.radius = 10;
CIImage *selectivelyFocusedCIImage = maskedVariableBlur.outputImage;The resulting image shows the original image with portions blurred out according to the mask applied. The linear gradient mask results in an output image focused on a strip, and the radial gradient mask results in an output image focused on a circular region.
[Image]
[Image]