2017-03-16 1 views
0

J'ai un appareil photo personnalisé, avec AVCapturePhotoCaptureDelegate ajouté à la classe, et le code suivant pour capturer un alambic Image:SWIFT 3: Capturez une photo avec AVCapturePhotoOutput (Avez-vous besoin d'un autre ensemble d'yeux pour regarder le code, pourquoi cela ne fonctionne-t-il pas?)

points de vente, variables et Constantes

@IBOutlet weak var cameraPreview: UIView! 
@IBOutlet wear var takePhotoPreview: UIImageView! 

private var cameraView: AVCaptureVideoPreviewLayer! 
private var camera: AVCaptureDevice! 
private var cameraInput: AVCaptureDeviceInput! 
private var cameraOutput: AVCapturePhotoOutput! 
private var photoSampleBuffer: CMSampleBuffer? 
private var previewPhotoSampleBuffer: CMSampleBuffer? 
private var photoData: Data? = nil 

private let cameraSession = AVCaptureSession() 
private photoOutput = AVCapturePhotoOutput() 

Configuration de la caméra session

private func createCamera() { 
    cameraSession.beginConfiguration() 
    cameraSession.sessionPreset = AVCaptureSessionPresetPhoto 
    cameraSession.automaticallyConfiguresCaptureDeviceForWideColor = true 

    // Add Camera Input 
    if let defaultCamera = AVCaptureDeviceDiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaTypeVideo, position: .back).devices { 
     camera = defaultCamera.first 
     do { 
      let cameraInput = try AVCaptureDeviceInput(device: camera) 
      if cameraSession.canAddInput(cameraInput) { 
       cameraSession.addInput(cameraInput) 
       print("Camera input added to the session") 
      } 
     } catch { print("Could not add camera input to the camera session") } 
    } 

    // Add Camera View Input 
    if let cameraView = AVCaptureVideoPreviewLayer(session: cameraSession) { 
     cameraView.frame = cameraPreview.bounds 
     cameraView.videoGravity = AVLayerVideoGravityResizeAspectFill 
     cameraView.cornerRadius = 12.0 
     cameraPreview.layer.addSublayer(cameraView) 
     print("Camera view created for the camera session") 
    } else { print("Could not create camera preview") } 

    // Add Photo Output 
    let cameraPhotoOutput = AVCapturePhotoOutput() 
    if cameraSession.canAddOutput(cameraPhotoOutput) { 
     cameraSession.addOutput(cameraPhotoOutput) 
     cameraPhotoOutput.isHighResolutionCaptureEnabled = true 
     print("Camera output added to the camera session") 
    } else { 
     print("Could not add camera photo output to the camera session") 
     cameraSession.commitConfiguration() 
     return 
    } 

    cameraSession.commitConfiguration() 

    cameraSession.startRunning() 
} 

CaptureButton

@IBOutlet weak var cameraShutter: UIButton! 
@IBAction func cameraShutter(_ sender: UIButton) { 
    let photoSettings = AVCapturePhotoSettings() 
    photoSettings.flashMode = .on 
    photoSettings.isHighResolutionPhotoEnabled = true 
    photoSettings.isAutoStillImageStabilizationEnabled = true 
    if photoSettings.availablePreviewPhotoPixelFormatTypes.count > 0 { 
     photoSettings.previewPhotoFormat = [ kCVPixelBufferPixelFormatTypeKey as String : photoSettings.availablePreviewPhotoPixelFormatTypes.first!] 
    } 
    cameraPhotoOutput.capturePhoto(with: photoSettings, delegate: self) 
} 

iOS Observer Fonction d'appareil photo

