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