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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当预设为640x480时,为什么使用AVFoundation捕获图像会给我480x640图像?相关的知识,希望对你有一定的参考价值。

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

答案

发生这种情况是因为在新图像的元数据中设置的方向受创建它的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的东西,你可以查看它的代码并去掉数据转换的部分。

以上是关于当预设为640x480时,为什么使用AVFoundation捕获图像会给我480x640图像?的主要内容,如果未能解决你的问题,请参考以下文章

使用动作选择器预设将项目添加到 NSMenu

如何通过 xCode 构建设置在 iPhone 上预设地理位置?

Amazon FireTV Stick:强制 640x480 分辨率

Babel:尝试使用中继预设时出错'找不到相对于目录的预设“中继”'

为啥我的vs2010安装时不能更改路径。预设C盘

使用内联 ASM c++ 显示 640x480 BMP 图像