Search code examples
iosswiftuiimagegaussianblur

Applying CIGaussianBlur to UIImage not working properly


I want a blur effect to UIImage as slider value changes.

I am using the CIGaussianBlur filter to blur the image.

The code is as follows

func applyBlurFilter(aCIImage: CIImage, val: CGFloat) -> UIImage {
    let clampFilter = CIFilter(name: "CIAffineClamp")
    clampFilter?.setDefaults()
    clampFilter?.setValue(aCIImage, forKey: kCIInputImageKey)

    let blurFilter = CIFilter(name: "CIGaussianBlur")
    blurFilter?.setValue(clampFilter?.outputImage, forKey: kCIInputImageKey)
    blurFilter?.setValue(val, forKey: kCIInputRadiusKey)

    let rect = aCIImage.extent
    if let output = blurFilter?.outputImage {
        if let cgimg = self.context.createCGImage(output, from: rect) {
            let processedImage = UIImage(cgImage: cgimg)
            return processedImage
        }
    }
    return image ?? self.image
}

Note: I've also tried the below code using CICrop filter

func applyBlurFilter(beginImage: CIImage, value: Float) -> UIImage? {
    let currentFilter = CIFilter(name: "CIGaussianBlur")
    currentFilter?.setValue(beginImage, forKey: kCIInputImageKey)
    currentFilter?.setValue(value, forKey: kCIInputRadiusKey)

    let cropFilter = CIFilter(name: "CICrop")
    cropFilter?.setValue(currentFilter!.outputImage, forKey: kCIInputImageKey)
    cropFilter?.setValue(CIVector(cgRect: beginImage!.extent), forKey: "inputRectangle")

    let output = cropFilter?.outputImage
    let context = CIContext(options: nil)
    let cgimg = self.context.createCGImage(output!, from: beginImage!.extent)
    let processedImage = UIImage(cgImage: cgimg!)
    return processedImage
}

The code works perfectly with some images, but with bigger images, while applying the blur filter to the image, the image's right edges get transparent which I don't want.

Note: I am running this on device

What am I doing wrong here, I have no idea

The image whose right edge gets transparant

Result after applying GaussianBlur to the above image

Thanks!!


Solution

  • Well, you're doing something wrong somewhere. The absolute best advice I can give you in your career is to create a small test project to experiment when you have such an issue - I've done this for 15 years in the Apple world, and its been of enormous help.

    I created a project here so you don't have to (this time). I downloaded the image, placed it in an ImageView, and it looked perfect (as expected). I then used your code (except I had to create a context, and guess at radius values, then ran it. Image looks perfect with a blur of 0, 5, 10, and 25.

    Obviously the issue is something else you are doing. What I suggest is that you keep adding to the test project until you can find what step is the problem (context? other image processing?)

    This is the entirety of my code:

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
            let im1 = UIImage(named: "Image.jpg")!
            let cim = CIImage(image: im1)!
            let im2 = applyBlurFilter(aCIImage: cim, val: 25)
    
            let iv = UIImageView(image: im2)
            iv.contentMode = .scaleToFill
    
            self.view.addSubview(iv)
        }
    
        func applyBlurFilter(aCIImage: CIImage, val: CGFloat) -> UIImage {
            let clampFilter = CIFilter(name: "CIAffineClamp")
            clampFilter?.setDefaults()
            clampFilter?.setValue(aCIImage, forKey: kCIInputImageKey)
    
            let blurFilter = CIFilter(name: "CIGaussianBlur")
            blurFilter?.setValue(clampFilter?.outputImage, forKey: kCIInputImageKey)
            blurFilter?.setValue(val, forKey: kCIInputRadiusKey)
    
            let rect = aCIImage.extent
            if let output = blurFilter?.outputImage {
                let context = CIContext(options: nil)
                if let cgimg = context.createCGImage(output, from: rect) {
                    let processedImage = UIImage(cgImage: cgimg)
                    return processedImage
                }
            }
            fatalError()
        }
    
    }