2011-08-07 1 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의 attachements해야으로 세로 모드에서의 이해 저를 보여

PixelXDimension = 640; 
PixelYDimension = 480; 

그래서 우리가 640 × 480으로하고있어 그 너비 x 높이 의미 모르는 것 같다 (분명히을 ...)

그러나 사과 사진 앱에서 나에게 사진을 이메일로 보내면 미리보기에서 속성을 확인하면 480x640 이미지가 표시됩니다. 이것은 이미지의 방향이 "6 (CCW 90도 회전)"으로 설정되었음을 알기 위해 이미지 특성을 파고들 때까지 나에게 이해가 가지 않는다. CCW가 반 시계 방향이라고 확신한다.

그래서보고있다. 브라우저의 이미지 : http://tonyamoyal.com/stuff/things_that_make_you_go_hmm/photo.JPG 이미지가 CCW로 90도 회전 한 것을 볼 수 있으며 640x480입니다.

정말이 동작에 대해 혼란스러워합니다. AVFoundation을 사용하여 640x480 스틸 이미지를 찍을 때 기본값이 회전 된 방향이 없을 것으로 예상됩니다. 내 눈이 미리보기 레이어에서 이미지를 보는 것과 똑같은 방향으로 640x480 이미지를 기대합니다. 누군가가 왜 이런 일이 일어나고 어떻게 이미지를 서버에 저장할 때 나중에 웹보기에 표시 할 수 있도록 캡처를 구성 할 수 있는지 설명 할 수 있습니까? 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에서 방향이 지정된 것처럼 보입니다.

메타 데이터의 주장과 실제 데이터가 일치하도록하려면 실제 데이터를 수정해야합니다. CGContexts와 AffineTransforms를 사용하여 새로운 이미지에 이미지를 쓰면됩니다. 또는 해결 방법이 더 쉽습니다. UIImage + Resize 패키지를 사용하십시오 (here).

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

이렇게하면 데이터의 방향이 부작용으로 수정됩니다.

UIImage + Resize의 전체 내용을 포함하고 싶지 않다면 코드를 체크 아웃하고 데이터가 변형 된 부분을 제거하십시오.

+3

더 많은 upvotes가 있어야합니다.고마워요 – Youssef

+0

좋은 솔루션 !! –

+0

매우 도움이됩니다. 감사합니다. –