2

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!!

Krima Shah
  • 117
  • 1
  • 8
  • You problem need to set the extent property but I don’t know exactly. Read up on it and experiment. – David H Feb 03 '20 at 12:42
  • Could you try to use `aCIImage.clampedToExtent` as input for the gauss filter? Theoretically it does the same as the `CIAffineClamp`-Filter, but who knows. – Paul Schröder Feb 03 '20 at 14:17
  • @DavidH Thanks for the response! Will look for the solution that you've given – Krima Shah Feb 04 '20 at 03:50
  • @PaulSchröder Thanks for the response! I've also tried using clampedToExtent, but it didn't work for me – Krima Shah Feb 04 '20 at 03:52
  • How big are those "bigger" images you are talking about? Could you maybe post one of them or at least a link. Where have you run your code on a real device or on the simulator? – Paul Schröder Feb 04 '20 at 07:50
  • @PaulSchröder Please check my edited question for the image, the first image is the image using which the blur doesn't work and the second image is the resulting image after applying blur. And I have run my code on a real device – Krima Shah Feb 04 '20 at 09:32
  • Put the image on Dropbox or similar. – David H Feb 04 '20 at 12:30
  • 1
    @DavidH I've given the link to the image in the edited question, please check it out – Krima Shah Feb 04 '20 at 13:13
  • Krima my answer was just upvoted. Really, you should accept it - didn’t it help you? I spent a lot of time to help you. – David H Feb 26 '22 at 13:07

1 Answers1

3

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()
    }

}
David H
  • 40,852
  • 12
  • 92
  • 138
  • Thanks for your help and time! I will look for the point that you've pointed out and will let you know if it works. – Krima Shah Feb 05 '20 at 04:07