Blur specific part of an image (rectangular, circular)?

Add the following Pangesture in view or imageview

UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(imageTaped:)];
[panGesture setMaximumNumberOfTouches:1];
[self.view addGestureRecognizer:panGesture];

The method for blur image

- (void)imageTaped:(UIPanGestureRecognizer *)gestureRecognizer
{

    CIContext *context = [CIContext contextWithOptions:nil];
    CGPoint touchLocation = [gestureRecognizer locationInView:self.imgviewMain];


    CGRect temp=CGRectMake(touchLocation.x-25, ((self.imgviewMain.frame.size.height-50) - touchLocation.y)+25, 50, 50);

    CIImage *inputImage0 = [[CIImage alloc] initWithImage:self.imgviewMain.image];

    CIImage *inputImage = [[CIImage alloc] initWithImage:[UIImage imageWithCGImage:[context createCGImage:inputImage0 fromRect:temp]]];
    CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [blurFilter setDefaults];
    [blurFilter setValue: inputImage forKey: @"inputImage"];
    [blurFilter setValue: [NSNumber numberWithFloat:0.1]
                  forKey:@"inputRadius"];


    CIImage *outputImage = [blurFilter valueForKey: @"outputImage"];
    UIImageView *imgtest=[[UIImageView alloc]init];

    imgtest.image=[UIImage imageWithCGImage:[context createCGImage:outputImage fromRect:outputImage.extent]];



    UIImage *image;

    UIImage *bottomImage = self.imgviewMain.image; 
          image = imgtest.image;    


    CGSize newSize = CGSizeMake(self.imgviewMain.frame.size.width, self.imgviewMain.frame.size.height);
    UIGraphicsBeginImageContext( newSize );

    [bottomImage drawInRect:CGRectMake(0,0,768,1024)];

    CGRect newRect2=CGRectMake(temp.origin.x,((self.imgviewMain.frame.size.height-50) - temp.origin.y), image.size.width, image.size.height);
    image=[self makeRoundedImage:image radius:10];

    [image drawInRect:newRect2 blendMode:kCGBlendModeNormal alpha:0.5];
     UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    self.imgviewMain.image=newImage;
   }

RoundedImage Method

-(UIImage *)makeRoundedImage:(UIImage *) image
                      radius: (float) radius;
{
    CALayer *imageLayer = [CALayer layer];
    imageLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height);
    imageLayer.contents = (id) image.CGImage;

    imageLayer.masksToBounds = YES;
    imageLayer.cornerRadius = radius;

    UIGraphicsBeginImageContext(image.size);
    [imageLayer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return roundedImage;
}

I know I'm bit late for the party but it may help someone else who struggling to get this working.

I've recently needed to implement it and I couldn't find much info on internet about this specific topic ( specially how to get this working when dealing with different UIImageView's scale types such as Scale to Fill, Center and so on). So I've developed a small project that does exactly what you expect.

enter image description here

https://github.com/pauloubuntu/ios-blur-pan-gesture


enter image description here

Just set your UIImageView property name as "imageView" and add the following four methods with the same sequence in your implementation file. Also, set your ImageView Mode to 'Redraw'. Add UIImage Category for the blur effect as given or use any custom class, it will work for you.

Method 1 - Cropping the Image

#pragma mark - Cropping the Image 

- (UIImage *)croppIngimageByImageName:(UIImage *)imageToCrop toRect:(CGRect)rect{

    CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);    
    UIImage *cropped = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return cropped;   


}

Method 2 - Merge the two Images

#pragma mark - Marge two Images 

