2010-09-07 76 views
34

我一直在撕裂我的头发,试图让AVFoundation相机以正确的方向(即设备方向)捕捉图片,但我无法使它工作。iPhone AVFoundation相机方向

我看过教程,我看过WWDC演示文稿,我已经下载了WWDC示例程序,但即使这样做也不行。

从我的应用程序中的代码是...

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来使用相同的writeImage ...方法作为WWDC代码)

和代码从WWDC应用程序是...

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]; 
                    } 
                   } 
                  }]; 

在其代码的开始,他们设置AVOrientation为纵向,这似乎很奇怪,但我想要得到它的检测设备当前的方向和使用。

正如你所看到的我已经把[UIApplication sharedApplication] statusBarOrientation尝试并获得这个,但它仍然只能保存肖像照片。

任何人都可以提供任何帮助或建议,我需要做什么?

谢谢!

Oliver

回答

44

嗯,这是带我永远fracking,但我已经做到了!

的代码,我一直在寻找该位

[UIDevice currentDevice].orientation; 

这正好为这样

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

而且它完美的作品:d

WOOP WOOP!

+2

好吧,我以为我已经修复它,但可惜我错了。它修复了在手机上显示图像并正确保存到库的问题,但是当上传到Facebook或在我的电脑上查看时,它们仍然是错误的方式:( – Fogmeister 2010-09-08 12:57:21

+2

你最终的解决方案是什么?我注意到你的文章UIDeviceOrientation和AVCaptureVideoOrientation不完全相同,LandscapeRight和LandscapeLeft在枚举中交换,我做了很长时间(如果纵向/纵向,如果横向离开/设置横向离开),我的风景图片总是颠倒过来!似乎交换是必需的,以保持映射正确,不知道如何工作。 – 2011-01-08 17:40:33

+0

嗯。对我而言,照片库中的缩略图方向会旋转,但图像本身很好。 – 2011-08-09 09:42:52

-1

如何使用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

谢谢,我明天晚上会去。直到那时才能访问我的MBP。 – Fogmeister 2010-09-13 15:38:00

4

有两件事情需要注意

一)布赖恩王写道 - LandscapeRight和LandscapeLeft枚举被交换。看到AVCamCaptureManager例如:

// 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)也有UIDeviceOrientationFaceUpUIDeviceOrientationFaceDown状态,如果你尝试设置为视频的方向,您的视频将无法记录。请确保在拨打[UIDevice currentDevice].orientation时不要使用它们!

11

以下是AVCam,我加入过它:

- (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]; 
} 

而且一定要添加到您的init方法:

NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
[notificationCenter addObserver:self 
    selector:@selector(deviceOrientationDidChange) 
    name:UIDeviceOrientationDidChangeNotification object:nil]; 
[self setOrientation:AVCaptureVideoOrientationPortrait]; 
+0

这不是一点点清洁剂吗? – 2013-09-19 15:52:06

+0

此解决方案与UIImage + fixOrientation.h一起修复了完全定向的问题 – 2015-02-05 19:01:36

0

您还可以创建一个中间CIImage,并抢属性词典

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

并据此转换:)

我很喜欢在iOS5中访问所有这些图像元数据的容易程度!

3

如果您使用AVCaptureVideoPreviewLayer,您可以在视图控制器中执行以下操作。

(假设你有一个名为 “previewLayer” AVCaptureVideoPreviewLayer的实例)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    [self.previewLayer setOrientation:[[UIDevice currentDevice] orientation]]; 
} 
+4

AVCaptureVideoPreviewLayer setOrientation:已弃用。 – 2013-02-13 17:52:05

+1

@TalYaniv在写这个回应的时候,它并没有被弃用。 – 2013-11-08 15:03:04

12

这是不是干净了一点?

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]; 
+4

可能。这个问题虽然是三岁。我甚至不记得当我问它时我正在写的应用程序:) – Fogmeister 2013-09-19 15:57:00

+0

如果我以设备横向方向捕捉它,它仍然会生成横向图像。我总是希望肖像模式下的图像。请给我建议。 – 2016-05-24 07:26:21

+0

非常感谢。它与Image + fixOrientation一起工作。 – 2016-05-24 07:43:48

1

这使用视图控制器的方向方法。这适用于我,希望能为你工作。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 

    AVCaptureConnection *videoConnection = self.prevLayer.connection; 
    [videoConnection setVideoOrientation:(AVCaptureVideoOrientation)toInterfaceOrientation]; 
} 
1

在斯威夫特,你应该这样做:

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 

它可以完美的我!

1

我写这段代码在Swift中,以防万一需要某人。

第1步:生成定向通知(在你的viewDidLoad

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

步骤2:取照片。我们将在这里交换方向videoConnection。在AVFoundation中,特别是在横向方向上有一个小的改变。所以我们只是交换它。例如,我们将改变LandscapeRightLandscapeLeft,反之亦然

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() 


     } 
    } 


    } 
} 

    } 

注:请注意景观方向的新方向值。它正好相反。 (这是罪魁祸首:: Joey:嗯)

步骤3:修复方向(延长的UIImage)

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) 
} 


    }