Swift - AVFoundation捕获图像方向

时间:2017-10-23 15:15:12

标签: ios swift avfoundation landscape-portrait

我有一个自定义相机,以纵向模式拍照。

我的问题是,如果我尝试拍摄横向照片并保存,那么图片仍然会以纵向模式保存。

我有这个功能来设置previewLayer:

 static func setupPreviewLayer(view: UIView) {
    cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
    switch UIDevice.current.orientation {
    case .portrait:
        cameraPreviewLayer?.connection?.videoOrientation = 
       AVCaptureVideoOrientation.portrait
    case .portraitUpsideDown:
        cameraPreviewLayer?.connection?.videoOrientation = 
          AVCaptureVideoOrientation.portraitUpsideDown
    case .landscapeLeft:
        cameraPreviewLayer?.connection?.videoOrientation =
        AVCaptureVideoOrientation.landscapeLeft
    case .landscapeRight:
        cameraPreviewLayer?.connection?.videoOrientation = 
         AVCaptureVideoOrientation.landscapeRight
    default:
        cameraPreviewLayer?.connection?.videoOrientation = 
         AVCaptureVideoOrientation.portrait
    }
    cameraPreviewLayer?.frame = view.frame
    view.layer.insertSublayer(cameraPreviewLayer!, at: 0)
}

我在viewWillAppear中调用它(我认为这不是正确的方法)。

然后我拍了照片:

@IBAction func takePhotoBtnPressed(_ sender: Any) {
    let settings = AVCapturePhotoSettings()
    useFlash(settings: settings)
    settings.isAutoStillImageStabilizationEnabled = true
    CustomCamera.photoOutput?.capturePhoto(with: settings, delegate: self)
}

并使用此扩展程序:

extension FishCameraVC: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    if let imageData = photo.fileDataRepresentation() {
        image = UIImage(data: imageData)


          performSegue(withIdentifier: "ShowTakenPhoto", sender: nil)
        }
    }
}

只要我拍摄了一张肖像模式照片,但是当我旋转手机拍摄风景照片时,所有内容都能正常工作,那么照片仍会以人像拍摄。

这是我第一次使用自定义相机,我真的不知道从哪里开始修复这个... 如果有人可以提供帮助,我会非常感激。

谢谢!

--------------- UPDATE 我添加了这个功能:

func managePhotoOrientation() -> UIImageOrientation {
    var currentDevice: UIDevice
    currentDevice = .current
    UIDevice.current.beginGeneratingDeviceOrientationNotifications()
    var deviceOrientation: UIDeviceOrientation
    deviceOrientation = currentDevice.orientation

    var imageOrientation: UIImageOrientation!

    if deviceOrientation == .portrait {
        imageOrientation = .up
        print("Device: Portrait")
    }else if (deviceOrientation == .landscapeLeft){
        imageOrientation = .left
        print("Device: LandscapeLeft")
    }else if (deviceOrientation == .landscapeRight){
        imageOrientation = .right
        CustomCamera.cameraPreviewLayer?.connection?.videoOrientation = .landscapeRight
        print("Device LandscapeRight")
    }else if (deviceOrientation == .portraitUpsideDown){
        imageOrientation = .down
        print("Device PortraitUpsideDown")
    }else{
       imageOrientation = .up
    }
    return imageOrientation
}

并将我的扩展名改为:

    extension FishCameraVC: AVCapturePhotoCaptureDelegate {
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        if let imageData = photo.fileDataRepresentation() {
            image = UIImage(data: imageData)
            let dataProvider  = CGDataProvider(data: imageData as CFData)
            let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)
            self.image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: imageOrientation!)
            performSegue(withIdentifier: "ShowTakenPhoto", sender: nil)
        }
    }
}

图像以正确的方向显示在预览中,但是当我保存图像时,它会转到肖像...

3 个答案:

答案 0 :(得分:1)

您需要在调用capturePhoto()

之前运行以下代码
if let photoOutputConnection = CustomCamera.photoOutput.connection(with: AVMediaType.video) {
    photoOutputConnection.videoOrientation = videoDeviceOrientation
}

您可以使用managePhotoOrientation()函数获取videoDeviceOrientation。

答案 1 :(得分:0)

我有一个类似的问题并通过根据拍摄的照片生成新图像来修复它:

UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.draw(in: CGRect(origin: .zero, size: image.size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

显然,iOS生成的图像元数据(包括方向)不完整,一些观看者(在我的情况下是Chrome和Safari浏览器)无法正确呈现图像。通过重新渲染,似乎可以为所有观看者正确设置元数据。

注意1)在我的应用程序中我也缩小图像(我不认为这会改变效果)和2)我通过其他方式捕获图像(即UIImagePickerController);不过,你可以尝试一下我的hacky修复。

答案 2 :(得分:0)

Swift 4.2最新的AVFoundation语法捕获图像方向(经过测试的代码)。

UIGraphicsBeginImageContextWithOptions((image?.size)!, false, (image?.scale)!)
image?.draw(in: CGRect(origin: .zero, size: (image?.size)!))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()