iPhone AVFoundation camera orientation

前端 未结 12 548
走了就别回头了
走了就别回头了 2020-12-02 09:46

I\'ve been tearing my hair out trying to get the AVFoundation camera to capture a picture in the correct orientation (i.e. the device orientation) but I can\'t get it to wor

相关标签:
12条回答
  • 2020-12-02 10:45

    Swift 4 & Swift 5.

    Here we go:

    private var requests = [VNRequest]()
    let exifOrientation = exifOrientationFromDeviceOrientation()
    let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
    do {
      try imageRequestHandler.perform(self.requests)
    } catch {
      print(error)
    }
    
    public func exifOrientationFromDeviceOrientation() -> CGImagePropertyOrientation {
        let curDeviceOrientation = UIDevice.current.orientation
        let exifOrientation: CGImagePropertyOrientation
    
        switch curDeviceOrientation {
        case UIDeviceOrientation.portraitUpsideDown:  // Device oriented vertically, home button on the top
            exifOrientation = .upMirrored
        case UIDeviceOrientation.landscapeLeft:       // Device oriented horizontally, home button on the right
            exifOrientation = .left
        case UIDeviceOrientation.landscapeRight:      // Device oriented horizontally, home button on the left
            exifOrientation = .right
        case UIDeviceOrientation.portrait:            // Device oriented vertically, home button on the bottom
            exifOrientation = .up
        default:
            exifOrientation = .up
        }
        return exifOrientation
    }
    
    0 讨论(0)
  • 2020-12-02 10:47

    there are two things to notice

    a) as Brian King wrote - LandscapeRight and LandscapeLeft are swapped in the enumeration. see AVCamCaptureManager example:

    // AVCapture and UIDevice have opposite meanings for landscape left and right (AVCapture orientation is the same as UIInterfaceOrientation)
    else if (deviceOrientation == UIDeviceOrientationLandscapeLeft)
        orientation = AVCaptureVideoOrientationLandscapeRight;
    else if (deviceOrientation == UIDeviceOrientationLandscapeRight)
        orientation = AVCaptureVideoOrientationLandscapeLeft;
    

    b) There are also UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown states, that if you try to set as the video orientation, your video will fail recording. Make sure you don't use them when calling [UIDevice currentDevice].orientation !

    0 讨论(0)
  • 2020-12-02 10:49

    Update the orientation in the preview layer after start the capture session and whenever the device is rotated.

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        coordinator.animate(alongsideTransition: { [weak self] context in
            if let connection = self?.previewLayer?.connection, connection.isVideoOrientationSupported {
                if let orientation = AVCaptureVideoOrientation(orientation: UIDevice.current.orientation) {
                    connection.videoOrientation = orientation
                }
            }
        }, completion: nil)
        super.viewWillTransition(to: size, with: coordinator)
    }
    
    extension AVCaptureVideoOrientation {
        init?(orientation: UIDeviceOrientation) {
            switch orientation {
            case .landscapeRight: self = .landscapeLeft
            case .landscapeLeft: self = .landscapeRight
            case .portrait: self = .portrait
            case .portraitUpsideDown: self = .portraitUpsideDown
            default: return nil
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 10:52

    If you're using AVCaptureVideoPreviewLayer you can do the following inside your view controller.

    (assuming you have an instance of AVCaptureVideoPreviewLayer called "previewLayer")

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
       [self.previewLayer setOrientation:[[UIDevice currentDevice] orientation]];
    }
    
    0 讨论(0)
  • 2020-12-02 10:52

    In Swift you should do this:

        videoOutput = AVCaptureVideoDataOutput()
        videoOutput!.setSampleBufferDelegate(self, queue: dispatch_queue_create("sample buffer delegate", DISPATCH_QUEUE_SERIAL))
    
        if captureSession!.canAddOutput(self.videoOutput) {
            captureSession!.addOutput(self.videoOutput)
        }
    
        videoOutput!.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = AVCaptureVideoOrientation.PortraitUpsideDown
    

    It works perfectly for me!

    0 讨论(0)
  • 2020-12-02 10:52

    You can also create an intermediate CIImage, and grab the properties dictionary

    NSDictionary *propDict = [aCIImage properties];
    NSString *orientString = [propDict objectForKey:kCGImagePropertyOrientation];
    

    And Transform accordingly :)

    I love how easy it is to access all this image metadata in iOS5!

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