当预设为640x480时,为什么使用AVFoundation捕获图像会给我480x640图像? [英] Why does capturing images with AVFoundation give me 480x640 images when the preset is 640x480?

查看:302
本文介绍了当预设为640x480时,为什么使用AVFoundation捕获图像会给我480x640图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些非常基本的代码来使用AVFoundation捕获静态图像。

I have some pretty basic code to capture a still image using 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:

My method that captures the still image is also pretty simple and prints out the orientation which is 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附件告诉我:

So the device understands it's in portrait mode as it should be, the exif attachements show me:

PixelXDimension = 640;
PixelYDimension = 480;

因此它似乎知道我们是640x480,这意味着WxH(显然......)

so it seems to know that we're in 640x480 and that means WxH (obviously...)

然而,当我从Apples Photos应用程序通过电子邮件将照片发送给自己时,如果我在预览中检查属性,则会得到480x640的图像。这对我来说没有任何意义,直到我进一步挖掘图像属性才发现图像方向设置为6(旋转90度CCW)我确定CCW是逆时针

However when I email the photo to myself from Apples Photos app, I get a 480x640 image if I check the properties in Preview. This didn't make any sense to me until I dug further into image properties to find out that the image orientation is set to "6 (Rotated 90 degrees CCW)" I'm sure CCW is counter clockwise

所以在浏览器中查看图片:
http://tonyamoyal.com /stuff/things_that_make_you_go_hmm/photo.JPG
我们看到图像旋转90度CCW,它是640x480。

So looking at the image in a browser: http://tonyamoyal.com/stuff/things_that_make_you_go_hmm/photo.JPG We see a the image rotated 90 degrees CCW and it is 640x480.

我真的很困惑关于这种行为。当我使用AVFoundation拍摄640x480静止图像时,我希望默认情况下没有旋转方向。我期待一个640x480的图像,就像我的眼睛看到预览图层中的图像一样。有人可以解释为什么会发生这种情况以及如何配置捕获,以便当我将图像保存到服务器以便稍后在Web视图中显示时,它不会旋转90度CCW?

I'm really confused about this behavior. When I take a 640x480 still image using AVFoundation, I would expect the default to have no rotated orientation. I expect a 640x480 image oriented exactly as my eye sees the image in the preview layer. Can someone explain why this is happening and how to configure the capture so that when I save my image to the server to later display in a web view, it is not rotated 90 degrees CCW?

推荐答案

这是因为新图像的元数据中设置的方向受创建的AV系统的方向影响它。实际图像数据的布局当然不同于元数据中提到的方向。一些图像查看程序遵循元数据方向,有些则忽略它。

This happens because the orientation set in the metadata of the new image is being effected by the orientation of the AV system that creates it. The layout of the actual image data is of course different from the orientation mentioned in your metadata. Some image viewing programs respect the metadata orientation, some ignore it.

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

You can affect the metadata orientation of the AV system by calling:

AVCaptureConnection *videoConnection = ...;
if ([videoConnection isVideoOrientationSupported])
    [videoConnection setVideoOrientation:AVCaptureVideoOrientationSomething];

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

You can affect the metadata orientation of a UIImage by calling:

UIImage *rotatedImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0f orientation:UIImageOrientationSomething];

但AVCapture系统的实际数据总是会出现更宽的尺寸为X和更窄的尺寸作为Y,并且看起来将面向LandscapeLeft。

But the actual data from the AVCapture system will always appear with the wider dimension as X and the narrower dimension as Y, and will appear to be oriented in LandscapeLeft.

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

If you want the actual data to line up with what your metadata claims, you need to modify the actual data. You can do this by writing the image out to a new image using CGContexts and AffineTransforms. Or there is an easier workaround, use the UIImage+Resize package as discussed here. And resize the image to it's current size by calling:

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

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

This will rectify the data's orientation as a side effect.

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

If you don't want to include the whole UIImage+Resize thing you can checkout it's code and strip out the parts where the data is transformed.

这篇关于当预设为640x480时,为什么使用AVFoundation捕获图像会给我480x640图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