我有一些非常基本的代码来使用AVFoundation捕获静态图像。
AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:nil];
AVCaptureStillImageOutput *newStillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
AVVideoCodecJPEG, AVVideoCodecKey,
nil];
[newStillImageOutput setOutputSettings:outputSettings];
[outputSettings release];
AVCaptureSession *newCaptureSession = [[AVCaptureSession alloc] init];
[newCaptureSession beginConfiguration];
newCaptureSession.sessionPreset = AVCaptureSessionPreset640x480;
[newCaptureSession commitConfiguration];
if ([newCaptureSession canAddInput:newVideoInput]) {
[newCaptureSession addInput:newVideoInput];
}
if ([newCaptureSession canAddOutput:newStillImageOutput]) {
[newCaptureSession addOutput:newStillImageOutput];
}
self.stillImageOutput = newStillImageOutput;
self.videoInput = newVideoInput;
self.captureSession = newCaptureSession;
[newStillImageOutput release];
[newVideoInput release];
[newCaptureSession release];
我捕捉静止图像的方法也非常简单,并打印出AVCaptureVideoOrientationPortrait的方向:
- (void) captureStillImage
{
AVCaptureConnection *stillImageConnection = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
if ([stillImageConnection isVideoOrientationSupported]){
NSLog(@"isVideoOrientationSupported - orientation = %d", orientation);
[stillImageConnection setVideoOrientation:orientation];
}
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:stillImageConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
ALAssetsLibraryWriteImageCompletionBlock completionBlock = ^(NSURL *assetURL, NSError *error) {
if (error) { // HANDLE }
};
if (imageDataSampleBuffer != NULL) {
CFDictionaryRef exifAttachments = CMGetAttachment(imageDataSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments) {
NSLog(@"attachements: %@", exifAttachments);
} else {
NSLog(@"no attachments");
}
self.stillImageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
self.stillImage = [UIImage imageWithData:self.stillImageData];
UIImageWriteToSavedPhotosAlbum(self.stillImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
else
completionBlock(nil, error);
}];
}
所以设备理解它应该是纵向模式,exif附件显示我:
PixelXDimension = 640;
PixelYDimension = 480;
因此它似乎知道我们处于640x480,这意味着WxH(显然......)
然而,当我从Apples Photos应用程序通过电子邮件将照片发送给自己时,如果我在预览中检查属性,则会获得480x640的图像。这对我来说没有任何意义,直到我进一步挖掘图像属性才发现图像方向设置为“6(旋转90度CCW)”我确定CCW是逆时针
所以在浏览器中查看图像: http://tonyamoyal.com/stuff/things_that_make_you_go_hmm/photo.JPG 我们看到图像旋转90度CCW,它是640x480。
我对这种行为感到很困惑。当我使用AVFoundation拍摄640x480静止图像时,我希望默认情况下没有旋转方向。我期待一个640x480的图像,就像我的眼睛看到预览图层中的图像一样。有人可以解释为什么会发生这种情况以及如何配置捕获,以便当我将图像保存到服务器以便稍后在Web视图中显示时,它不会旋转90度CCW?
答案 0 :(得分:33)
这是因为新图像元数据中设置的方向受创建它的AV系统的方向影响。当然,实际图像数据的布局与元数据中提到的方向不同。一些图像查看程序遵循元数据方向,有些则忽略它。
您可以通过调用以下方式影响AV系统的元数据方向:
AVCaptureConnection *videoConnection = ...;
if ([videoConnection isVideoOrientationSupported])
[videoConnection setVideoOrientation:AVCaptureVideoOrientationSomething];
您可以通过调用:
来影响UIImage的元数据方向UIImage *rotatedImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0f orientation:UIImageOrientationSomething];
但是AVCapture系统的实际数据总是以更宽的尺寸显示为X而更窄的尺寸显示为Y,并且看起来将面向LandscapeLeft。
如果您希望实际数据与元数据声明的内容对齐,则需要修改实际数据。您可以使用CGContexts和AffineTransforms将图像写入新图像。或者有一个更简单的解决方法。按照here所述使用UIImage + Resize包。并通过调用:
将图像调整为当前大小UIImage *rotatedImage = [image resizedImage:CGSizeMake(image.size.width, image.size.height) interpolationQuality:kCGInterpolationDefault];
这将纠正数据的方向作为副作用。
如果您不想包含整个UIImage + Resize,可以查看它的代码并去掉数据转换的部分。