AVCaptureDevice相机变焦
我有一个简单的AVCaptureSession运行在我的应用程序中获取相机源并拍照。 我如何使用相机的UIGestureRecognizer
实现“捏放大”function?
接受的答案实际上是过时的,我不确定它实际上将放大图像的照片。 有一种方法可以放大像bcattle答案说。 他的回答的问题是,它不承担用户可以放大然后从该缩放位置重新开始的事实。 他的解决scheme将创造一些不是很优雅的跳跃。
最简单和最优雅的方法是使用捏手势的速度。
-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer { const CGFloat pinchVelocityDividerFactor = 5.0f; if (pinchRecognizer.state == UIGestureRecognizerStateChanged) { NSError *error = nil; if ([videoDevice lockForConfiguration:&error]) { CGFloat desiredZoomFactor = device.videoZoomFactor + atan2f(pinchRecognizer.velocity, pinchVelocityDividerFactor); // Check if desiredZoomFactor fits required range from 1.0 to activeFormat.videoMaxZoomFactor device.videoZoomFactor = MAX(1.0, MIN(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor)); [videoDevice unlockForConfiguration]; } else { NSLog(@"error: %@", error); } } }
我发现将arctan函数添加到速度会稍微放大缩小效果。 这并不完美,但效果足以满足需求。 当它几乎达到1时,可能还有其他的function来放大缩小。
注意 :另外,缩小手势的比例从0到无限,0到1被捏入(缩小),1被无限缩小(放大)。 为了得到放大缩小的效果,你需要有一个math公式。 速度实际上是从无限到无限,以0为起点。
编辑 :修复范围exception崩溃。 感谢@garafajon !
许多人都试图通过设置图层上的transform属性为CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y);
在这里看到一个完整的捏缩放的实现。
从iOS 7开始,您可以使用AVCaptureDevice
的videoZoomFactor
属性直接设置缩放。
使用缩放常数将videoZoomFactor
的scale
属性UIPinchGestureRecognizer
到videoZoomFactor
。 这会让你改变对味道的敏感度:
-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer { const CGFloat pinchZoomScaleFactor = 2.0; if (pinchRecognizer.state == UIGestureRecognizerStateChanged) { NSError *error = nil; if ([videoDevice lockForConfiguration:&error]) { videoDevice.videoZoomFactor = 1.0 + pinchRecognizer.scale * pinchZoomScaleFactor; [videoDevice unlockForConfiguration]; } else { NSLog(@"error: %@", error); } } }
请注意, AVCaptureDevice
,与AVCaptureSession
相关的所有其他内容都不是线程安全的。 所以你可能不希望从主队列中这样做。
在swift版本中,只需在videoZoomFactor上传递缩放的数字就可以放大/缩小。 以下代码在UIPinchGestureRecognizer处理程序将解决此问题。
do { try device.lockForConfiguration() switch gesture.state { case .began: self.pivotPinchScale = device.videoZoomFactor case .changed: var factor = self.pivotPinchScale * gesture.scale factor = max(1, min(factor, device.activeFormat.videoMaxZoomFactor)) device.videoZoomFactor = factor default: break } device.unlockForConfiguration() } catch { // handle exception }
在这里,pivotPinchScale是一个CGFloat属性,在你的控制器的某个地方声明。
您也可以参考以下项目了解相机如何与UIPinchGestureRecognizer配合使用。 https://github.com/DragonCherry/CameraPreviewController
斯威夫特4
添加捏手势识别器到最前面的视图,并将其连接到此操作( pinchToZoom )。 captureDevice应该是当前为捕获会话提供input的实例。 pinchToZoom可以为前后捕捉设备提供平滑的缩放。
@IBAction func pinchToZoom(_ sender: UIPinchGestureRecognizer) { guard let device = captureDevice else { return } func minMaxZoom(_ factor: CGFloat) -> CGFloat { return min(max(factor, 1.0), device.activeFormat.videoMaxZoomFactor) } func update(scale factor: CGFloat) { do { try device.lockForConfiguration() defer { device.unlockForConfiguration() } device.videoZoomFactor = factor } catch { debugPrint(error) } } let newScaleFactor = minMaxZoom(pinch.scale * zoomFactor) switch sender.state { case .began: fallthrough case .changed: update(scale: newScaleFactor) case .ended: zoomFactor = minMaxZoom(newScaleFactor) update(scale: zoomFactor) default: break } }
在摄像头或vc上声明zoomFactor会很有用。 我通常把它放在具有AVCaptureSession的同一个单例中。 这将作为captureDevice的videoZoomFactor的默认值。
var zoomFactor: Float = 1.0
我正在使用iOS SDK 8.3和AVfoundation框架,并为我使用以下方法工作:
nameOfAVCaptureVideoPreviewLayer.affineTransform = CGAffineTransformMakeScale(scaleX, scaleY)
为了以相同的比例保存图片,我使用了以下方法:
nameOfAVCaptureConnection.videoScaleAndCropFactor = factorNumber;
下面的代码是为了获得规模的图像
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { if(imageDataSampleBuffer != NULL){ NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; UIImage *image = [UIImage imageWithData:imageData]; } }];