AVCAPTURE image orientation

后端 未结 1 1189
抹茶落季
抹茶落季 2021-01-19 23:45

I have a view controller which allows a user to take a picture. I am setting the avcapture bounds to be the bounds of a view on screen.

Above this view I have a coll

1条回答
  •  深忆病人
    2021-01-20 00:16

    When creating the image from a portrait orientation device, you should consider that a UIImage that has been rotated 90 degrees, e.g.:

    switch UIApplication.shared.statusBarOrientation {
    case .portrait:
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .right)
    case .landscapeRight:
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .up)
    case .landscapeLeft:
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .down)
    case .portraitUpsideDown:
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .left)
    default:
        fatalError("Unexpected orientation")
    }
    

    For a complete example, see:

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var imageView: UIImageView!
        @IBOutlet weak var videoPreviewView: UIView!
        var videoPreviewLayer: AVCaptureVideoPreviewLayer!
    
        var session: AVCaptureSession = AVCaptureSession()
        var stillImageOutput: AVCaptureStillImageOutput = {
            let output = AVCaptureStillImageOutput()
            output.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
            return output
        }()
    
        var images: [UIImage] = [UIImage]()
    
        var orientation = UIApplication.shared.statusBarOrientation
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            guard let device = AVCaptureDevice.default(for: .video) else {
                print("Unable to create capture device")
                return
            }
    
            let input: AVCaptureDeviceInput
            do {
                input = try AVCaptureDeviceInput(device: device)
            } catch {
                print("Unable to create input", error)
                return
            }
    
            guard session.canAddInput(input) else {
                print("Cannot add input")
                return
            }
            session.addInput(input)
    
            guard session.canAddOutput(stillImageOutput) else {
                print("Cannot add output")
                return
            }
            session.addOutput(stillImageOutput)
    
            session.startRunning()
            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
            videoPreviewView.layer.addSublayer(videoPreviewLayer)
        }
    
        @IBAction func didTapCaptureButton(_ sender: Any) {
            if let connection = stillImageOutput.connection(with: .video) {
                stillImageOutput.captureStillImageAsynchronously(from: connection) { sampleBuffer, error in
                    guard let sampleBuffer = sampleBuffer, error == nil else {
                        print(error ?? "Unknown error")
                        return
                    }
    
                    guard
                        let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer),
                        let dataProvider = CGDataProvider(data: imageData as CFData),
                        let cgImageRef = CGImage(jpegDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else {
                            print("unable to capture image")
                            return
                    }
    
                    var image: UIImage?
    
                    switch self.orientation {
                    case .portrait:
                        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .right)
                    case .landscapeRight:
                        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .up)
                    case .landscapeLeft:
                        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .down)
                    case .portraitUpsideDown:
                        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .left)
                    default:
                        fatalError("Unexpected orientation")
                    }
    
                    guard image != nil else {
                        print("unable to create UIImage")
                        return
                    }
    
                    DispatchQueue.main.async {
                        self.images.append(image!)
                        self.imageView.image = image
                    }
                }
    
            }
        }
    
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
    
            if let connection =  self.videoPreviewLayer?.connection  {
                orientation = UIApplication.shared.statusBarOrientation
    
                switch orientation {
                case .portrait:           updatePreviewOrientation(for: connection, to: .portrait)
                case .landscapeRight:     updatePreviewOrientation(for: connection, to: .landscapeRight)
                case .landscapeLeft:      updatePreviewOrientation(for: connection, to: .landscapeLeft)
                case .portraitUpsideDown: updatePreviewOrientation(for: connection, to: .portraitUpsideDown)
                default:                  updatePreviewOrientation(for: connection, to: .portrait)
                }
            }
        }
    
        private func updatePreviewOrientation(for connection: AVCaptureConnection, to orientation: AVCaptureVideoOrientation) {
            if connection.isVideoOrientationSupported {
                connection.videoOrientation = orientation
            }
            videoPreviewLayer.frame = videoPreviewView.bounds
        }
    }
    

    You are manually converting the image orientation in fixOrientation. Once you create UIImage from CGImage using the appropriate orientation, you don't have to mess around with recreating the image if you don't want.

    0 讨论(0)
提交回复
热议问题