How to add a blur mask with a custom shape above a dynamic camera view in Swift?

后端 未结 2 721
孤城傲影
孤城傲影 2021-02-06 13:32

I am using Swift to develop an iOS application with a camera feature, and it requires a blur layer above the camera view with a hole in the middle like the image shown below.

2条回答
  •  轮回少年
    2021-02-06 14:11

    This question asked a long time a go but I cannot see any useful answer that's why I'll answer it maybe it help others.

    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:

    1. 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")
      
    2. 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)
      }
    }
    

    Happy coding...

提交回复
热议问题