iPhone AVFoundation camera orientation

前端 未结 12 547
走了就别回头了
走了就别回头了 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:31

    Well, it's taken me fracking forever but I've done it!

    The bit of code I was looking for is

    [UIDevice currentDevice].orientation;
    

    This goes in as so

    AVCaptureConnection *videoConnection = [CameraVC connectionWithMediaType:AVMediaTypeVideo fromConnections:[imageCaptureOutput connections]];
    if ([videoConnection isVideoOrientationSupported])
    {
        [videoConnection setVideoOrientation:[UIDevice currentDevice].orientation];
    }
    

    And it works perfectly :D

    Woop woop!

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

    How to use with AVCaptureFileOutput ?

    - (void)detectVideoOrientation:(AVCaptureFileOutput *)captureOutput {
        for(int i = 0; i < [[captureOutput connections] count]; i++) {
            AVCaptureConnection *captureConnection = [[captureOutput connections] objectAtIndex:i];
            if([captureConnection isVideoOrientationSupported]) {
                [captureConnection setVideoOrientation:[[UIDevice currentDevice] orientation]];
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 10:36

    The following is from AVCam, I added too it:

    - (void)deviceOrientationDidChange{
    
        UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
    
        AVCaptureVideoOrientation newOrientation;
    
        if (deviceOrientation == UIDeviceOrientationPortrait){
            NSLog(@"deviceOrientationDidChange - Portrait");
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
        else if (deviceOrientation == UIDeviceOrientationPortraitUpsideDown){
            NSLog(@"deviceOrientationDidChange - UpsideDown");
            newOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
        }
    
        // AVCapture and UIDevice have opposite meanings for landscape left and right (AVCapture orientation is the same as UIInterfaceOrientation)
        else if (deviceOrientation == UIDeviceOrientationLandscapeLeft){
            NSLog(@"deviceOrientationDidChange - LandscapeLeft");
            newOrientation = AVCaptureVideoOrientationLandscapeRight;
        }
        else if (deviceOrientation == UIDeviceOrientationLandscapeRight){
            NSLog(@"deviceOrientationDidChange - LandscapeRight");
            newOrientation = AVCaptureVideoOrientationLandscapeLeft;
        }
    
        else if (deviceOrientation == UIDeviceOrientationUnknown){
            NSLog(@"deviceOrientationDidChange - Unknown ");
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
    
        else{
            NSLog(@"deviceOrientationDidChange - Face Up or Down");
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
    
        [self setOrientation:newOrientation];
    }
    

    And be sure to add this to your init method:

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [notificationCenter addObserver:self
        selector:@selector(deviceOrientationDidChange) 
        name:UIDeviceOrientationDidChangeNotification object:nil];
    [self setOrientation:AVCaptureVideoOrientationPortrait];
    
    0 讨论(0)
  • 2020-12-02 10:36

    This uses the view controller's orientation method. This works for me, hopefully works for you.

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    
        AVCaptureConnection *videoConnection = self.prevLayer.connection;
        [videoConnection setVideoOrientation:(AVCaptureVideoOrientation)toInterfaceOrientation];
    }
    
    0 讨论(0)
  • 2020-12-02 10:37

    Isn't this a little cleaner?

        AVCaptureVideoOrientation newOrientation;
        switch ([[UIDevice currentDevice] orientation]) {
        case UIDeviceOrientationPortrait:
            newOrientation = AVCaptureVideoOrientationPortrait;
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            newOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
            break;
        case UIDeviceOrientationLandscapeLeft:
            newOrientation = AVCaptureVideoOrientationLandscapeRight;
            break;
        case UIDeviceOrientationLandscapeRight:
            newOrientation = AVCaptureVideoOrientationLandscapeLeft;
            break;
        default:
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
        [stillConnection setVideoOrientation: newOrientation];
    
    0 讨论(0)
  • 2020-12-02 10:37

    I am writing this code in Swift in case may be needful for someone.

    Step-1: Generate Orientation notifications (in yourviewDidLoad)

        UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("deviceOrientationDidChange:"), name: UIDeviceOrientationDidChangeNotification, object: nil)
    

    Step-2: Take picture. Here we will interchange orientation of videoConnection. In AVFoundation there is a minor change in orientation especially for landscape orientation. So we will just interchange it. For example we will change from LandscapeRight to LandscapeLeft and viceversa

      func takePicture() {
    if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
    
        var newOrientation: AVCaptureVideoOrientation?
        switch (UIDevice.currentDevice().orientation) {
        case .Portrait:
            newOrientation = .Portrait
            break
        case .PortraitUpsideDown:
            newOrientation = .PortraitUpsideDown
            break
        case .LandscapeLeft:
            newOrientation = .LandscapeRight
            break
        case .LandscapeRight:
            newOrientation = .LandscapeLeft
            break
        default :
            newOrientation = .Portrait
            break
    
        }
        videoConnection.videoOrientation = newOrientation!
    
    
      stillImageOutput!.captureStillImageAsynchronouslyFromConnection(videoConnection) {
        (imageDataSampleBuffer, error) -> Void in
    
        let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
    
          dispatch_async(dispatch_get_main_queue()) {
    
            let image = UIImage(data: imageData!)!
            let portraitImage = image.fixOrientation()
    
    
          }
        }
    
    
      }
    }
    
      }
    

    NOTE: Please notice the new orientation value for Landscape orientations. Its just the opposite. (This is the culprit ::UHHHH)

    Step-3: Fix orientation (UIImage extension)

    extension UIImage {
    
    func fixOrientation() -> UIImage {
    
        if imageOrientation == UIImageOrientation.Up {
            return self
        }
    
        var transform: CGAffineTransform = CGAffineTransformIdentity
    
        switch imageOrientation {
        case UIImageOrientation.Down, UIImageOrientation.DownMirrored:
            transform = CGAffineTransformTranslate(transform, size.width, size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
            break
        case UIImageOrientation.Left, UIImageOrientation.LeftMirrored:
            transform = CGAffineTransformTranslate(transform, size.width, 0)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
            break
        case UIImageOrientation.Right, UIImageOrientation.RightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
            break
        case UIImageOrientation.Up, UIImageOrientation.UpMirrored:
            break
        }
    
        switch imageOrientation {
        case UIImageOrientation.UpMirrored, UIImageOrientation.DownMirrored:
            CGAffineTransformTranslate(transform, size.width, 0)
            CGAffineTransformScale(transform, -1, 1)
            break
        case UIImageOrientation.LeftMirrored, UIImageOrientation.RightMirrored:
            CGAffineTransformTranslate(transform, size.height, 0)
            CGAffineTransformScale(transform, -1, 1)
        case UIImageOrientation.Up, UIImageOrientation.Down, UIImageOrientation.Left, UIImageOrientation.Right:
            break
        }
    
        let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(size.width), Int(size.height), CGImageGetBitsPerComponent(CGImage), 0, CGImageGetColorSpace(CGImage), CGImageAlphaInfo.PremultipliedLast.rawValue)!
    
        CGContextConcatCTM(ctx, transform)
    
        switch imageOrientation {
        case UIImageOrientation.Left, UIImageOrientation.LeftMirrored, UIImageOrientation.Right, UIImageOrientation.RightMirrored:
            CGContextDrawImage(ctx, CGRectMake(0, 0, size.height, size.width), CGImage)
            break
        default:
            CGContextDrawImage(ctx, CGRectMake(0, 0, size.width, size.height), CGImage)
            break
        }
    
        let cgImage: CGImageRef = CGBitmapContextCreateImage(ctx)!
    
        return UIImage(CGImage: cgImage)
    }
    
    
       }
    
    0 讨论(0)
提交回复
热议问题