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: