Apply CIGaussianBlur only to a small part of an image
Asked Answered
A

4

6

I need to apply a CIGaussianBlur filter only on a small part of an image like this:

enter image description here

Is there any way to do this? For example when I apply the filter perhaps I think that I have to specify the dimension of the filter (someone like CGRectMake).

var imageToBlur = CIImage(image: coro.logo)
var blurfilter = CIFilter(name: "CIGaussianBlur")
blurfilter.setValue(imageToBlur, forKey: "inputImage")
blurfilter.setValue(2, forKey: "inputRadius")
var resultImage = blurfilter.valueForKey("outputImage") as! CIImage
var blurredImage = UIImage(CIImage: resultImage)
self.immagineCoro.image = blurredImage
Argumentative answered 26/8, 2015 at 9:56 Comment(1)
doesn't CIFilter have an extents rectangle property?Cauvery
B
3

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
    }
Briton answered 25/10, 2015 at 9:45 Comment(3)
Can you post an objective c variant of the same ?Woodcock
@Nil - (UIImage*)getBluredImageFromImage:(UIImage*)image forRect:(CGRect)rect { CIContext* context = [CIContext contextWithOptions:nil]; CIImage* inputImage = [CIImage imageWithCGImage:image.CGImage]; CIFilter* filter = [CIFilter filterWithName:@"CIGaussianBlur"]; [filter setValue:inputImage forKey:kCIInputImageKey]; [filter setValue:@(70) forKey:kCIInputRadiusKey]; CIImage* outputImage = [filter outputImage];Briton
CGImageRef cgImage; if (outputImage) cgImage = [context createCGImage:outputImage fromRect:rect]; if (cgImage) return [UIImage imageWithCGImage:cgImage]; return nil; } Try to copy/past it to xCode… It will looks better :)Briton
D
12

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

Drillstock answered 25/10, 2015 at 15:10 Comment(0)
B
3

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
    }
Briton answered 25/10, 2015 at 9:45 Comment(3)
Can you post an objective c variant of the same ?Woodcock
@Nil - (UIImage*)getBluredImageFromImage:(UIImage*)image forRect:(CGRect)rect { CIContext* context = [CIContext contextWithOptions:nil]; CIImage* inputImage = [CIImage imageWithCGImage:image.CGImage]; CIFilter* filter = [CIFilter filterWithName:@"CIGaussianBlur"]; [filter setValue:inputImage forKey:kCIInputImageKey]; [filter setValue:@(70) forKey:kCIInputRadiusKey]; CIImage* outputImage = [filter outputImage];Briton
CGImageRef cgImage; if (outputImage) cgImage = [context createCGImage:outputImage fromRect:rect]; if (cgImage) return [UIImage imageWithCGImage:cgImage]; return nil; } Try to copy/past it to xCode… It will looks better :)Briton
G
3

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)
}
Gehlbach answered 17/7, 2020 at 6:33 Comment(0)
S
1

edited version for Swift 5+

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)
    
    guard let outputImage = filter?.outputImage,
          let cgImage = context.createCGImage(outputImage, from: rect)
    else {
        return nil
    }
    
    return UIImage(cgImage: cgImage)
}
Shrike answered 26/8, 2020 at 9:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.