我有一个简单AVCaptureSession运行让我的应用程序摄像机的输入和拍照。 我怎样才能实现“捏缩放”功能使用UIGestureRecognizer
相机?
Answer 1:
该接受的答案实际上是过时的,我不知道它实际上将图像放大后的照片。 有放大像bcattle回答说的方法。 他的回答的问题是,它并不负责采取的事实,用户可以放大,然后从该变焦位置重新启动。 他的解决方案将创造某种不属于真正优雅的跳跃。
这样做的最简单,最优雅的方式是使用缩放手势的速度。
-(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);
}
}
}
我发现,加入反正切函数的速度将缓解放大出来的效果变焦位。 这不完全是完美的,但效果是需求不够好。 也许有可能是另一种功能,缓解变焦出来的时候,几乎达到1。
注意 :另外,捏手势的刻度从0到无穷大,用0至1的存在夹持在(缩小)和1至无限的空间中捏出(放大)。 为了得到变焦良好的变焦效果出来这个你需要有一个数学方程式。 速度实际上是无穷大与0为出发点,以无限的。
编辑 :在范围例外固定崩溃。 感谢@garafajon !
Answer 2:
许多人试图通过设置层的transform属性做到这一点CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y);
见这里的羽翼丰满实现双指缩放。
Answer 3:
由于iOS的7,您可以用直接设置缩放videoZoomFactor
财产AVCaptureDevice
。
领带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
,不是线程安全的。 所以,你可能不希望从主队列中做到这一点。
Answer 4:
斯威夫特4
捏合手势识别器添加到最前视图,并将其连接到这个动作(pinchToZoom)。 captureDevice应该是目前情况下提供输入捕获会话。 pinchToZoom为双方提供正面和背面捕获设备平滑缩放。
@IBAction func pinchToZoom(_ pinch: 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
}
}
这将是宣布zoomFactor相机或VC非常有用。 我通常把它放在有AVCaptureSession相同的单。 这将作为captureDevice的videoZoomFactor的默认值。
var zoomFactor: Float = 1.0
Answer 5:
在迅速的版本,你可以通过简单地传递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
Answer 6:
我从@Gabriel卡地亚的解决方案(感谢)开始。 在我的代码,我最好使用平滑rampToVideoZoomFactor和更简单的方法来计算设备的比例因子。
(IBAction) pinchForZoom:(id) sender forEvent:(UIEvent*) event {
UIPinchGestureRecognizer* pinchRecognizer = (UIPinchGestureRecognizer *)sender;
static CGFloat zoomFactorBegin = .0;
if ( UIGestureRecognizerStateBegan == pinchRecognizer.state ) {
zoomFactorBegin = self.captureDevice.videoZoomFactor;
} else if (UIGestureRecognizerStateChanged == pinchRecognizer.state) {
NSError *error = nil;
if ([self.captureDevice lockForConfiguration:&error]) {
CGFloat desiredZoomFactor = zoomFactorBegin * pinchRecognizer.scale;
CGFloat zoomFactor = MAX(1.0, MIN(desiredZoomFactor, self.captureDevice.activeFormat.videoMaxZoomFactor));
[self.captureDevice rampToVideoZoomFactor:zoomFactor withRate:3.0];
[self.captureDevice unlockForConfiguration];
} else {
NSLog(@"error: %@", error);
}
}
}
Answer 7:
基于@Gabriel卡地亚的回答:
- (void) cameraZoomWithPinchVelocity: (CGFloat)velocity {
CGFloat pinchVelocityDividerFactor = 40.0f;
if (velocity < 0) {
pinchVelocityDividerFactor = 5.; //zoom in
}
if (_videoInput) {
if([[_videoInput device] position] == AVCaptureDevicePositionBack) {
NSError *error = nil;
if ([[_videoInput device] lockForConfiguration:&error]) {
CGFloat desiredZoomFactor = [_videoInput device].videoZoomFactor + atan2f(velocity, pinchVelocityDividerFactor);
// Check if desiredZoomFactor fits required range from 1.0 to activeFormat.videoMaxZoomFactor
CGFloat maxFactor = MIN(10, [_videoInput device].activeFormat.videoMaxZoomFactor);
[_videoInput device].videoZoomFactor = MAX(1.0, MIN(desiredZoomFactor, maxFactor));
[[_videoInput device] unlockForConfiguration];
} else {
NSLog(@"cameraZoomWithPinchVelocity error: %@", error);
}
}
}
}
Answer 8:
我使用的是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];
}
}];