- (UIImage *) addImageToImage:(UIImage *)img withImage2:(UIImage *)img2 andRect:(CGRect)cropRect{

    CGSize size = CGSizeMake(imageView.image.size.width, imageView.image.size.height);
    UIGraphicsBeginImageContext(size);

    CGPoint pointImg1 = CGPointMake(0,0);
    [img drawAtPoint:pointImg1]; 

    CGPoint pointImg2 = cropRect.origin;
    [img2 drawAtPoint: pointImg2];

    UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

Method 3 - RoundRect the Image

#pragma mark - RoundRect the Image

- (UIImage *)roundedRectImageFromImage:(UIImage *)image withRadious:(CGFloat)radious {

    if(radious == 0.0f)
        return image;

    if( image != nil) {

        CGFloat imageWidth = image.size.width;
        CGFloat imageHeight = image.size.height;

        CGRect rect = CGRectMake(0.0f, 0.0f, imageWidth, imageHeight);
        UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
        const CGFloat scale = window.screen.scale;
        UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);

        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextBeginPath(context);
        CGContextSaveGState(context);
        CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
        CGContextScaleCTM (context, radious, radious);

        CGFloat rectWidth = CGRectGetWidth (rect)/radious;
        CGFloat rectHeight = CGRectGetHeight (rect)/radious;

        CGContextMoveToPoint(context, rectWidth, rectHeight/2.0f);
        CGContextAddArcToPoint(context, rectWidth, rectHeight, rectWidth/2.0f, rectHeight, radious);
        CGContextAddArcToPoint(context, 0.0f, rectHeight, 0.0f, rectHeight/2.0f, radious);
        CGContextAddArcToPoint(context, 0.0f, 0.0f, rectWidth/2.0f, 0.0f, radious);
        CGContextAddArcToPoint(context, rectWidth, 0.0f, rectWidth, rectHeight/2.0f, radious);
        CGContextRestoreGState(context);
        CGContextClosePath(context);
        CGContextClip(context);

        [image drawInRect:CGRectMake(0.0f, 0.0f, imageWidth, imageHeight)];

        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return newImage;
    } 
    return nil;
}

Method 4 - Touch Move

#pragma mark - Touch Methods

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {


    UIImage *croppedImg = nil;

    UITouch *touch = [touches anyObject];
    CGPoint currentPoint = [touch locationInView:self.imageView];

    double ratioW=imageView.image.size.width/imageView.frame.size.width ;

    double ratioH=imageView.image.size.height/imageView.frame.size.height;

    currentPoint.x *= ratioW;
    currentPoint.y *= ratioH;

    double circleSizeW = 30 * ratioW;
    double circleSizeH = 30 * ratioH;


    currentPoint.x = (currentPoint.x - circleSizeW/2<0)? 0 : currentPoint.x - circleSizeW/2;
    currentPoint.y = (currentPoint.y - circleSizeH/2<0)? 0 : currentPoint.y - circleSizeH/2;


    CGRect cropRect = CGRectMake(currentPoint.x , currentPoint.y,   circleSizeW,  circleSizeH);

    NSLog(@"x %0.0f, y %0.0f, width %0.0f, height %0.0f", cropRect.origin.x, cropRect.origin.y,   cropRect.size.width,  cropRect.size.height );

    croppedImg = [self croppIngimageByImageName:self.imageView.image toRect:cropRect];

    // Blur Effect 
    croppedImg = [croppedImg imageWithGaussianBlur9];

    // Contrast Effect 
    // croppedImg = [croppedImg imageWithContrast:50];



    croppedImg = [self roundedRectImageFromImage:croppedImg withRadious:4]; 

    imageView.image = [self addImageToImage:imageView.image withImage2:croppedImg andRect:cropRect];  
} 

UIImage Category Class

UIImage+ImageBlur.h

#import <UIKit/UIKit.h>

@interface UIImage (ImageBlur)

- (UIImage *)imageWithGaussianBlur9;

@end

UIImage+ImageBlur.m

#import "UIImage+ImageBlur.h"

@implementation UIImage (ImageBlur)

- (UIImage *)imageWithGaussianBlur9 {
    float weight[5] = {0.1270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162};
    // Blur horizontally
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height) blendMode:kCGBlendModeNormal alpha:weight[0]];
    for (int x = 1; x < 5; ++x) {
        [self drawInRect:CGRectMake(x, 0, self.size.width, self.size.height) blendMode:kCGBlendModeNormal alpha:weight[x]];
        [self drawInRect:CGRectMake(-x, 0, self.size.width, self.size.height) blendMode:kCGBlendModeNormal alpha:weight[x]];
    }
    UIImage *horizBlurredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    // Blur vertically
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [horizBlurredImage drawInRect:CGRectMake(0, 0, self.size.width, self.size.height) blendMode:kCGBlendModeNormal alpha:weight[0]];
    for (int y = 1; y < 5; ++y) {
        [horizBlurredImage drawInRect:CGRectMake(0, y, self.size.width, self.size.height) blendMode:kCGBlendModeNormal alpha:weight[y]];
        [horizBlurredImage drawInRect:CGRectMake(0, -y, self.size.width, self.size.height) blendMode:kCGBlendModeNormal alpha:weight[y]];
    }
    UIImage *blurredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //
    return blurredImage;
}

@end

happy coding....