无法使用 AVCapturePhotoOutput 快速捕捉照片 + xcode

Posted

技术标签:

【中文标题】无法使用 AVCapturePhotoOutput 快速捕捉照片 + xcode【英文标题】:Unable to use AVCapturePhotoOutput to capture photo swift + xcode 【发布时间】:2016-12-13 14:18:43 【问题描述】:

我正在开发一个自定义相机应用程序,本教程使用 AVCaptureStillImageOutput,它在 ios 10 中已被弃用。我已经设置了相机,现在一直不知道如何拍照

这是我有相机的全景图

import UIKit
import AVFoundation

var cameraPos = "back"

class View3: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate 


@IBOutlet weak var clickButton: UIButton!
@IBOutlet var cameraView: UIView!
var session: AVCaptureSession?
var stillImageOutput: AVCapturePhotoOutput?
var videoPreviewLayer: AVCaptureVideoPreviewLayer?

override func viewDidLoad() 
    super.viewDidLoad()        


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()


override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)
    clickButton.center.x = cameraView.bounds.width/2
    loadCamera()


override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)
 

@IBAction func clickCapture(_ sender: UIButton) 

    if let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo) 
       // This is where I need help 
        


@IBAction func changeDevice(_ sender: UIButton) 
    if cameraPos == "back"
    cameraPos = "front"

    else
    cameraPos = "back"


    loadCamera()


func loadCamera()

    session?.stopRunning()
    videoPreviewLayer?.removeFromSuperlayer()

    session = AVCaptureSession()
    session!.sessionPreset = AVCaptureSessionPresetPhoto

    var backCamera = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .front)

    if cameraPos == "back"
    
        backCamera = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .back)
    

    var error: NSError?
    var input: AVCaptureDeviceInput!
    do 
        input = try AVCaptureDeviceInput(device: backCamera)
     catch let error1 as NSError 
        error = error1
        input = nil
        print(error!.localizedDescription)
    

    if error == nil && session!.canAddInput(input) 
        session!.addInput(input)

        stillImageOutput = AVCapturePhotoOutput()

if session!.canAddOutput(stillImageOutput) 
            session!.addOutput(stillImageOutput)
            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
            videoPreviewLayer?.frame = cameraView.bounds
            videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
            videoPreviewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait

            cameraView.layer.addSublayer(videoPreviewLayer!)
            session!.startRunning()

                


这是我需要帮助的地方

@IBAction func clickCapture(_ sender: UIButton) 

if let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo) 
   // This is where I need help 
    

我已经在这里查看了答案How to use AVCapturePhotoOutput 但我不明白如何将该代码合并到此代码中,因为它涉及声明一个新类

【问题讨论】:

【参考方案1】:

你快到了。

输出为AVCapturePhotoOutput

查看AVCapturePhotoOutput documentation 以获得更多帮助。

这些是拍摄照片的步骤。

    创建一个AVCapturePhotoOutput 对象。使用它的属性来 确定支持的捕获设置并启用某些功能 (例如,是否拍摄实况照片)。 创建并配置一个AVCapturePhotoSettings 对象以供选择 特定捕获的功能和设置(例如,是否 启用图像稳定功能或闪光灯)。 通过将照片设置对象传递给 capturePhoto(with:delegate:) 方法以及委托对象 实现AVCapturePhotoCaptureDelegate 协议。照片 捕获输出然后调用你的代表通知你重要的 捕获过程中的事件。

在您的 clickCapture 方法中添加以下代码,并且不要忘记确认并在您的类中实现委托。

let settings = AVCapturePhotoSettings()
let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
                             kCVPixelBufferWidthKey as String: 160,
                             kCVPixelBufferHeightKey as String: 160,
                             ]
settings.previewPhotoFormat = previewFormat
self.cameraOutput.capturePhoto(with: settings, delegate: self)

输出为AVCaptureStillImageOutput

如果您打算通过视频连接拍摄照片。您可以按照以下步骤操作。

第 1 步:获取连接

if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) 
  // ...
  // Code for photo capture goes here...

第 2 步:拍摄照片

调用captureStillImageAsynchronouslyFromConnection函数 stillImageOutputsampleBuffer 表示捕获的数据。
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler:  (sampleBuffer, error) -> Void in
  // ...
  // Process the image data (sampleBuffer) here to get an image file we can put in our captureImageView
)

第 3 步:处理图像数据

我们需要采取一些步骤来处理在 sampleBuffer 中找到的图像数据,以便最终得到一个 UIImage,我们可以将其插入到 captureImageView 中并在应用程序的其他地方轻松使用。
if sampleBuffer != nil 
  let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
  let dataProvider = CGDataProviderCreateWithCFData(imageData)
  let cgImageRef = CGImageCreateWithJPEGDataProvider(dataProvider, nil, true, CGColorRenderingIntent.RenderingIntentDefault)
  let image = UIImage(CGImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.Right)
  // ...
  // Add the image to captureImageView here...

第 4 步:保存图片

根据您的需要将图像保存到照片库或在图像视图中显示


欲了解更多详情,请查看拍照下的Create custom camera view guide

【讨论】:

captureStillImageAsynchronouslyFromConnection 函数不是 AVCapturePhotoOutput 的成员,它是 AVCaptureStillImageOutput 的成员 captureStillImageAsynchronouslyFromConnection 是用自定义相机从视频中拍照。而AVCapturePhotoOutput是用来直接拍照的 但将 stillImageOutput 作为 AVCapturePhotoOutput 的对象,然后将 stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: (sampleBuffer, error) -> Void in 给出错误 你必须选择图像输出..它可以是AVCaptureStillImageOutputAVCapturePhotoOutput 或者你也可以有两个输出。然后按照上面提到的步骤。 它肯定会出错,因为它是AVCaptureStillImageOutput 的成员而不是AVCapturePhotoOutput。如果你想使用AVCaptureStillImageOutput,你必须关注this..记住这里有两种方法..不要混淆

以上是关于无法使用 AVCapturePhotoOutput 快速捕捉照片 + xcode的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AVCapturePhotoOutput

使用 AVCapturePhotoOutput 使用闪光灯拍照时出现问题

在 iOS10 中使用 AVCapturePhotoOutput - NSGenericException

AVCapturePhotoOutput - Xcode 9 Beta 5 中的更改

swift AVCapturePhotoOutput capturePhoto 挂起预览

为啥在 AVCapturePhotoOutput 上调用 .capturePhoto(with:,delegate:) 会导致崩溃