iPhone AVFoundation camera orientation

2019-01-10 08:17发布

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 work.

I have looked at tutorials, I've watched the WWDC presentation and I've downloaded the WWDC sample program but even that doesn't do it.

The code from my app is...

AVCaptureConnection *videoConnection = [CameraVC connectionWithMediaType:AVMediaTypeVideo fromConnections:[imageCaptureOutput connections]];
if ([videoConnection isVideoOrientationSupported])
{
    [videoConnection setVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

[imageCaptureOutput captureStillImageAsynchronouslyFromConnection:videoConnection
                                                completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
{
    if (imageDataSampleBuffer != NULL)
    {
        //NSLog(@"%d", screenOrientation);

        //CMSetAttachment(imageDataSampleBuffer, kCGImagePropertyOrientation, [NSString stringWithFormat:@"%d", screenOrientation], 0);

        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [[UIImage alloc] initWithData:imageData];

        [self processImage:image];
    }
}];

(processImage uses the same writeImage... method as the WWDC code)

and the code from the WWDC app is...

AVCaptureConnection *videoConnection = [AVCamDemoCaptureManager connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
        if ([videoConnection isVideoOrientationSupported]) {
            [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
        }

[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection
                                                             completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
                                                                 if (imageDataSampleBuffer != NULL) {
                                                                     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
                                                                     UIImage *image = [[UIImage alloc] initWithData:imageData];                                                                 
                                                                     ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
                                                                     [library writeImageToSavedPhotosAlbum:[image CGImage]
                                                                                               orientation:(ALAssetOrientation)[image imageOrientation]
                                                                                           completionBlock:^(NSURL *assetURL, NSError *error){
                                                                                               if (error) {
                                                                                                   id delegate = [self delegate];
                                                                                                   if ([delegate respondsToSelector:@selector(captureStillImageFailedWithError:)]) {
                                                                                                       [delegate captureStillImageFailedWithError:error];
                                                                                                   }                                                                                               
                                                                                               }
                                                                                           }];
                                                                     [library release];
                                                                     [image release];
                                                                 } else if (error) {
                                                                     id delegate = [self delegate];
                                                                     if ([delegate respondsToSelector:@selector(captureStillImageFailedWithError:)]) {
                                                                         [delegate captureStillImageFailedWithError:error];
                                                                     }
                                                                 }
                                                             }];

At the beginning of their code they set the AVOrientation to portrait which seems very odd but I'm trying to get it to detect the device's current orientation and use that.

As you can see I have put [UIApplication sharedApplication]statusBarOrientation to try and get this but it still only save the photos in portrait.

Can anyone offer any help or advice on what I need to be doing?

Thanks!

Oliver

11条回答
女痞
2楼-- · 2019-01-10 08:58

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];
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-10 08:58

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]];
        }
    }
}
查看更多
趁早两清
4楼-- · 2019-01-10 08:59

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!

查看更多
祖国的老花朵
5楼-- · 2019-01-10 08:59

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];
查看更多
Evening l夕情丶
6楼-- · 2019-01-10 08:59

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!

查看更多
登录 后发表回答