【问题标题】:SWIFT 3: Capture photo with AVCapturePhotoOutput (Need another set of eyes to look over code, why isn't this working?)SWIFT 3:使用 AVCapturePhotoOutput 捕获照片(需要另一双眼睛来查看代码,为什么这不起作用?)
【发布时间】:2017-03-16 15:02:36
【问题描述】:

我有一个自定义相机,在类中添加了AVCapturePhotoCaptureDelegate,并使用以下代码捕获静止图像:

出口、变量和常数

@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()

设置相机会话

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

捕捉按钮

@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 观察相机功能

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
    }
}

好的,这就是交易——我在cameraPhotoOutput.capturePhoto(with: photoSettings, delegate: self) 设置了一个断点,并在进入该行时收到以下错误消息:

错误信息

致命错误:在展开可选值时意外发现 nil [runtime details] 致命错误:在展开可选值时意外发现 nil

上面的代码直接来自 Apple 的示例文档“AVCam”以及来自 SO Q&As(linklink. 和其他重复这些答案的其他人)的输入。我的最终目标是捕获图像,并立即将图像和用户推送到新的 ViewController 以进行编辑/发布/保存;但是,我目前使用 UIImageView 只是为了确认捕获...这首先不起作用。

那么,这个实现是怎么回事???这几天一直让我发疯。

Swift 3,xCode 8

【问题讨论】:

  • 我应该注意到捕获会话工作得很好,在显示视频预览提要方面零问题 - 这是导致头痛的捕获照片操作。 CameraViewController 以模态方式呈现在 tabBarController 上。
  • 您是否真的在 iPad 等实际设备上进行测试?
  • @ElTomato 确实,iPhone 7+
  • 如果你在iPad上测试它作为一个实际的设备,它肯定会崩溃。否则,请准确告诉我们它在哪一行崩溃。
  • @ElTomato 我不确定你的意思?它已经在实际设备(iPhone7+)上捕获时崩溃。我知道它正在崩溃,我的问题是它为什么会崩溃......这可能很明显,而且我离问题太近了,无法看到全局。

标签: ios swift camera avcapturesession avcapturedevice


【解决方案1】:

尝试改变

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

进入

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

【讨论】:

  • 我喝了第二杯啤酒。希望这会奏效。
  • 如果您要让应用程序在 iPad 上运行,您还需要做一些事情。
【解决方案2】:

好吧,想通了。 El Tomato 对问题孩子的治疗是正确的,但这不是正确的处方。我的createCamera() 函数设置为private,这当然会使内容在其主体之外不可见。因此,当我调用正确的 AVCapturePhotoOutput() 时,不存在用于执行 capturePhoto() 调用的缓冲区提要...抛出所描述的错误。

所以这意味着行:

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

是正确的,但只是执行时设置不正确。为了确认正确执行我...

  • 更改了我的private let photoOutput = AVCapturePhotoOutput() 常量
  • private let cameraPhotoOutput = AVCapturePhotoOutput()
  • 并直接在private func createCamera() 中调用该常量

它立即完美地执行了图像捕获。

还尝试将cameraPhotoOutputAVCapturePhotoOutput()替换为cameraOutputAVCapturePhotoOutput!,并简单地重现了错误。

如果您有兴趣:cgImage 创建过程在func capture(_ : capture... 函数中保持不变。在其范围内,我还确定了摄像头设备的位置,如果前置摄像头,则更改图像的方向,并在主队列中将照片发送到 ReviewViewController 上的 var photoContent: UIImage? 变量。

希望我的心理错误对其他人有所帮助:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 2022-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多