mini instalar como apple actualizar camera swift3 ios10 avcapturesession

camera - instalar - AVLayerVideoGravityResize no coincide en los dispositivos nuevos, iOS 10?



ios 12 (1)

AVLayerVideoGravityResize cordura: ¿está seguro de que AVLayerVideoGravityResize es el que desea usar? Eso va a estirar la imagen (no preservar la relación de aspecto) al marco de la vista previa. Si tiene la intención de mantener la relación de aspecto, o bien desea AVLayerVideoGravityResizeAspect (como observó, habrá barras grises, pero se mantendrá la relación de aspecto) o AVLayerVideoGravityResizeAspectFill (probablemente lo que quiera, parte de la vista previa se cortará, pero aspecto la relación se mantendrá).

Suponiendo que su vista ''aquí'' (la que pasó a makePhotoOn: tiene el mismo tamaño / posición que su vista previa, querrá establecer el modo de contentMode la vista ''aquí'' para que coincida con el comportamiento de su vista previa.

Entonces, si utilizó AVLayerVideoGravityResizeAspect para la vista previa, entonces:

here.contentMode = .scaleAspectFit

Si utilizó AVLayerVideoGravityResizeAspectFill para la vista previa, entonces:

here.contentMode = .scaleAspectFill .

El contentMode predeterminado de una vista es .scaleToFill (indicado aquí: https://developer.apple.com/reference/uikit/uiview/1622619-contentmode ) por lo que su imagen "aquí" probablemente esté estirando la imagen para que coincida con su tamaño, no manteniendo la relación de aspecto.

Si eso no ayuda, puede considerar proporcionar un proyecto barebones que muestre el problema en github para que los usuarios entre nosotros en SO puedan construirlo rápidamente y jugar con él.

Cámara con una vista previa en vivo a pantalla completa,

previewLayer!.videoGravity = AVLayerVideoGravityResize

hacer una imagen ...

stillImageOutput?.captureStillImageAsynchronously( from: videoConnection, completionHandler:

la vista previa en vivo a pantalla completa coincidirá o debería coincidir exactamente con la imagen fija.

(Para mayor claridad, AVLayerVideoGravityResizeAspectFill usa accidentalmente AVLayerVideoGravityResizeAspectFill . En ese caso, la vista previa en vivo NO coincidirá con la imagen fija; verá un "salto" mientras se estira).

Sin embargo...

Si intenta lo siguiente (por lo que usa AVLayerVideoGravityResize - la opción correcta) con iOS10 ...

no funciona exactamente: obtienes A SMALL JUMP entre la vista previa en vivo y la imagen fija. Uno o el otro está ligeramente estirado incorrectamente.

¿Podría esto ser un error con algunos dispositivos? o en iOS?

(Funciona perfectamente, sin saltos, en dispositivos viejos, y si lo intentas con iOS9).

¿Alguien más ha visto esto?

// CameraPlane ... the actual live camera plane per se import UIKit import AVFoundation class CameraPlane:UIViewController { var captureSession: AVCaptureSession? var stillImageOutput: AVCaptureStillImageOutput? var previewLayer: AVCaptureVideoPreviewLayer? fileprivate func fixConnectionOrientation() { if let connection = self.previewLayer?.connection { let previewLayerConnection : AVCaptureConnection = connection guard previewLayerConnection.isVideoOrientationSupported else { print("strangely no orientation support") return } previewLayerConnection.videoOrientation = neededVideoOrientation() previewLayer!.frame = view.bounds } } func neededVideoOrientation()->(AVCaptureVideoOrientation) { let currentDevice:UIDevice = UIDevice.current let orientation: UIDeviceOrientation = currentDevice.orientation var r:AVCaptureVideoOrientation switch (orientation) { case .portrait: r = .portrait break case .landscapeRight: r = .landscapeLeft break case .landscapeLeft: r = .landscapeRight break case .portraitUpsideDown: r = .portraitUpsideDown break default: r = .portrait break } return r } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() fixConnectionOrientation() } func cameraBegin() { captureSession = AVCaptureSession() captureSession!.sessionPreset = AVCaptureSessionPresetPhoto // remember that of course, none of this will work on a simulator, only on a device let backCamera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) var error: NSError? var input: AVCaptureDeviceInput! do { input = try AVCaptureDeviceInput(device: backCamera) } catch let error1 as NSError { error = error1 input = nil } if ( error != nil ) { print("probably on simulator? no camera?") return; } if ( captureSession!.canAddInput(input) == false ) { print("capture session problem?") return; } captureSession!.addInput(input) stillImageOutput = AVCaptureStillImageOutput() stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG] if ( captureSession!.canAddOutput(stillImageOutput) == false ) { print("capture session with stillImageOutput problem?") return; } captureSession!.addOutput(stillImageOutput) previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) // previewLayer!.videoGravity = AVLayerVideoGravityResizeAspect // means, won''t reach the top and bottom on devices, gray bars // previewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill // means, you get the "large squeeze" once you make photo previewLayer!.videoGravity = AVLayerVideoGravityResize // works perfectly on ios9, older devices etc. // on 6s+, you get a small jump between the video live preview and the make photo fixConnectionOrientation() view.layer.addSublayer(previewLayer!) captureSession!.startRunning() previewLayer!.frame = view.bounds } /*Video Gravity. These string constants define how the video is displayed within a layer’s bounds rectangle. You use these constants when setting the videoGravity property of an AVPlayerLayer or AVCaptureVideoPreviewLayer instance. AVLayerVideoGravityResize Specifies that the video should be stretched to fill the layer’s bounds. AVLayerVideoGravityResizeAspect Specifies that the player should preserve the video’s aspect ratio and fit the video within the layer’s bounds. AVLayerVideoGravityResizeAspectFill Specifies that the player should preserve the video’s aspect ratio and fill the layer’s bounds. */ func makePhotoOn(_ here:UIImageView) { // recall that this indeed makes a still image, which is used as // a new background image (indeed on the "stillImage" view) // and you can then continue to move the door around on that scene. if ( stillImageOutput == nil ) { print("simulator, using test image.") here.image = UIImage(named:"ProductMouldings.jpg") return } guard let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo) else { print("AVMediaTypeVideo didn''t work?") return } videoConnection.videoOrientation = (previewLayer!.connection?.videoOrientation)! stillImageOutput?.captureStillImageAsynchronously( from: videoConnection, completionHandler: { (sampleBuffer, error) in guard sampleBuffer != nil else { print("sample buffer woe?") return } let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer) let dataProvider = CGDataProvider(data: imageData as! CFData) let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent) let ort = self.neededImageOrientation() let image = UIImage(cgImage:cgImageRef!, scale:1.0, orientation:ort) here.image = image }) } func neededImageOrientation()->(UIImageOrientation) { var n : UIImageOrientation let currentDevice: UIDevice = UIDevice.current let orientation: UIDeviceOrientation = currentDevice.orientation switch orientation { case UIDeviceOrientation.portraitUpsideDown: n = .left case UIDeviceOrientation.landscapeRight: n = .down case UIDeviceOrientation.landscapeLeft: n = .up case UIDeviceOrientation.portrait: n = .right default: n = .right } return n } /* @IBAction func didPressTakeAnother(sender: AnyObject) { captureSession!.startRunning() } */ }