ioscore-imageuivisualeffectview

How to use Core Image APIs to blur a image looks just like the `UIVisualView` effect?


The first image below is the original image.
The second image is a blurred image implemented using Core Image API.
The third image is a blurred image implemented using UIVisualView.

It's obvious that the Core Image blurred the image and shrunk it. The bigger radius resulted in a wider white border.

Question: How to use core image make a visual effect just like the UIVisualView effect.

At least, how to use Core Image to blur an image without the white border.

func blur(image: UIImage, withRadius radius: Float) -> UIImage {
    let context = CIContext(options: nil)
    let image = CIImage(image: image)

    let filter = CIFilter(name: "CIGaussianBlur")
    filter?.setValue(image, forKey: kCIInputImageKey)
    filter?.setValue(radius, forKey: "inputRadius")
    let result = filter?.outputImage
    return UIImage(cgImage: context.createCGImage(result!, from: (result?.extent)!)!)
}

The third image is

func addVisualEffectView() {
    let effectView = UIVisualEffectView(effect: UIBlurEffect(style:.light))
    effectView.frame = originalImageView.bounds // originalImageView is the ImageView represents the original image
    originalImageView.addSubview(effectView)
}

enter image description here enter image description here

enter image description here


Solution

  • You can create an UIImageView and an UIViewVisualEffectView above the image view, then render it to an image, see my approach:

    extension UIImage
    {
        var glass: UIImage?
        {
            let area = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        
            let mainView = UIView(frame: area)
        
            let imageView = UIImageView(image: self)
            imageView.frame = area
        
            let blurEffect = UIBlurEffect(style: .light)
            let blurredEffectView = UIVisualEffectView(effect: blurEffect)
            blurredEffectView.frame = area
        
            mainView.addSubview(imageView)
            mainView.addSubview(blurredEffectView)
        
            let renderer = UIGraphicsImageRenderer(size: size)
            let blurImage = renderer.image { _ in
                mainView.drawHierarchy(in: area, afterScreenUpdates: true)
            }
            return blurImage
        }
    }