使用自定义相机拍照 iOS 11.0 Swift 4。更新错误。

36

我的应用程序中有一个自定义相机,之前它运行良好,但在新更新后出现了以下错误:

'jpegPhotoDataRepresentation(forJPEGSampleBuffer:previewPhotoSampleBuffer:)' 在iOS 11.0中已被弃用:请改用-[AVCapturePhoto fileDataRepresentation]。

以下是出现错误的代码行:

    guard let imageData =
        AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) else {
            return
    }

这是我的完整函数(如有必要):

//Take pic function
func photoOutput(_ captureOutput: AVCapturePhotoOutput,
                 didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?,
                 previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?,
                 resolvedSettings: AVCaptureResolvedPhotoSettings,
                 bracketSettings: AVCaptureBracketedStillImageSettings?,
                 error: Error?) {


    // Make sure we get some photo sample buffer
    guard error == nil,
        let photoSampleBuffer = photoSampleBuffer else {
            print("Error capturing photo: \(String(describing: error))")
            return
    }
    // Convert photo same buffer to a jpeg image data by using // AVCapturePhotoOutput
    guard let imageData =
        AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) else {
            return
    }

    let dataProvider = CGDataProvider(data: imageData as CFData)

    let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.absoluteColorimetric)


    let image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.right)

    self.tempImageView.image = image

}

我的问题是:我应该使用什么来代替它才能使它工作?

谢谢。


请问您能否帮我在这个帖子中?它看起来非常相似,但我需要旧版本的代码:https://stackoverflow.com/questions/49291753/how-to-change-some-function-to-be-compatible-for-ios-10-or-below-for-some-functi - Agung Laksana
4个回答

57

iOS 11中,您应该像这样使用:

@available(iOS 11.0, *)
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        let imageData = photo.fileDataRepresentation()
}

你能帮我在这个线程中吗?它看起来非常相似,但我需要旧版本的 https://stackoverflow.com/questions/49291753/how-to-change-some-function-to-be-compatible-for-ios-10-or-below-for-some-functi - Agung Laksana
非常感谢!浪费了太多时间去寻找它。 - Andrey M.

12

感谢 @Vini App,我尝试了代码,它对我有用。我发布了我的图像捕获和处理的代码,希望能帮助那些需要在他们的应用中实现类似功能的人。

首先,您需要设置视频捕获设备,可以在Google上搜索,这里是一个示例:https://gist.github.com/tad-iizuka/fc35bc7835920c0b8b84e316f83e3a40

确保您需要在顶部定义photoSetting

...
var photoSetting = AVCapturePhotoSettings()
...

viewDidLoad()viewWillAppear()中配置照片设置。

            // Configure camera
        photoSetting = AVCapturePhotoSettings.init(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
        photoSetting.isAutoStillImageStabilizationEnabled = true
        photoSetting.flashMode = .off

然后使用以下函数处理缓存的图像数据

     func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

    // Check if there is any error in capturing
    guard error == nil else {
        print("Fail to capture photo: \(String(describing: error))")
        return
    }

    // Check if the pixel buffer could be converted to image data
    guard let imageData = photo.fileDataRepresentation() else {
        print("Fail to convert pixel buffer")
        return
    }

    // Check if UIImage could be initialized with image data
    guard let capturedImage = UIImage.init(data: imageData , scale: 1.0) else {
        print("Fail to convert image data to UIImage")
        return
    }

    // Get original image width/height
    let imgWidth = capturedImage.size.width
    let imgHeight = capturedImage.size.height
    // Get origin of cropped image
    let imgOrigin = CGPoint(x: (imgWidth - imgHeight)/2, y: (imgHeight - imgHeight)/2)
    // Get size of cropped iamge
    let imgSize = CGSize(width: imgHeight, height: imgHeight)

    // Check if image could be cropped successfully
    guard let imageRef = capturedImage.cgImage?.cropping(to: CGRect(origin: imgOrigin, size: imgSize)) else {
        print("Fail to crop image")
        return
    }

    // Convert cropped image ref to UIImage
    imageToSave = UIImage(cgImage: imageRef, scale: 1.0, orientation: .down)
    UIImageWriteToSavedPhotosAlbum(imageToSave, nil, nil, nil)

    // Stop video capturing session (Freeze preview)
    captureSession.stopRunning()
}

在这个函数中,像素缓冲区将被转换为photoSetting指定的图像数据格式,然后裁剪为您想要的大小。

您可以在IB中创建一个按钮来调用上述捕获函数。

@IBAction func onTakePhoto(_ sender: UIButton) {
    if let videoConnection = videoOutput.connection(with: AVMediaType.video) {
        // Adjust the orientaion of captured image
        let capturePhotoSetting = AVCapturePhotoSettings.init(from: photoSetting)
        videoConnection.videoOrientation = (previewLayer.connection?.videoOrientation)!
        // Save captured photo to system album
        self.videoOutput.capturePhoto(with: capturePhotoSetting, delegate: self)
    }
}

定义照片设置将顶部设置为变量对我没有起作用,因为在拍摄第二张照片时,应用程序崩溃并显示我不允许使用照片设置。AVCapturePhotoSettings可以在您的IBAction或其他函数中每次拍照时使用“let”(而不是var)进行定义,然后它将与重复拍照一起正常工作。 - Chewie The Chorkie
1
嗨,@VagueExplanation,感谢您的回复,但我并没有完全理解是什么导致了崩溃(听起来像是每次我实例化AVCapturePhotoSetting?)。我发布的代码在我的应用程序中的“照片展台”视图中运行良好,因此基本上,您可以拍照并继续下一个视图,如果您满意或不喜欢它,则可以重新拍摄。照片保存到相册中,应用程序在iPad上运行。希望这会有所帮助?或者您可以提供更多详细信息以进行讨论? - infinity_coding7
啊,好的,那就算了。这取决于你如何使用它。 - Chewie The Chorkie
请问您能帮助我解决这个线程问题吗?它看起来非常相似,但我需要旧版本的代码。原链接:https://stackoverflow.com/questions/49291753/how-to-change-some-function-to-be-compatible-for-ios-10-or-below-for-some-functi - Agung Laksana
谢谢你的代码!裁剪部分对我很有帮助 :) - Morpheus
@Coconuts 没问题,很高兴代码仍然有帮助 :) - infinity_coding7

0

对于 iOS 11.0 及以下版本,我都进行了处理。

var photoOutput : AVCapturePhotoOutput?

if #available(iOS 11.0, *)
{
                    photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey:AVVideoCodecType.jpeg])], completionHandler: nil)
} 

else
{
                    photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey:AVVideoCodecJPEG])], completionHandler: nil)
}

-2

使用此代码(Swift 5),我已经成功运行。

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    guard let imageData = photo.fileDataRepresentation() else { return }
    let previewImage = UIImage(data: imageData)
}

建议使用完全不同的方法,而不是帮助修复主题发起者正在使用的方法,这有什么意义呢? - Pavel Bogart
它怎么可能是不同的方法?只需检查问题并再次阅读我的答案。如果您有解决方案,请在此处发布。@PavelBogart - nitin.agam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接