ios - 结果图像方向的 AVFoundation CaptureStillImage 问题

标签 ios swift avfoundation

我有一个自定义相机 View Controller ,它使用 AVFoundation 来捕获静止图像,您可以在此处看到:Capture Preview

我的问题是,一旦我捕捉到图像,方向总是横向的,您可以在这里看到 Captured Image

我的代码如下:

    var captureInput: AVCaptureInput?
    var stillImageOutput: AVCaptureStillImageOutput?
    var previewLayer: AVCaptureVideoPreviewLayer?
    var currentDevice: AVCaptureDevice?
    var currentLayer: AVCaptureVideoPreviewLayer?

    @IBAction func captureButtonTap(sender: UIButton) {
        if(!capturingPhoto){
        capturingPhoto = true
        if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            videoConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
            self.stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {(sampleBuffer, error) in
                if (sampleBuffer != nil) {
                    var imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
                    var image = UIImage(data: imageData)
                    var imageWidth = image?.size.width
                    var cropRect = CGRect(x: 0, y: 0, width: imageWidth!, height: imageWidth!)
                    var imageRef: CGImageRef = CGImageCreateWithImageInRect(image!.CGImage, cropRect)
                    var croppedImage: UIImage = UIImage(CGImage: imageRef)!
                    self.imagePreview.image = croppedImage
                    self.image = croppedImage
                    self.switchModeToPreview()
                }
            })
            }
            }
        }
    }

        func initCameraSession(){
        configureDevice()
        NSLog(String(selectedCamera))
        captureSession = AVCaptureSession()
        captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
        if(selectedCamera == 0){
            var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
            currentDevice = backCamera
        }else if(selectedCamera == 1){
            var frontCamera = frontCameraIfAvalible()
            currentDevice = frontCamera
        }
        if(currentDevice == nil){
            NSException(name: "Error", reason: "Device Has No Camera.", userInfo: nil)
        }
        updateButtons()

        var error: NSError?
        var input = AVCaptureDeviceInput(device: currentDevice, error: &error)

        if error == nil && captureSession!.canAddInput(input) {
            captureSession!.addInput(input)
            captureInput = input
            stillImageOutput = AVCaptureStillImageOutput()
            stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
            if captureSession!.canAddOutput(stillImageOutput) {
                captureSession!.addOutput(stillImageOutput)
                previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
                previewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
                previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
                cameraPreview.layer.addSublayer(previewLayer)
                previewLayer?.frame = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.width, height: self.view.bounds.width + 139)
                if(currentLayer != nil){
                    currentLayer!.removeFromSuperlayer()
                }
                currentLayer = previewLayer!
                captureSession!.startRunning()
            }
        }
    }

请注意,我故意遗漏了一些代码,如果您需要更多信息,请提出要求。感谢您的帮助。

最佳答案

尝试使用类似这样的东西,当我旋转设备时,我用它来变换 View 上的按钮。这可以与拍摄的图像一起使用。如果您曾经上过线性代数类(class),请记忆一下您的标准变换旋转矩阵。基本上,只需更改此代码以旋转您捕获的图像的框架,然后确保将其框架边界设置回 View 的框架,以便使其正确适合 View 。这可能比需要的更复杂,但我以前从未遇到过图像问题。请记住,这是由于已注册的旋转更改观察器而被调用的,您可能不需要使用它。但是这个基本概念被大量使用

每当我遇到旋转问题时,我都会使用它。

/**************************************************************************
    DEVICE ORIENTATION DID CHANGE
    **************************************************************************/
    func deviceOrientationDidChange() {

        println("DEVICE ORIENTATION DID CHANGE CALLED")

        let orientation: UIDeviceOrientation = UIDevice.currentDevice().orientation

        //------ IGNORE THESE ORIENTATIONS ------
        if orientation == UIDeviceOrientation.FaceUp || orientation == UIDeviceOrientation.FaceDown || orientation == UIDeviceOrientation.Unknown || orientation == UIDeviceOrientation.PortraitUpsideDown || self.currentOrientation == orientation {

            println("device orientation does not need to change --- returning...")

            return
        }


        self.currentOrientation = orientation


        //------ APPLY A ROTATION USING THE STANDARD ROTATION TRANSFORMATION MATRIX in R3 ------

        /*

            x       y       z
            ---           ---
        x | cosø    sinø    0 |
        y | -sinø   consø   0 |
        z | 0       0       1 |
            ---           ---

        */

        //----- PERFORM BUTTON AND VIDEO DATA BUFFER ROTATIONS ------

        switch orientation {

        case UIDeviceOrientation.Portrait:

            println("Device Orientation Portrait")

            if self.usingFrontCamera == true {
            }
            else {

                self.playBackTransformation = CGAffineTransformMakeRotation(self.degrees0)
                self.switchCaptureSession.transform = self.playBackTransformation!
                self.switchCaptureSession.frame = self.view.bounds
                self.flipCamera.transform = self.playBackTransformation!
                self.flipCamera.frame = self.view.bounds
                self.captureButton.transform = self.playBackTransformation!
                self.captureButton.frame = self.view.bounds
            }

            break

        case UIDeviceOrientation.LandscapeLeft:

            println("Device Orientation LandScapeLeft")

            if self.usingFrontCamera == true {
            }
            else {

                self.playBackTransformation = CGAffineTransformMakeRotation(CGFloat(self.degrees90))
                self.switchCaptureSession.transform = self.playBackTransformation!
                self.switchCaptureSession.frame = self.view.bounds
                self.flipCamera.transform = self.playBackTransformation!
                self.flipCamera.frame = self.view.bounds
                self.captureButton.transform = self.playBackTransformation!
                self.captureButton.frame = self.view.bounds
            }

            break

        case UIDeviceOrientation.LandscapeRight:

            println("Device Orientation LandscapeRight")

            if self.usingFrontCamera == true {
            }
            else {

                self.playBackTransformation = CGAffineTransformMakeRotation(-self.degrees90)
                self.switchCaptureSession.transform = self.playBackTransformation!
                self.switchCaptureSession.frame = self.view.bounds
                self.flipCamera.transform = self.playBackTransformation!
                self.flipCamera.frame = self.view.bounds
                self.captureButton.transform = self.playBackTransformation!
                self.captureButton.frame = self.view.bounds
            }

            break

        default:

            break
        }

仿射变换非常适合旋转。可能有一个功能可以在捕获时设置默认图像方向。查看 Apple 的引用资料。

关于ios - 结果图像方向的 AVFoundation CaptureStillImage 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30239628/

相关文章:

ios - Swift - prepareForSegue 不工作

ios - 如何在 iPhone 4/4S 屏幕的指定部分设置摄像头?

ios - 设置UILabel的背景为透明黑色

ios - ReactiveCocoa 中的 Map 或 flattenMap

ios - 访问 AWS Cognito 用户的自定义属性

objective-c - 如何防止触摸击中 SKCropNode 中的隐藏内容?

ios - 类型 'AVCaptureDevice' 的值没有成员 'supporteddepthdataformats'

iphone - 视频直播需要什么样的服务器?

ios - 无法让平移手势工作

ios - 动态调整 UITableView 的大小,它将显示为不可滚动的内容列表