捏缩放相机

时间:2015-10-16 22:38:26

标签: ios iphone swift camera zoom

我试图缩小相机,但我遇到了两个问题。首先,它允许用户以太多的方式进行缩放,其次,当我拍摄照片时,它没有采用放大的视图。这是我的捏合函数代码......

func pinch(pinch: UIPinchGestureRecognizer) {
    if let view = cameraView {
        view.transform = CGAffineTransformScale(view.transform,
            pinch.scale, pinch.scale)
            pinch.scale = 1
    }

}

告诉我您是否需要查看更多代码。谢谢!

6 个答案:

答案 0 :(得分:27)

Swift 3.0

let minimumZoom: CGFloat = 1.0
let maximumZoom: CGFloat = 3.0
var lastZoomFactor: CGFloat = 1.0

func pinch(_ pinch: UIPinchGestureRecognizer) {
    guard let device = videoDeviceInput.device else { return }

    // Return zoom value between the minimum and maximum zoom values
    func minMaxZoom(_ factor: CGFloat) -> CGFloat {
        return min(min(max(factor, minimumZoom), maximumZoom), device.activeFormat.videoMaxZoomFactor)
    }

    func update(scale factor: CGFloat) {
        do {
            try device.lockForConfiguration()
            defer { device.unlockForConfiguration() }
            device.videoZoomFactor = factor
        } catch {
            print("\(error.localizedDescription)")
        }
    }

    let newScaleFactor = minMaxZoom(pinch.scale * lastZoomFactor)

    switch pinch.state {
    case .began: fallthrough
    case .changed: update(scale: newScaleFactor)
    case .ended:
        lastZoomFactor = minMaxZoom(newScaleFactor)
        update(scale: lastZoomFactor)
    default: break
    }
}

答案 1 :(得分:11)

我在相机实现方面遇到了同样的问题。要解决这个问题,你需要了解两件事。

  • 最大和最小变焦必须在一个值范围内,否则会导致相机变焦太大。
  • 与不保存放大图像的实际图像一样,这是许多在线解决方案无法涵盖的常见错误。这实际上是因为您只是更改了视图的缩放而不是实际的AVCaptureDevice缩放。

要改变你需要的两件事:

func pinch(pinch: UIPinchGestureRecognizer) {
   var device: AVCaptureDevice = self.videoDevice
   var vZoomFactor = ((gestureRecognizer as! UIPinchGestureRecognizer).scale)
   var error:NSError!
        do{
            try device.lockForConfiguration()
            defer {device.unlockForConfiguration()}
            if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor){
                device.videoZoomFactor = vZoomFactor
            }else{
            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, vZoomFactor);
            }
        }catch error as NSError{
             NSLog("Unable to set videoZoom: %@", error.localizedDescription);
        }catch _{

        }
}

如您所见,我使用视频设备的类变量(videoDevice)来跟踪我用于可视组件的捕获设备。我将缩放限制在特定范围并更改设备上的缩放属性,而不是视图本身!

答案 2 :(得分:2)

您可以像这样简单地将prevZoomFactor重置为1,从而避免保存UIPinchGestureRecognizer.scale

    @IBAction func pinchAction(_ sender: UIPinchGestureRecognizer) {
        guard let device = currentCaptureDevice else {return}
        var zoom = device.videoZoomFactor * sender.scale
        sender.scale = 1.0
        var error:NSError!
        do{
            try device.lockForConfiguration()
            defer {device.unlockForConfiguration()}
            if zoom >= device.minAvailableVideoZoomFactor && zoom <= device.maxAvailableVideoZoomFactor {
                device.videoZoomFactor = zoom
            }else{
                NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, zoom);
            }
        }catch error as NSError{
            NSLog("Unable to set videoZoom: %@", error.localizedDescription);
        }catch _{
        }
    }

这是Apple在我参加的WWDC活动中推荐的,那是我第一次参加手势识别器问世的时候。

答案 3 :(得分:1)

    var device: AVCaptureDevice = self.backCamera
    var vZoomFactor = sender.scale
    var error:NSError!
    do{
        try device.lockForConfiguration()
        defer {device.unlockForConfiguration()}
        if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor) {

            let desiredZoomFactor:CGFloat = vZoomFactor + atan2(sender.velocity, 5.0);
            device.videoZoomFactor = max(1.0, min(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor));
        }
        else {

            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, vZoomFactor);
        }
    }
    catch error as NSError{

        NSLog("Unable to set videoZoom: %@", error.localizedDescription);
    }
    catch _{

    }

答案 4 :(得分:1)

如果您需要手动zoomTo(2.0)功能,可以使用此

// Create listener for Pinch to Zoom
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action:#selector(FSCameraView.pinchToZoom(_:)))
pinchRecognizer.delegate = self
self.previewViewContainer.addGestureRecognizer(pinchRecognizer)

// set the zoom to a zoomed in mode from start
setZoom(CGFloat(2.0)



// and the functions
func pinchToZoom(sender:UIPinchGestureRecognizer) {
    var vZoomFactor = ((sender as! UIPinchGestureRecognizer).scale)
    setZoom(vZoomFactor)
}

func setZoom(zoomFactor:CGFloat) {
    var device: AVCaptureDevice = self.device!
    var error:NSError!
    do{
        try device.lockForConfiguration()
        defer {device.unlockForConfiguration()}
        if (zoomFactor <= device.activeFormat.videoMaxZoomFactor) {

            let desiredZoomFactor:CGFloat = zoomFactor + atan2(sender.velocity, 5.0);
            device.videoZoomFactor = max(1.0, min(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor));
        }
        else {
            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, zoomFactor);
        }
    }
    catch error as NSError{
        NSLog("Unable to set videoZoom: %@", error.localizedDescription);
    }
    catch _{
    }
}

答案 5 :(得分:1)

要扩展 Ritvik Upadhyaya的答案,您还需要保存以前的缩放系数来计算新的缩放因子,每次抬起你的时候都不希望缩放重置为正常手指并再次尝试缩放。

// To track the zoom factor
var prevZoomFactor: CGFloat = 1

func pinch(pinch: UIPinchGestureRecognizer) {
    var device: AVCaptureDevice = self.videoDevice

    // Here we multiply vZoomFactor with the previous zoom factor if it exist. 
    // Else just multiply by 1
    var vZoomFactor = pinch.scale * prevZoomFactor

    // If the pinching has ended, update prevZoomFactor.
    // Note that we set the limit at 1, because zoom factor cannot be less than 1 or the setting device.videoZoomFactor will crash
    if sender.state == .ended {
        prevZoomFactor = zoomFactor >= 1 ? zoomFactor : 1
    }

    do {
        try device.lockForConfiguration()
        defer {device.unlockForConfiguration()}
        if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor) {
            device.videoZoomFactor = vZoomFactor
        } else {
            print("Unable to set videoZoom: (max \(device.activeFormat.videoMaxZoomFactor), asked \(vZoomFactor))")
      }
    } catch {
        print("\(error.localizedDescription)")
    }
}