2011-08-07 16 views
8

Tengo un código bastante básico para capturar una imagen fija usando AVFoundation.¿Por qué la captura de imágenes con AVFoundation me da 480x640 imágenes cuando el valor predeterminado es 640x480?

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]; 

Mi método que captura la imagen fija también es bastante simple e imprime la orientación que es 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); 

                 }]; 
} 

Así que el dispositivo entiende que es en modo vertical como debe ser, los archivos adjuntos EXIF mostrarme:

PixelXDimension = 640; 
PixelYDimension = 480; 

por lo que parece saber que estamos en 640x480 y eso significa ancho x alto (obviamente ...)

Sin embargo, cuando me envío la foto por correo electrónico desde la aplicación Apples Photos, obtengo una imagen de 480x640 si reviso las propiedades en Vista previa. Esto no tenía ningún sentido para mí hasta que profundicé en las propiedades de la imagen para descubrir que la orientación de la imagen está configurada en "6 (Giro 90 grados en sentido contrario a las agujas del reloj)" Estoy seguro CCW en sentido antihorario

Así que mirando la imagen en un navegador: http://tonyamoyal.com/stuff/things_that_make_you_go_hmm/photo.JPG Vemos una imagen girada 90 grados CCW y es 640x480.

Estoy muy confundido acerca de este comportamiento. Cuando tomo una imagen fija de 640x480 usando AVFoundation, esperaría que el valor predeterminado no tenga una orientación girada. Espero una imagen de 640x480 orientada exactamente como mi ojo ve la imagen en la capa de vista previa. ¿Alguien puede explicar por qué sucede esto y cómo configurar la captura para que cuando guarde mi imagen en el servidor y luego se muestre en una vista web, no se gire 90 grados en sentido contrario a las agujas del reloj?

Respuesta

33

Esto sucede porque la orientación establecida en los metadatos de la nueva imagen se ve afectada por la orientación del sistema AV que la crea. El diseño de los datos de imagen reales es, por supuesto, diferente de la orientación mencionada en sus metadatos. Algunos programas de visualización de imágenes respetan la orientación de metadatos, algunos lo ignoran.

Puede afectar a la orientación de los metadatos del sistema AV llamando:

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

Puede afectar a la orientación de los metadatos de un UIImage llamando:

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

pero los datos reales de la AVCapture el sistema siempre aparecerá con la dimensión más amplia como X y la dimensión más estrecha como Y, y aparecerá orientada en LandscapeLeft.

Si desea que los datos reales se alineen con lo que afirman sus metadatos, debe modificar los datos reales. Puede hacerlo escribiendo la imagen en una nueva imagen usando CGContexts y AffineTransforms. O hay una solución más fácil, use el paquete UIImage + Resize como se describe en here. Y cambiar el tamaño de la imagen a su tamaño actual llamando:

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

Esto rectificar la orientación de los datos como un efecto secundario.

Si no desea incluir todo el UIImager + Cambiar tamaño, puede verificar su código y quitar las partes donde se transforman los datos.

+3

Esto debería tener más votos ascendentes.Gracias amigo – Youssef

+0

¡¡¡Buena solución !! –

+0

Muy útil, ¡gracias! –

Cuestiones relacionadas