Skip to content

Instantly share code, notes, and snippets.

@mxcl
Created February 8, 2018 18:23
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mxcl/76f40027b1ef515e4e6b41292b54fe92 to your computer and use it in GitHub Desktop.
Save mxcl/76f40027b1ef515e4e6b41292b54fe92 to your computer and use it in GitHub Desktop.
extension UIImage {
func blurred(radius: CGFloat) -> UIImage {
let ciContext = CIContext(options: nil)
guard let cgImage = cgImage else { return self }
let inputImage = CIImage(cgImage: cgImage)
guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
ciFilter.setValue(radius, forKey: "inputRadius")
guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
return UIImage(cgImage: cgImage2)
}
}
@krishnastvSMSC
Copy link

Its took 200% of CPU, its very huge and UIThread is blocking, any other solution for this.
Thank you

@victorengel
Copy link

The documentation says CIContext() is very expensive. Do that once in your app and use the variable throughout the app.

@semyaniv
Copy link

semyaniv commented Nov 20, 2020

extension DispatchQueue {
    static func background(_ task: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
        global(qos: .background).async {
            task?()
            if let completion = completion {
                main.async {
                    completion()
                }
            }
        }
    }
    
    static func userInitiated(_ task: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
        global(qos: .userInitiated).async {
            task?()
            if let completion = completion {
                main.async {
                    completion()
                }
            }
        }
    }
}

extension UIImage {
    func blurred(radius: CGFloat, completion: ((UIImage?) -> Void)?) {
        var image: UIImage?
        DispatchQueue.background {
            let ciContext = CIContext(options: nil)
            guard let cgImage = self.cgImage else {
                completion?(nil)
                return
            }
            let inputImage = CIImage(cgImage: cgImage)
            guard let ciFilter = CIFilter(name: "CIGaussianBlur") else {
                completion?(nil)
                return
            }
            ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
            ciFilter.setValue(radius, forKey: "inputRadius")
            guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else {
                completion?(nil)
                return
            }
            guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else {
                completion?(nil)
                return
            }
            image = UIImage(cgImage: cgImage2)
        } completion: {
            completion?(image)
        }
    }
}

Usage:

backgroundImage.image?.blurred(radius: 7.0, completion: { [weak self] image in
                self?.backgroundImage.image = image
            })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment