32

I have a custom camera in my app and it worked fine, but after the new update I am getting this error:

'jpegPhotoDataRepresentation(forJPEGSampleBuffer:previewPhotoSampleBuffer:)' was deprecated in iOS 11.0: Use -[AVCapturePhoto fileDataRepresentation] instead.

This is the line where I'm getting that error:

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

This is my whole function (if needed):

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

}

My guestion is: What should I use instead to make it work?

Thank you.

0ndre_
  • 3,057
  • 5
  • 19
  • 42
  • could you please help me in this thread? it seems very similar but i need the old version of this https://stackoverflow.com/questions/49291753/how-to-change-some-function-to-be-compatible-for-ios-10-or-below-for-some-functi – Agung Laksana Mar 15 '18 at 05:48

4 Answers4

54

In iOS 11, you should use like this :

@available(iOS 11.0, *)
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        let imageData = photo.fileDataRepresentation()
}
Vini App
  • 6,755
  • 2
  • 22
  • 41
  • could you please help me in this thread? it seems very similar but i need the old version of this https://stackoverflow.com/questions/49291753/how-to-change-some-function-to-be-compatible-for-ios-10-or-below-for-some-functi – Agung Laksana Mar 15 '18 at 04:48
  • Thanks a lot! Wasted too much time to find it. – Andrey M. Jan 04 '20 at 04:34
12

Thanks @Vini App, I tried the code it worked for me, I posted my code for image capturing and processing, hope that will help people who needs similar function in their app.

First you need to setup your video capturing device, search it google here is an example https://gist.github.com/tad-iizuka/fc35bc7835920c0b8b84e316f83e3a40

Makes sure that you need to define photoSetting at the top

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

Configure the photo setting either in viewDidLoad() or viewWillAppear()

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

Then use the following function to process buffered image data

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

In this function, pixel buffer is converted to image data in the format specified by photoSetting and then cropped to the size you want.

You can create a button in IB to call the capturing function above

@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)
    }
}
infinity_coding7
  • 166
  • 1
  • 14
  • Defining photoSetting up top as a variable didn't work for me, because by the second photo was taken, the application crashed saying I was not allowed to use photo settings. AVCapturePhotoSettings can be defined with "let" (not var) in your IBAction or other function every time you take a photo, then it will work fine with repeated photo taking. – Chewie The Chorkie Feb 16 '18 at 16:38
  • 1
    Hi, @VagueExplanation, thanks for the reply but I didn't quite understand what is exactly caused the crash (sounds like each time I instantiate an AVCapturePhotoSetting?). The code that posted worked in a 'Photo booth' view in my app, so basically, you can take a photo and proceed to next view you are satisfied or re-take it if you don't like it. The photo is saved to album and the app runs on iPad. Hope that will be helpful? Or maybe you can provide more details for discussion? – infinity_coding7 Feb 18 '18 at 18:48
  • Ah okay, then never mind. It depends on how you use it. – Chewie The Chorkie Feb 20 '18 at 16:09
  • could you please help me in this thread? it seems very similar but i need the old version of this https://stackoverflow.com/questions/49291753/how-to-change-some-function-to-be-compatible-for-ios-10-or-below-for-some-functi – Agung Laksana Mar 15 '18 at 05:48
  • Thanks for the code! The cropping part helped me :) – Coconuts Jun 10 '20 at 21:14
  • @Coconuts no problem, glad the code is still helpful :) – infinity_coding7 Jun 13 '20 at 01:40
0

For iOS 11.0 and lower both I handled

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)
}
karan
  • 3,150
  • 1
  • 32
  • 44
-1

Use this code (Swift 5), it is working fine for me.

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    guard let imageData = photo.fileDataRepresentation() else { return }
    let previewImage = UIImage(data: imageData)
}
nitin.agam
  • 1,354
  • 1
  • 11
  • 19
  • What's the point to suggest completely different method instead of helping to fix the one the topic starter is using? – Pavel Bogart Mar 24 '21 at 16:28
  • How can it be a different method? Just check the question and read my answer again. And if you have a solution then post it here. @PavelBogart – nitin.agam Mar 30 '21 at 11:20