func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) { 
    if let photoSampleBuffer = photoSampleBuffer { 
     photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) 
     let photoDataProvider = CGDataProvider(data: photoData as! CFData) 
     let cgImagePhotoRef = CGImage(jpegDataProviderSource: photoDataProvider!, decode: nil, shouldInterpolate: true, intent: .absoluteColorimetric) 
     let newPhoto = UIImage(cgImage: cgImagePhotoRef!, scale: 1.0, orientation: UIImageOrientation.right) 
     self.takePhotoPreview.image = newPhoto 
     self.takePhotoPreview.isHidden = false 
    } 
     else { 
     print("Error capturing photo: \(error)") 
     return 
    } 
} 

Bon, alors voici l'accord - je mets un point d'arrêt à cameraPhotoOutput.capturePhoto(with: photoSettings, delegate: self) et à entrer dans la ligne reçu l'erreur suivante message:

Message d'erreur

erreur fatale: de façon inattendue nulle en déballant une valeur facultative [détails d'exécution] d'erreur fatale: de façon inattendue trouvée nulle en déballant une valeur facultative

Le code ci-dessus est celui du premier exemple de doc d'Apple « AVCam » le long avec l'entrée de SO Q & As (link, link., et d'autres qui ont répété ces réponses). Mon objectif final est de capturer une image, et immédiatement pousser à l'image et l'utilisateur à un nouveau ViewController pour éditer/poster/enregistrer; Cependant, j'utilise actuellement un UIImageView juste pour confirmer la capture ... qui ne fonctionne pas en premier lieu.

Alors, que se passe-t-il avec cette implémentation ??? Cela m'a rendu fou pendant des jours.

Swift 3, xCode 8

+0

Je dois souligner que la session de capture fonctionne très bien, zéro problèmes dans l'affichage de l'alimentation de prévisualisation vidéo - c'est l'action de photo de capture provoquant le mal de tête. Le CameraViewController est présenté de manière modale sur un tabBarController. – brolly

+0

Etes-vous en train de tester sur un appareil réel comme un iPad? –

+0

@ElTomato oui en effet, iPhone 7+ – brolly

Répondre

0

D'accord, tout compris. El Tomato était sur la bonne voie avec l'enfant à problèmes, mais ce n'était pas la bonne prescription. Ma fonction createCamera() a été définie sur private ce qui, bien sûr, rend le contenu invisible à l'extérieur de son corps. Donc pendant que j'appelais le AVCapturePhotoOutput() correct, le flux tampon n'existait pas pour l'appel capturePhoto() pour exécuter ... en lançant l'erreur décrite.

Cela signifie donc la ligne:

cameraPhotoOutput.capturePhoto(with: photoSettings, delegate: self)

était correcte, mais il était tout simplement la configuration incorrecte dans l'exécution. Pour confirmer la bonne exécution je ...

  • a changé ma private let photoOutput = AVCapturePhotoOutput() constante
  • -private let cameraPhotoOutput = AVCapturePhotoOutput()
  • et appelé cette constante directement dans private func createCamera()

qui a exécuté immédiatement une capture d'image parfaitement.

remplaçant également cameraPhotoOutput, un AVCapturePhotoOutput(), avec cameraOutput, un AVCapturePhotoOutput!, a été essayé et simplement reproduire l'erreur.

Si vous êtes intéressé: le processus de création de cgImage est resté le même dans la fonction func capture(_ : capture.... Dans ses limites, j'ai également déterminé la position de l'appareil photo, changé l'orientation de l'image si caméra frontale, et envoyé sur la file d'attente principale la photo sur une variable var photoContent: UIImage? sur le ReviewViewController.

espère que mon erreur mentale aide quelqu'un d'autre :-)

0

Essayez de changer

cameraPhotoOutput.capturePhoto(with: photoSettings, delegate: self) 

dans

cameraOutput.capturePhoto(with: photoSettings, delegate: self as AVCapturePhotoCaptureDelegate) 
+2

Je suis bourré avec une 2ème bière. J'espère que ça va marcher. –

+0

Vous devez également faire quelque chose si vous voulez que l'application fonctionne sur l'iPad. –