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:

enter image description here

After:

enter image description here


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