Apply CIGaussianBlur only to a small part of an image
The idea is to make a new image from a rect in the source image, blur this new image then composite it back into the source.
I'm making this an extension to UIImage for an easier usage.
extension UIImage {
func getImageFromRect(rect: CGRect) -> UIImage? {
if let cg = self.CGImage,
let mySubimage = CGImageCreateWithImageInRect(cg, rect) {
return UIImage(CGImage: mySubimage)
}
return nil
}
func blurImage(withRadius radius: Double) -> UIImage? {
let inputImage = UIKit.CIImage(CGImage: self.CGImage!)
if let filter = CIFilter(name: "CIGaussianBlur") {
filter.setValue(inputImage, forKey: kCIInputImageKey)
filter.setValue((radius), forKey: kCIInputRadiusKey)
if let blurred = filter.outputImage {
return UIImage(CIImage: blurred)
}
}
return nil
}
func drawImageInRect(inputImage: UIImage, inRect imageRect: CGRect) -> UIImage {
UIGraphicsBeginImageContext(self.size)
self.drawInRect(CGRectMake(0.0, 0.0, self.size.width, self.size.height))
inputImage.drawInRect(imageRect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
func applyBlurInRect(rect: CGRect, withRadius radius: Double) -> UIImage? {
if let subImage = self.getImageFromRect(rect),
let blurredZone = subImage.blurImage(withRadius: radius) {
return self.drawImageInRect(blurredZone, inRect: rect)
}
return nil
}
}
Usage:
// your image
let sourceImage = UIImage(...)
// the rect to blur
let targetZone = CGRectMake(-50, sourceImage.size.height - 220, sourceImage.size.width + 100, 220)
// apply our functions to the source image
if let resultImage = sourceImage.applyBlurInRect(targetZone, withRadius: 6.0) {
// use resultImage
}
Before:
After:
Try to use this
func blurImage(image:UIImage, forRect rect: CGRect) -> UIImage?
{
let context = CIContext(options: nil)
let inputImage = CIImage(CGImage: image.CGImage!)
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue((70.0), forKey: kCIInputRadiusKey)
let outputImage = filter?.outputImage
var cgImage:CGImageRef?
if let asd = outputImage
{
cgImage = context.createCGImage(asd, fromRect: rect)
}
if let cgImageA = cgImage
{
return UIImage(CGImage: cgImageA)
}
return nil
}
Swift: It seems to be an easy process.
// convert UIImage to CIImage
guard let ciImage = imgage.ciImage ?? image.cgImage.map({CIImage(cgImage: $0)}) else {
return
}
// crop out image that needs to be blurred
// be careful about bounds
let imagePartToBlur = ciImage.cropped(to: bounds)
// apply gaussian blur
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(faceImage, forKey: kCIInputImageKey)
filter?.setValue(32, forKey: kCIInputRadiusKey)
let outputImage = filter?.outputImage
// composite the blurred croppedout image to original image and get new image
if let newImageWithBlurredPart = outputImage?.composited(over: ciImage) {
// now get uimage which is ready to use
let cgImage = context.createCGImage(newImageWithBlurredPart, from: ciImage.extent)
let image = UIImage(cgImage: cgImage)
}