Reputation: 478
My iPad app can only be used in landscape orientations. After what feels like I've looked at dozens of stack answers, I am unable to properly take a photo the right way up (the meta data corrects it but is only useful on macs). When the app is physically in LandscapeLeft it returns an upside down photo, whereas in LandscapeRight, it's correct.
As far as I can tell, setting VideoOrientation for the preview layer provides me the correct orientation when previewing the photo.
_capturePreview = [[ISCapturePreview alloc] init];
[self addSubview:_capturePreview];
// Session
self.session = [AVCaptureSession new];
[self.session setSessionPreset:AVCaptureSessionPresetPhoto];
// Capture device
AVCaptureDevice* inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
// Device input
self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if ( [self.session canAddInput:self.deviceInput] )
[self.session addInput:self.deviceInput];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
// Preview
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
[previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[previewLayer.connection setVideoOrientation:(AVCaptureVideoOrientation)orientation];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self capturePreview] layer];
[rootLayer setMasksToBounds:YES];
[previewLayer setFrame:CGRectMake(0, 0, 1024, 600)];
[rootLayer insertSublayer:previewLayer atIndex:0];
AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
if ([self.session canAddOutput:stillImageOutput])
{
[stillImageOutput setOutputSettings:@{AVVideoCodecKey : AVVideoCodecJPEG}];
[self.session addOutput:stillImageOutput];
[self setStillImageOutput:stillImageOutput];
}
[self.session startRunning];
And the output code is here. Setting the VideoOrientation here in my tests has no impact.
- (void)takePhotoButtonWasPressed:(id)sender{
[[[self stillImageOutput] connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:[[(AVCaptureVideoPreviewLayer *)[[self capturePreview] layer] connection] videoOrientation]];
// Capture a still image.
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:[[self stillImageOutput] connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer)
{
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
}];}
Upvotes: 0
Views: 392
Reputation: 420
I currently cannot test the code myself, but if you set the available orientations (in the project settings) to both landscapeLeft and landscapeRight, iOS might be handling the orientation itself, so try not setting the orientation. Furthermore if you change the orientation of the device after the view has loaded, you will be using the wrong orientation, so think of adding an observer to check for changes. In addition apple says you should use UITraitCollection
and UITraitEnvironment
instead of UIInterfaceOrientation
starting with iOS8.
I hope this helps you :)
Upvotes: 0