2011-08-07 3 views
8

AVFoundationを使用して静止画像をキャプチャするためのかなり基本的なコードがあります。プリセットが640x480の場合、AVFoundationで画像をキャプチャすると480x640の画像が表示されるのはなぜですか?

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; 

ので、我々が640×480にいることを知っているようだ、それは幅x高(明らかに...)意味

しかし、Apples Photosアプリから写真を自分宛てにメールすると、プレビューでプロパティをチェックすると480x640の画像が表示されます。画像の向きが「6(CCW 90°回転)」に設定されていることを確認するまで、画像プロパティをさらに掘り下げるまではこれは意味をなさない。CCWは反時計回りであることを確信している。

ブラウザの画像: http://tonyamoyal.com/stuff/things_that_make_you_go_hmm/photo.JPG 画像が90度CCW回転し、640x480です。

私はこの動作について本当に混乱しています。私がAVFoundationを使って640x480の静止画を撮ると、デフォルトで回転した向きはないと思うでしょう。私は、私の目がプレビューレイヤーの画像を見ているように、640x480の画像を正確に向けると思います。誰かがこれが起こっている理由とキャプチャを設定する方法を説明して、イメージを後でWebビューに表示するためにサーバーに保存するとCCWを90度回転させないようにすることはできますか?

答えて

33

これは、新しいイメージのメタデータで設定された方向が、新しいイメージの作成時のAVシステムの方向によって影響を受けているためです。もちろん、実際の画像データのレイアウトは、メタデータで述べた方向とは異なります。一部の画像閲覧プログラムはメタデータの向きを尊重し、一部は無視します。

あなたは呼び出すことにより、AVシステムのメタデータの向きに影響を与えることができます。

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

あなたはUIImageのメタデータの向きに影響を与える可能性があり呼び出すことにより:AVCaptureから

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

しかし、実際のデータをシステムは常にXとして幅の広いディメンションとYとして狭いディメンションで表示され、LandscapeLeftで方向付けされているように見えます。

実際のデータとメタデータの主張が一致するようにするには、実際のデータを変更する必要があります。これを行うには、CGContextとAffineTransformsを使ってイメージを新しいイメージに書き出します。または、より簡単な回避策がある場合は、hereのようにUIImage + Resizeパッケージを使用してください。

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

これにより、データの向きが副作用として修正されます。

UIImage + Resizeの全体を含める必要がない場合は、コードをチェックアウトして、データが変換される部分を取り除くことができます。

+3

これ以上のupvotesが必要です。ありがとうございます – Youssef

+0

素敵な解決策! –

+0

非常に参考になりました、ありがとう! –

関連する問題