【问题标题】:Swift - AVFoundation capture image orientationSwift - AVFoundation 捕获图像方向
【发布时间】:2022-04-22 03:41:56
【问题描述】:

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

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

我有这个功能来设置预览层:

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

只要我拍摄纵向模式的照片,一切正常,但是当我旋转手机拍摄横向照片时,照片仍然是纵向拍摄的。

这是我第一次使用定制相机,我真的不知道从哪里开始解决这个问题...... 如果有人可以提供帮助,我将不胜感激。

谢谢!

---------------更新 我已经添加了这个功能:

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

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

【问题讨论】:

标签: ios swift avfoundation landscape-portrait


【解决方案1】:

在调用 capturePhoto() 之前需要运行以下代码

if let photoOutputConnection = CustomCamera.photoOutput.connection(with: AVMediaType.video) {
    photoOutputConnection.videoOrientation = videoDeviceOrientation
}

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

【讨论】:

  • 感谢您的回答....我以苹果建议为例完全改变了我的代码...developer.apple.com/library/content/samplecode/AVCam/Listings/…
  • AVCam 是我拍摄照片的基础。您应该在该代码中看到 videoOrientation 设置
  • 我愿意...您的答案确实是正确的...如果有人需要,请发表评论以分享链接...但我想我可以接受答案...
【解决方案2】:

我遇到了类似的问题,并通过根据拍摄的照片生成新图像来解决它:

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 fix。

【讨论】:

  • 感谢您的回答。问题是即使我绘制了新图像,它仍然处于纵向模式...问题似乎是当我旋转手机时它不会添加新的预览层...
  • 澄清一下:所以图像是在应用程序中拍摄在应用程序中显示并且仍然有错误的方向?
  • No....在应用程序中它具有正确的方向但是当我保存它时它会变成纵向...我已经更改了一些代码...我会更新我的回答
  • 我明白了...我仍然会尝试使用图形上下文重新渲染图像,因为这会根据UIImage 的框架自动设置方向。如果这不起作用,我就没有主意了——对不起。
  • 我试过了......但什么都没有......好吧,我会尝试更深入地研究......谢谢你的尝试! :)
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    基于dr_barto源代码我为UIImage写了一个扩展:

    extension UIImage {
        var orientationCorrectedImage: UIImage? {
            UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
            self.draw(in: CGRect(origin: .zero, size: self.size))
            let result = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return result
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2017-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多