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
there are two things to notice
a) as Brian King wrote - LandscapeRight and LandscapeLeft are swapped in the enumeration. see AVCamCaptureManager example:
b) There are also
UIDeviceOrientationFaceUp
andUIDeviceOrientationFaceDown
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
!You can also create an intermediate CIImage, and grab the properties dictionary
And Transform accordingly :)
I love how easy it is to access all this image metadata in iOS5!
This uses the view controller's orientation method. This works for me, hopefully works for you.
If you're using AVCaptureVideoPreviewLayer you can do the following inside your view controller.
(assuming you have an instance of AVCaptureVideoPreviewLayer called "previewLayer")
I am writing this code in Swift in case may be needful for someone.
Step-1: Generate Orientation notifications (in your
viewDidLoad
)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 fromLandscapeRight
toLandscapeLeft
and viceversaNOTE: Please notice the new orientation value for Landscape orientations. Its just the opposite. (This is the culprit ::UHHHH)
Step-3: Fix orientation (UIImage extension)
Update the orientation in the preview layer after start the capture session and whenever the device is rotated.