ios - 修复自定义相机应用程序 iOS 的方向

标签 ios swift iphone camera

基于自定义相机教程:https://github.com/brianadvent/CustomCamera

尝试从中构建。观察到相机没有按预期旋转。应用程序在纵向模式下运行完美,但在横向模式下它以意外模式运行。在横向模式下,相机 View 不像默认相机那样平移。

查看之前的帖子:cannot change AVCaptureVideoDataOutput orientation

但是这些过时的帖子。因此不得不重新发布。

竖屏截图: enter image description here

横屏模式截图: enter image description here

以下是ViewController.swift的代码。

import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
    let captureSession = AVCaptureSession()
    var previewLayer:CALayer!
    var captureDevice:AVCaptureDevice!
    var takePhoto = false

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        prepareCamera()
    }

    func prepareCamera() {
        captureSession.sessionPreset = AVCaptureSession.Preset.photo
        if let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices.first {
            captureDevice = availableDevices
            beginSession()
        }
    } // prepareCamera

    func beginSession () {
        do {
            let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
            captureSession.addInput(captureDeviceInput)
        }catch {
            print(error.localizedDescription)
        }

        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

        self.previewLayer = previewLayer
        self.view.layer.addSublayer(self.previewLayer)
        self.previewLayer.frame = self.view.layer.frame
        captureSession.startRunning()

        let dataOutput = AVCaptureVideoDataOutput()
        dataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString):NSNumber(value:kCVPixelFormatType_32BGRA)] as [String : Any]
        dataOutput.alwaysDiscardsLateVideoFrames = true

        if captureSession.canAddOutput(dataOutput) {
            captureSession.addOutput(dataOutput)
        }

        captureSession.commitConfiguration()


        let queue = DispatchQueue(label: "com.brianadvent.captureQueue")
        dataOutput.setSampleBufferDelegate(self, queue: queue)
    }

    @IBAction func takePhoto(_ sender: Any) {
        takePhoto = true

    }

    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        if takePhoto {
            takePhoto = false

            if let image = self.getImageFromSampleBuffer(buffer: sampleBuffer) {

                let photoVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoVC") as! PhotoViewController
                photoVC.takenPhoto = image
                DispatchQueue.main.async {
                    self.present(photoVC, animated: true, completion: { 
                        self.stopCaptureSession()
                    })
                } // dispatch
            } // if image
        } //takePhoto
    } // captureOutput


    func getImageFromSampleBuffer (buffer:CMSampleBuffer) -> UIImage? {
        if let pixelBuffer = CMSampleBufferGetImageBuffer(buffer) {
            let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
            let context = CIContext()

            let imageRect = CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))

            if let image = context.createCGImage(ciImage, from: imageRect) {
                return UIImage(cgImage: image, scale: UIScreen.main.scale, orientation: .right)
            }
        } // if pixelBuffer

        return nil
    } // getImageFromSampleBuffer

    func stopCaptureSession () {
        self.captureSession.stopRunning()

        if let inputs = captureSession.inputs as? [AVCaptureDeviceInput] {
            for input in inputs {
                self.captureSession.removeInput(input)
            }
        }

    } // stopCaptureSession


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    } // didReceiveMemoryWarning


}

最佳答案

第 1 步:检查 AVCaptureConnection 是否支持 VideoOrientation

第二步:如果是,设置AVCaptureConnection portrait或landscapeRight的VideoOrientation。

替换成这个函数你的问题就解决了。

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {

    if takePhoto {
        takePhoto = false
        if connection.isVideoOrientationSupported {
            connection.videoOrientation = UIDevice.current.orientation == .portrait ? .portrait : .landscapeRight
        }
        if let image = self.getImageFromSampleBuffer(buffer: sampleBuffer) {

            let photoVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoVC") as! PhotoViewController

            photoVC.takenPhoto = image

            DispatchQueue.main.async {
                self.present(photoVC, animated: true, completion: {
                    self.stopCaptureSession()
                })

            }
        }


    }
}

关于ios - 修复自定义相机应用程序 iOS 的方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57105723/

相关文章:

ios - 如何跳过登录 View Controller ?

ios - 如何检查数组中重复的内容?

ios - swift 崩溃 : function signature specialization <Arg[0] = Owned To Guaranteed>

iphone - UITableView - 方法未被调用

ios - AFNetworking 连接检测并返回一个变量

swift - 我可以使用 willSet 构造类实例字典条目吗?

ios - iAd Banner 未显示在已批准的 iPhone 应用程序中

android - 接收短信并处理内容

iphone - 在 iPad 中,当从弹出窗口内的另一个 View 导航回来时,表格 View 会显示更多记录

ios - 登录Parse后加载账户信息