在UIView的背景上设置相机 [英] Set up camera on the background of UIView

查看:121
本文介绍了在UIView的背景上设置相机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在UIViewController的UIView背景上设置相机,以便能够在它上面绘制。

I'm trying set camera on the background of UIView in UIViewController, in order to be able to draw on it.

怎么做?

推荐答案

更新SWIFT 3

您可以尝试这样的事情:

You could try something like this:

我添加两个 UIView s到我的 UIViewController 的主视图,一个名为 previewView (用于相机)和另一个 UIView 名为 boxView (位于相机视图上方)

I add two UIViews to my UIViewController's main view, one called previewView (for the camera) and another UIView called boxView (which is above the camera view)

class ViewController: UIViewController {

    var previewView : UIView!;
    var boxView:UIView!;

    //Camera Capture requiered properties
    var videoDataOutput: AVCaptureVideoDataOutput!
    var videoDataOutputQueue: DispatchQueue!
    var previewLayer:AVCaptureVideoPreviewLayer!
    var captureDevice : AVCaptureDevice!
    let session = AVCaptureSession()
    var currentFrame: CIImage!
    var done = false

    override func viewDidLoad() {
        super.viewDidLoad()
        previewView = UIView(frame: CGRect(x: 0, y: 0, width:  UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
        previewView.contentMode = UIViewContentMode.scaleAspectFit
        view.addSubview(previewView)

        //Add a box view
        boxView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 200))
        boxView.backgroundColor = UIColor.green
        boxView.alpha = 0.3
        view.addSubview(boxView)

        self.setupAVCapture()
    }

    override func viewWillAppear(_ animated: Bool) {
        if !done {
            session.startRunning()
        }
    }

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

    override var shouldAutorotate: Bool {
        if (UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft ||
        UIDevice.current.orientation == UIDeviceOrientation.landscapeRight ||
            UIDevice.current.orientation == UIDeviceOrientation.unknown) {
            return false
        }
        else {
            return true
        }
    }
}


// AVCaptureVideoDataOutputSampleBufferDelegate protocol and related methods
extension ViewController:  AVCaptureVideoDataOutputSampleBufferDelegate{
    func setupAVCapture(){
        session.sessionPreset = AVCaptureSession.Preset.vga640x480
        guard let device = AVCaptureDevice
        .default(AVCaptureDevice.DeviceType.builtInWideAngleCamera,
                 for: .video,
                 position: AVCaptureDevice.Position.front) else{
                            return
        }
        captureDevice = device
        beginSession()
        done = true
    }

    func beginSession(){
        var deviceInput: AVCaptureDeviceInput!
        do {
            deviceInput = try AVCaptureDeviceInput(device: captureDevice)
            guard deviceInput != nil else {
                print("error: cant get deviceInput")
                return
            }

            if self.session.canAddInput(deviceInput){
                self.session.addInput(deviceInput)
            }

            videoDataOutput = AVCaptureVideoDataOutput()
            videoDataOutput.alwaysDiscardsLateVideoFrames=true
            videoDataOutputQueue = DispatchQueue(label: "VideoDataOutputQueue")
            videoDataOutput.setSampleBufferDelegate(self, queue:self.videoDataOutputQueue)

            if session.canAddOutput(self.videoDataOutput){
                session.addOutput(self.videoDataOutput)
            }

            videoDataOutput.connection(withMediaType: AVMediaTypeVideo).isEnabled = true

            self.previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
            self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspect

            let rootLayer: CALayer = self.previewView.layer
            rootLayer.masksToBounds = true
            self.previewLayer.frame = rootLayer.bounds
            rootLayer.addSublayer(self.previewLayer)
            session.startRunning()
        } catch let error as NSError {
            deviceInput = nil
            print("error: \(error.localizedDescription)")
        }
    }

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        currentFrame =   self.convertImageFromCMSampleBufferRef(sampleBuffer)
    }


    // clean up AVCapture
    func stopCamera(){
        session.stopRunning()
        done = false
    }

    func convertImageFromCMSampleBufferRef(_ sampleBuffer:CMSampleBuffer) -> CIImage{
        let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
        let ciImage:CIImage = CIImage(cvImageBuffer: pixelBuffer)
        return ciImage
    }
}

您可以使用mainView的框架替换boxView的框架,并且不要设置它的背景属性。这样您就可以使用此视图添加更多子视图。

You can replace the boxView's frame with mainView's frameand don't set its background property. This way you can use this view to add more subviews.


重要

请记住,在iOS 10中,您需要首先询问用户是否有权访问相机。您可以通过在应用的 Info.plist 中添加使用
以及目的字符串来实现此目的
因为如果你没有宣布使用,你的应用程序会在
首次访问时崩溃。

Remember that in iOS 10 you need to first ask the user for permission in order to have access to the camera. You do this by adding a usage key to your app’s Info.plist together with a purpose string because if you fail to declare the usage, your app will crash when it first makes the access.

以下是显示相机访问请求的屏幕截图

Here's a screenshot to show the Camera access request

我希望这可以提供帮助!

I hope this can help!

这篇关于在UIView的背景上设置相机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