当预设为640x480时,为什么使用AVFoundation捕获图像会给我480x640图像?

时间:2011-08-07 22:26:15

标签: objective-c ios4 orientation avfoundation

我有一些非常基本的代码来使用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?

1 个答案:

答案 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,可以查看它的代码并去掉数据转换的部分。