Using Filters - CIMaskedVariableBlur

1.3k views Asked by At

I have been gradually getting my head around filters but I can't for the life of me get this to work and there are minimal articles about this specific filter.

I have a mask (png) with a gradient between white and black and an image and I can't get it to blur an image called bg.png. The app crashes out with:

'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key inputMaskImage.'

let mask = CIImage(image: UIImage(named: "mask.png")!)
let context = CIContext()
let filter = CIFilter(name: "CIMaskedVariableBlur")
filter?.setValue(mask, forKey: kCIInputMaskImageKey)
let image = CIImage(image: UIImage(named: "bg.png")!)
filter?.setValue(image, forKey: kCIInputImageKey)
let result = filter?.outputImage!
let cgImage = context.createCGImage(result!, from:(result?.extent)!)
let outputImg = UIImage(cgImage: cgImage!)
bgImage.image = outputImg

I have been playing around with different ways of doing it but all give the same error and I assume it is to do with the mask type?... I have no idea!

2

There are 2 answers

0
AudioBubble On

If you are targeting iOS 8, the key kCIInputMaskImageKey won't work. It's only for iOS 9 or later. But the good news is you can get things to work in iOS 8 by typing in the name of the keys. I usually do this anyways. Here's a function that should work for you:

func applyMaskedVariableBlur(image:UIImage, mask:UIImage) -> UIImage {

    let filter = CIFilter(name: "CIMaskedVariableBlur")

    // convert UIImages to CIImages and set as input

    let ciInput = CIImage(image: image)
    let ciMask = CIImage(image: mask)
    filter?.setValue(ciInput, forKey: "inputImage")
    filter?.setValue(ciMask, forKey: "inputMask")

    // get output CIImage, render as CGImage first to retain proper UIImage scale

    let ciOutput = filter?.outputImage
    let ciContext = CIContext()
    let cgImage = ciContext.createCGImage(ciOutput!, from: (ciOutput?.extent)!)

    return UIImage(cgImage: cgImage!)
}
0
Michael N On

This code crops the image to the extent of the original image:

func applyMaskedVariableBlur(image: UIImage, mask: UIImage) -> UIImage {

    let filter = CIFilter(name: "CIMaskedVariableBlur")

    // convert UIImages to CIImages and set as input

    let ciInput = CIImage(image: image)
    let ciMask = CIImage(image: mask)
    filter?.setValue(ciInput?.clampedToExtent(), forKey: "inputImage")
    filter?.setValue(ciMask, forKey: "inputMask")
    filter?.setValue(20, forKey: "inputRadius")

    // get output CIImage, render as CGImage first to retain proper UIImage scale

    let ciOutput = filter?.outputImage
    let ciContext = CIContext()
    let croppedCi = ciOutput?.cropped(to: ciInput!.extent)
    let cgImage = ciContext.createCGImage(croppedCi!, from: (croppedCi?.extent)!)

    let processedImage = UIImage(cgImage: cgImage!, scale: image.scale, orientation: image.imageOrientation)

    return processedImage
    
}