AVCaptureDevice Camera Zoom

Tengo una AVCaptureSession simple en ejecución para get una camera de alimentación en mi aplicación y tomar fotos. ¿Cómo puedo implementar la funcionalidad 'pellizcar para ampliar' usando un UIGestureRecognizer para la camera?

La respuesta aceptada es obsoleta y no estoy seguro de que realmente tomará la foto de la image ampliada. Hay un método para acercar el zoom como dice respuesta bcattle. El problema de su respuesta es que no tiene en count el hecho de que el usuario puede acercar y reiniciar desde esa position de zoom. Su solución creará algún tipo de saltos que no sean realmente elegantes.

La forma más fácil y elegante de hacerlo es usar la velocidad del gesto de pellizco.

 -(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer { const CGFloat pinchVelocityDividerFactor = 5.0f; if (pinchRecognizer.state == UIGestureRecognizerStateChanged) { NSError *error = nil; if ([videoDevice lockForConfiguration:&error]) { CGFloat desinetworkingZoomFactor = device.videoZoomFactor + atan2f(pinchRecognizer.velocity, pinchVelocityDividerFactor); // Check if desinetworkingZoomFactor fits requinetworking range from 1.0 to activeFormat.videoMaxZoomFactor device.videoZoomFactor = MAX(1.0, MIN(desinetworkingZoomFactor, device.activeFormat.videoMaxZoomFactor)); [videoDevice unlockForConfiguration]; } else { NSLog(@"error: %@", error); } } } 

Descubrí que agregar la function arctan a la velocidad facilitará un poco el efecto de acercar el zoom. No es exactamente perfecto, pero el efecto es lo suficientemente bueno para las necesidades. Probablemente podría haber otra function para networkingucir el zoom cuando casi alcanza 1.

NOTA : Además, la escala de un gesto de pellizco va de 0 a infinito, con 0 a 1 pellizcando (alejándose) y 1 a infinito siendo pellizcante (acercando). Para get un buen zoom en el efecto de alejamiento con esto, necesitaría tener una ecuación matemática. La velocidad es en realidad de infinito a infinito, siendo 0 el punto de partida.

EDIT : Se corrigió la exception de locking en el range. Gracias a @garafajon !

Muchos han tratado de hacerlo estableciendo la propiedad de transformación en la capa en CGAffineTransformMakeScale(gesture.scale.x, gesture.scale.y); Vea aquí una implementación completa de pellizcar para ampliar.

Desde iOS 7 puede establecer el zoom directamente con la propiedad AVCaptureDevice de AVCaptureDevice .

Ate la propiedad de scale del UIPinchGestureRecognizer al videoZoomFactor con una constante de escala. Esto le permitirá variar la sensibilidad al gusto:

 -(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); } } } 

Tenga en count que AVCaptureDevice , junto con todo lo demás relacionado con AVCaptureSession , no es seguro para subprocesss. Entonces probablemente no quieras hacer esto desde la queue principal.

En la versión rápida, puede acercar / alejar simplemente pasando el número de escala en videoZoomFactor. El código siguiente en el controller UIPinchGestureRecognizer resolverá el problema.

 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 } 

Aquí, pivotPinchScale es una propiedad CGFloat que declaró en su controller en alguna parte.

También puede consultar el siguiente proyecto para ver cómo funciona la camera con UIPinchGestureRecognizer. https://github.com/DragonCherry/CameraPreviewController

Estoy usando iOS SDK 8.3 y el marco AVfoundation y para mí, con el siguiente método, trabajé para:

 nameOfAVCaptureVideoPreviewLayer.affineTransform = CGAffineTransformMakeScale(scaleX, scaleY) 

Para save la image con la misma escala utilicé el siguiente método:

 nameOfAVCaptureConnection.videoScaleAndCropFactor = factorNumber; 

El siguiente código es para get la image en la escala

 [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { if(imageDataSampleBuffer != NULL){ NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; UIImage *image = [UIImage imageWithData:imageData]; } }];