1 Reply
      Latest reply on Feb 5, 2019 4:41 AM by carstengp
      Gargoyle Level 2 Level 2 (70 points)

        In Apple's documentation it says this:


        "This method, though convenient, is inefficient if used multiple times in succession. Achieve better performance by chaining filters without asking for the outputs of individual filters."


        That confuses me though because I don't know how to link them together without getting the output.  For example, this is my method to apply a TiltShift filter, based on the instructions from Apple's docs.  When I perform the gradient filter, I have to take the outputImage of that to pass into the next filter.  What's the right way to be doing this?


            override public var outputImage: CIImage? {
                guard let inputImage = inputImage else {
                    return nil
                let clamped = inputImage.clampedToExtent()
                let blurredImage = clamped.applyingGaussianBlur(sigma: inputRadius)
                var gradientParameters = [
                    "inputPoint0": CIVector(x: 0, y: 0.75 * inputImage.extent.height),
                    "inputColor0": CIColor(red: 0, green: 1, blue: 0, alpha: 1),
                    "inputPoint1": CIVector(x: 0, y: 0.5 * inputImage.extent.height),
                    "inputColor1": CIColor(red: 0, green: 1, blue: 0, alpha: 0)
                guard let gradientImage = ciImage(from: "CILinearGradient", parameters: gradientParameters) else {
                    return nil
                gradientParameters["inputPoint0"] = CIVector(x: 0, y: 0.25 * inputImage.extent.height)
                guard let backgroundGradientImage = ciImage(from: "CILinearGradient", parameters: gradientParameters) else {
                    return nil
                let maskParameters = [
                    kCIInputImageKey: gradientImage,
                    kCIInputBackgroundImageKey: backgroundGradientImage
                guard let maskImage = ciImage(from: "CIAdditionCompositing", parameters: maskParameters) else {
                    return nil
                let combinedParameters = [
                    kCIInputImageKey: blurredImage,
                    kCIInputBackgroundImageKey: clamped,
                    kCIInputMaskImageKey: maskImage
                return ciImage(from: "CIBlendWithMask", parameters: combinedParameters)
            private func ciImage(from filterName: String, parameters: [String: Any]) -> CIImage? {
                guard let filtered = CIFilter(name: filterName, parameters: parameters) else {
                    return nil
                return filtered.outputImage
        • Re: How do you chain CIFilter
          carstengp Level 1 Level 1 (10 points)

          I had to search a bit before understanding what method you were referring to - seems to imageByApplyingFilter? I also find that note quite weird as it does not sound like this convenience method does anything but setting the inputImage and returning outputImage and I would not expect this to trigger any kind of rendering at all