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

Ton*_*ony 8 objective-c avfoundation orientation ios4

我有一些非常基本的代码来使用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];
Run Code Online (Sandbox Code Playgroud)

我捕获静止图像的方法也非常简单,并打印出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);

                                                         }];
}
Run Code Online (Sandbox Code Playgroud)

所以设备理解它应该是纵向模式,exif附件告诉我:

PixelXDimension = 640;
PixelYDimension = 480;
Run Code Online (Sandbox Code Playgroud)

所以它似乎知道我们在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?

小智 33

发生这种情况是因为在新图像的元数据中设置的方向受到创建它的AV系统的方向的影响.实际图像数据的布局当然不同于元数据中提到的方向.一些图像查看程序尊重元数据方向,有些则忽略它.

您可以通过调用以下方式影响AV系统的元数据方向:

AVCaptureConnection *videoConnection = ...;
if ([videoConnection isVideoOrientationSupported])
    [videoConnection setVideoOrientation:AVCaptureVideoOrientationSomething];
Run Code Online (Sandbox Code Playgroud)

您可以通过调用以下内容来影响UIImage的元数据方向:

UIImage *rotatedImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0f orientation:UIImageOrientationSomething];
Run Code Online (Sandbox Code Playgroud)

但是来自AVCapture系统的实际数据将始终显示为更宽的尺寸为X,更窄的尺寸为Y,并且看起来将面向LandscapeLeft.

如果您希望实际数据与元数据声明的内容对齐,则需要修改实际数据.您可以使用CGContexts和AffineTransforms将图像写入新图像.或者有一个更简单的解决方法,使用这里讨论的UIImage + Resize包.并通过调用以下内容将图像调整为当前大小:

UIImage *rotatedImage = [image resizedImage:CGSizeMake(image.size.width, image.size.height) interpolationQuality:kCGInterpolationDefault];
Run Code Online (Sandbox Code Playgroud)

这将纠正数据的方向作为副作用.

如果你不想包含整个UIImage + Resize的东西,你可以检查它的代码并去掉数据转换的部分.

  • 这应该有更多的赞成.谢了哥们 (3认同)