2016-06-16 6 views
27

pracuję na wykorzystaniu własnego aparatu, a ja niedawno uaktualniony do Xcode 8 Beta wraz z Swift 3. I pierwotnie miał to:Jak korzystać AVCapturePhotoOutput

var stillImageOutput: AVCaptureStillImageOutput? 

Jednak teraz jestem coraz ostrzeżenie :

'AVCaptureStillImageOutput' was deprecated in iOS 10.0: Use AVCapturePhotoOutput instead

Ponieważ jest to dość nowe, nie widziałem wiele informacji na ten temat. Tu jest mój bieżący kod:

var captureSession: AVCaptureSession? 
var stillImageOutput: AVCaptureStillImageOutput? 
var previewLayer: AVCaptureVideoPreviewLayer? 

func clickPicture() { 

    if let videoConnection = stillImageOutput?.connection(withMediaType: AVMediaTypeVideo) { 

     videoConnection.videoOrientation = .portrait 
     stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) -> Void in 

      if sampleBuffer != nil { 

       let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer) 
       let dataProvider = CGDataProvider(data: imageData!) 
       let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent) 

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

      } 

     }) 

    } 

} 

Próbowałem spojrzeć na AVCapturePhotoCaptureDelegate, ale nie jestem pewien, jak go używać. Czy ktoś wie, jak tego użyć? Dzięki.

+0

Musisz zobaczyć sesję WWDC 2016 511 wideo .. –

+0

Ohk! Więc obejrzę wideo i opublikuję odpowiedź, jeśli będę mógł. Dzięki! – penatheboss

+0

Spojrzenie na [docs] (http://developer.apple.com/reference/AVFoundation/AVCapturePhotoOutput) również może pomóc. – rickster

Odpowiedz

39

Aktualizacja do Swift 4 Hi jest bardzo łatwy w użyciu AVCapturePhotoOutput.

Potrzebujesz AVCapturePhotoCaptureDelegate, który zwraca CMSampleBuffer.

można dostać, jak również obraz podglądu jeśli powiesz AVCapturePhotoSettings się previewFormat

class CameraCaptureOutput: NSObject, AVCapturePhotoCaptureDelegate { 

     let cameraOutput = AVCapturePhotoOutput() 

     func capturePhoto() { 

      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) 

     } 

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {       
      if let error = error { 
       print(error.localizedDescription) 
      } 

      if let sampleBuffer = photoSampleBuffer, let previewBuffer = previewPhotoSampleBuffer, let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) { 
       print(image: UIImage(data: dataImage).size) // Your Image 
      } 

     } 

    } 

Więcej informacji można znaleźć https://developer.apple.com/reference/AVFoundation/AVCapturePhotoOutput

Uwaga: Musisz dodać AVCapturePhotoOutput do AVCaptureSession przed wykonaniem zdjęcia . Więc coś takiego: session.addOutput(output), a następnie: output.capturePhoto(with:settings, delegate:self) Dzięki @BigHeadCreations

+7

Daje błąd: "[Wykrywanie AVCapturePhotoOutputPhotoWithSettings: delegate:] Brak aktywnego i włączonego połączenia wideo". Czy mógłbyś podać pełny przykład dla iOS 10/Swift 3. –

+0

@TuomasLaatikainen prawdopodobnie będziesz musiał ustawić wstępne ustawienie sesji przechwytywania na AVCaptureSessionPresetPhoto –

+0

Oglądałem wideo, surfowałem po Internecie, przepisałem kod, zmieniłem iPhone'y i nie mogę rozwiązać wyjątek "Brak aktywnego i włączonego połączenia wideo". Dokument Apple jest klasycznie niejasny i pozbawiony szczegółów. Wsparcie! Czy istnieje działający projekt do udostępnienia? – mobibob

28

Nie ma moje pełne wdrożenie

import UIKit 
import AVFoundation 

class ViewController: UIViewController, AVCapturePhotoCaptureDelegate { 

var captureSesssion : AVCaptureSession! 
var cameraOutput : AVCapturePhotoOutput! 
var previewLayer : AVCaptureVideoPreviewLayer! 

@IBOutlet weak var capturedImage: UIImageView! 
@IBOutlet weak var previewView: UIView! 

override func viewDidLoad() { 
    super.viewDidLoad() 
    captureSesssion = AVCaptureSession() 
    captureSesssion.sessionPreset = AVCaptureSessionPresetPhoto 
    cameraOutput = AVCapturePhotoOutput() 

    let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) 

    if let input = try? AVCaptureDeviceInput(device: device) { 
     if (captureSesssion.canAddInput(input)) { 
      captureSesssion.addInput(input) 
      if (captureSesssion.canAddOutput(cameraOutput)) { 
       captureSesssion.addOutput(cameraOutput) 
       previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion) 
       previewLayer.frame = previewView.bounds 
       previewView.layer.addSublayer(previewLayer) 
       captureSesssion.startRunning() 
      } 
     } else { 
      print("issue here : captureSesssion.canAddInput") 
     } 
    } else { 
     print("some problem here") 
    } 
} 

// Take picture button 
@IBAction func didPressTakePhoto(_ sender: UIButton) { 
    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 
    cameraOutput.capturePhoto(with: settings, delegate: self) 
} 

// callBack from take picture 
func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) { 

    if let error = error { 
     print("error occure : \(error.localizedDescription)") 
    } 

    if let sampleBuffer = photoSampleBuffer, 
     let previewBuffer = previewPhotoSampleBuffer, 
     let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) { 
     print(UIImage(data: dataImage)?.size as Any) 

     let dataProvider = CGDataProvider(data: dataImage as CFData) 
     let cgImageRef: CGImage! = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent) 
     let image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right) 

     self.capturedImage.image = image 
    } else { 
     print("some error here") 
    } 
} 

// This method you can use somewhere you need to know camera permission state 
func askPermission() { 
    print("here") 
    let cameraPermissionStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) 

    switch cameraPermissionStatus { 
    case .authorized: 
     print("Already Authorized") 
    case .denied: 
     print("denied") 

     let alert = UIAlertController(title: "Sorry :(" , message: "But could you please grant permission for camera within device settings", preferredStyle: .alert) 
     let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil) 
     alert.addAction(action) 
     present(alert, animated: true, completion: nil) 

    case .restricted: 
     print("restricted") 
    default: 
     AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { 
      [weak self] 
      (granted :Bool) -> Void in 

      if granted == true { 
       // User granted 
       print("User granted") 
DispatchQueue.main.async(){ 
      //Do smth that you need in main thread 
      } 
      } 
      else { 
       // User Rejected 
       print("User Rejected") 

DispatchQueue.main.async(){ 
      let alert = UIAlertController(title: "WHY?" , message: "Camera it is the main feature of our application", preferredStyle: .alert) 
       let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil) 
       alert.addAction(action) 
       self?.present(alert, animated: true, completion: nil) 
      } 
      } 
     }); 
    } 
} 
} 
+3

działa idealnie dla mnie (testowanie na iPhone 7 plus) – aBikis

+0

W jaki sposób ustawiłeś dla niego tryb flashMode? – coolly

+0

Praca na iOS 10.0.2. Aby włączyć flash 'settings.flashMode = .on' –

2

Funkcja capture delegat został zmieniony na photoOutput. Oto zaktualizowana funkcja dla Swift 4.

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {    
     if let error = error { 
      print(error.localizedDescription) 
     } 

     if let sampleBuffer = photoSampleBuffer, let previewBuffer = previewPhotoSampleBuffer, let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) { 
      print("image: \(String(describing: UIImage(data: dataImage)?.size))") // Your Image 
     } 
}