Search code examples
iosswiftcore-imagecifilter

How to apply CIVignette as if CIImage were square?


I have a 1080x1920 CIImage and wish to apply CIVignette as if the image were square (to mimic a camera lens).

I'm new to CoreImage and am wondering how to temporarily change the extent of my CIImage to 1920x1920. (But I'm not sure if this is needed at all.)

I could copy-paste two narrow slivers of the original image left and right and CICrop afterwards, but this seems hacky.

Any ideas?


Solution

  • You can use a combination of clampedToExtent (which causes the image to repeat its border pixels infinitely) and cropped to make the image square. Then you can apply the vignette and crop the result back to the original extent:

    // "crop" to square, placing the image in the middle
    let longerSize = max(inputImage.extent.width, inputImage.extent.height)
    let xOffset = (longerSize - inputImage.extent.width) / 2.0
    let yOffset = (longerSize - inputImage.extent.height) / 2.0
    let squared = inputImage.clampedToExtent().cropped(to: CGRect(x: -xOffset, y: -yOffset, width: longerSize, height: longerSize))
    
    // apply vignette
    let vignetteFilter = CIFilter(name: "CIVignette")!
    vignetteFilter.setValue(squared, forKey: kCIInputImageKey)
    vignetteFilter.setValue(1.0, forKey: kCIInputIntensityKey)
    vignetteFilter.setValue(1.0, forKey: kCIInputRadiusKey)
    let withVignette = vignetteFilter.outputImage!
    
    // crop back to original extent
    let output = withVignette.cropped(to: inputImage.extent)