修复自定义相机应用iOS的方向

时间:2019-07-19 04:51:24

标签: ios swift iphone camera

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

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

浏览了以前的帖子,例如: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


}

2 个答案:

答案 0 :(得分:0)

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

第2步:如果是,请设置AVCaptureConnection纵向或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()
                })

            }
        }


    }
}

答案 1 :(得分:0)

我已通过

更改了方向
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 0.5)).scaledBy(x: scale, y: -scale))

captureConnection?.videoOrientation = .landscapeRight

这是我使用landscapeRight检测对象的演示。