Easiest way to apply blur to out of some circular region in image we can applying Gaussian blur and gradient masks. Here Apple has a post on it.
Basically common steps to do this:
Create a mask filter using CIRadialGradient (adjust your circle center here)
guard let radialMask = CIFilter(name:"CIRadialGradient") else {
return nil
}
let h = inputImage.extent.size.height
let w = inputImage.extent.size.width
// Adjust your circular hole position here
let imageCenter = CIVector(x:0.55 * w, y:0.6 * h)
radialMask.setValue(imageCenter, forKey:kCIInputCenterKey)
// Small fraction of the image's dimension (high sharp)
radialMask.setValue(0.2 * h, forKey:"inputRadius0")
// Large fraction of the image's dimension (lower sharp)
radialMask.setValue(0.3 * h, forKey:"inputRadius1")
radialMask.setValue(CIColor(red:0, green:1, blue:0, alpha:0),
forKey:"inputColor0")
radialMask.setValue(CIColor(red:0, green:1, blue:0, alpha:1),
forKey:"inputColor1")
Create CIMaskedVariableBlur to mask blured area
guard let maskedVariableBlur = CIFilter(name:"CIMaskedVariableBlur") else {
return nil
}
// inputImage:- Your original image
maskedVariableBlur.setValue(inputImage, forKey: kCIInputImageKey)
// inputRadiusKey:- Right degree of blur desired
maskedVariableBlur.setValue(10, forKey: kCIInputRadiusKey)
// here we will use result of radialMask filter result image
maskedVariableBlur.setValue(radialMask.outputImage, forKey: "inputMask")
// Get result image
let selectivelyFocusedCIImage = maskedVariableBlur.outputImage
// Convert your result image to UIImage
let resultImage = UIImage(ciImage: selectivelyFocusedCIImage)
Extra:- You can use UIPanGestureRecognizer
to move your circle hole
1- Create gesture recognizer:
lazy var panGesture: UIPanGestureRecognizer = {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handleDrag))
return panGesture
}()
2- Add gesture recognizer to your image view
self.imageView.isUserInteractionEnabled = true
self.imageView.addGestureRecognizer(panGesture)
3- Handle your gesture
var initialCenter = CGPoint()
@objc fileprivate func handleDrag(_ gestureRecognizer: UIPanGestureRecognizer) {
guard gestureRecognizer.view != nil else {return}
let translation = gestureRecognizer.translation(in: imageView.superview)
if gestureRecognizer.state == .began {
// Save the view's original position.
self.initialCenter = CGPoint(x: centerVector.x, y: centerVector.y)
}
// Update the position for the .began, .changed, and .ended states
if gestureRecognizer.state != .cancelled {
// Add the X and Y translation to the view's original position.
let newCenter = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + -translation.y)
self.imageCenter = CIVector.init(cgPoint: newCenter)
// Then apply your filter on gestureRecognizer.state == .end
} else {
// On cancellation, return the piece to its original location.
self.imageCenter = CIVector(x: initialCenter.x, y: initialCenter.y)
}
}