iPhone AVFoundation摄像头方向

我一直在撕掉我的头发,试图让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使用与WWDC代码相同的writeImage …方法)

并从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试图得到这个,但它仍然只保存照片中的肖像。

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

谢谢!

奥利弗

那么,这是我永远采取了fracking,但我已经做了!

我正在寻找的代码是

 [UIDevice currentDevice].orientation; 

这是如此

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

它完美的作品:D

Woop woop!

这是不是一点点清洁?

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

以下是来自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]; 

有两件事要注意

a)Brian King写道 – 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状态,如果您尝试设置为video方向,则video将无法录制。 确保在调用[UIDevice currentDevice].orientation时不要使用它们!

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

(假设你有一个叫做“previewLayer”的AVCaptureVideoPreviewLayer实例)

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

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

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; AVCaptureConnection *videoConnection = self.prevLayer.connection; [videoConnection setVideoOrientation:(AVCaptureVideoOrientation)toInterfaceOrientation]; } 

在Swift中你应该这样做:

  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 

这对我来说非常合适!

我在Swift中编写这个代码可能是需要某人的。

步骤1:生成方向通知(在您的viewDidLoad

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

第二步:拍照。 这里我们将交换videoConnection方向。 在AVFoundation有一个小的改变方向,尤其是对于风景方向。 所以我们只是交换它。 例如,我们将从LandscapeRight更改为LandscapeLeft ,反之亦然

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

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

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

你也可以创build一个中间的CIImage,并获取属性字典

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

并相应地转换:)

我喜欢在iOS5中访问所有这些图像元数据是多么容易!

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