iosswiftavfoundationavcapturedeviceuipinchgesturerecognizer

AVCaptureDevice videoZoomFactor Pinch-to-Zoom Rate


I am trying to implement 'Pinch-to-Zoom' feature with AVCaptureDevice in AVFoundation:

 @IBAction func pinchGestureDetected(_ gestureRecognizer: UIPinchGestureRecognizer)  {

    switch gestureRecognizer.state {
    case .began:
        print ("began")
        self.currenZoomFactor = self.videoDevice!.videoZoomFactor
        do {
            try self.videoDevice!.lockForConfiguration()
        } catch let error as NSError {
            NSLog("Could not lock device for configuration: %@", error)
        }

    case .changed:
        print ("changed")

            var zoomValue : CGFloat = ((gestureRecognizer.scale) - 1) + self.currenZoomFactor
            if zoomValue > min(10.00, self.videoDevice!.activeFormat.videoMaxZoomFactor) {
                zoomValue = min(10.00, self.videoDevice!.activeFormat.videoMaxZoomFactor)

            } else if zoomValue < 1.00 {
                zoomValue = 1.00
            }

            self.videoDevice!.videoZoomFactor = sentZoomValue

    case .ended, .cancelled:
        print ("ended/canceld")
        self.videoDevice!.unlockForConfiguration()

    default:
        break
    }

}

Above works fine. However, with above, zoom rate is linear with pinch scale. This makes zooming much slower at higher zoom factors.

How would I obtain accelerated zoom rates at higher zoom factors?


Solution

  • To get accelerated zoom rates, we need some below calculations.

    You can call this utility method from your pinchGestureDetected

    func zoomto(scale: CGFloat, hasBegunToZoom: Bool) {
    
        if hasBegunToZoom {
            initialPinchZoom = captureDevice.videoZoomFactor
        }
        do {
            try captureDevice.lockForConfiguration()
            if scale < 1.0 {
                zoomFactor = initialPinchZoom - pow(captureDevice.activeFormat.videoMaxZoomFactor, 1.0 - scale)
            }
            else {
                zoomFactor = initialPinchZoom + pow(captureDevice.activeFormat.videoMaxZoomFactor, (scale - 1.0f) / 2.0f)
            }
            zoomFactor = min(10.0, zoomFactor)
            zoomFactor = max(1.0, zoomFactor)
            captureDevice.videoZoomFactor = zoomFactor
            captureDevice.unlockForConfiguration()
        } catch let error as NSError {
            NSLog("Could not lock device for configuration: %@", error)
        }
    }
    

    You can call like below

    @IBAction func pinchGestureDetected(_ gestureRecognizer: UIPinchGestureRecognizer)  {
        zoomto(scale: gestureRecognizer.scale, hasBegunToZoom:(gestureRecognizer.state == .began))
    }