Search code examples
iosswiftxcodecore-graphicscifilter

How to combine filters


How can I combine filters for images? For example, I want to use CIColorControls, CINoiseReduction, etc. Is it necessary to create several filters and initialize them? Or is there another way?

var colorControls: CIFilter
var noiseReduction: CIFilter
...

func init() {
   colorControls = CIFilter.init(name: "CIColorControls")!
   noiseReduction = CIFilter.init(name: "CINoiseReduction")!
   ...
}

Solution

  • You can apply filters one by one:

    func filter(image: CIImage) -> CIImage? {
        guard let colorControls = CIFilter(name: "CIColorControls"),
              let noiseReduction = CIFilter(name: "CINoiseReduction") else { return nil }
        colorControls.setValue(image, forKey: kCIInputImageKey)
        ... // add some CIColorControls filter manipulations
        guard let imageWithFirstFilter = colorControls.value(forKey: kCIOutputImageKey) as? CIImage else { return nil }
        noiseReduction.setValue(imageWithFirstFilter, forKey: kCIInputImageKey)
        ... // add some CINoiseReduction filter manipulations
        guard let imageWithBothFilters = noiseReduction.value(forKey: kCIOutputImageKey) as? CIImage else { return nil }
        return imageWithBothFilters
    }
    

    A little different way:

    func apply(_ filter: CIFilter?, for image: CIImage) -> CIImage {
        guard let filter = filter else { return image }
        filter.setValue(image, forKey: kCIInputImageKey)
        guard let filteredImage = filter.value(forKey: kCIOutputImageKey) else { return image }
        return filteredImage
    }
    

    Using:

    image = apply(colorControls, for: image)