2009-02-11 9 views
43

En mi aplicación de iPhone solo para exteriores, inicio UIImagePickerController para tomar una foto, pero la imagen en vivo que muestra la cámara está en orientación vertical, con espacio en blanco alrededor. La imagen se gira.La vista previa de la cámara UIImagePickerController es retratos en la aplicación horizontal

Una vez que se presiona el botón de la cámara, la vista previa es muy desordenada, con la mayoría de la vista previa fuera de pantalla y las vistas no alineadas correctamente.

Apple ha reconocido que esto es un defecto y está trabajando en ello.

Mi pregunta es, ¿alguien tiene una solución alternativa (legal o ilegal) que me permita hacer que esto funcione ahora? No lanzaría a la tienda de aplicaciones con una solución ilegal, pero tendría una aplicación mucho mejor para las pruebas de usuario: actualmente la cámara es prácticamente inutilizable en el paisaje.

Adjuntaré un proyecto de prueba simple e imágenes si puedo.

Editar - solo para aclarar, la imagen que obtengo es correctamente horizontal. Quiero que la cámara & ¡UI de vista previa se vea bien!


Camera http://i42.tinypic.com/2zqsbpy.jpg

alt text http://i43.tinypic.com/168zam0.jpg

+5

Hablando como un árbitro de la NFL, "Arreglo ilegal, ofensa, 10 yardas. Segunda oportunidad". – gonzobrains

+5

Lo que es extraño, porque no tengo idea de lo que es la NFL. –

+0

Extraño cómo nosotros los norteamericanos (nota: América del Norte no incluye solo a los EE. UU.) ¡Supongamos que todos saben lo que es la NFL! @JaneSales representa la National Football League, que en realidad es diferente al fútbol que conoces. –

Respuesta

87

La respuesta es más ridícula de lo que parece. Tuve el mismo problema y encontré una solución en algún foro. Pase su imagen tomada en un método como este:

// Code from: http://discussions.apple.com/thread.jspa?messageID=7949889 
- (UIImage *)scaleAndRotateImage:(UIImage *)image { 
    int kMaxResolution = 640; // Or whatever 

    CGImageRef imgRef = image.CGImage; 

    CGFloat width = CGImageGetWidth(imgRef); 
    CGFloat height = CGImageGetHeight(imgRef); 


    CGAffineTransform transform = CGAffineTransformIdentity; 
    CGRect bounds = CGRectMake(0, 0, width, height); 
    if (width > kMaxResolution || height > kMaxResolution) { 
     CGFloat ratio = width/height; 
     if (ratio > 1) { 
      bounds.size.width = kMaxResolution; 
      bounds.size.height = roundf(bounds.size.width/ratio); 
     } 
     else { 
      bounds.size.height = kMaxResolution; 
      bounds.size.width = roundf(bounds.size.height * ratio); 
     } 
    } 

    CGFloat scaleRatio = bounds.size.width/width; 
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 
    CGFloat boundHeight; 
    UIImageOrientation orient = image.imageOrientation; 
    switch(orient) { 

     case UIImageOrientationUp: //EXIF = 1 
      transform = CGAffineTransformIdentity; 
      break; 

     case UIImageOrientationUpMirrored: //EXIF = 2 
      transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
      break; 

     case UIImageOrientationDown: //EXIF = 3 
      transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 
      transform = CGAffineTransformRotate(transform, M_PI); 
      break; 

     case UIImageOrientationDownMirrored: //EXIF = 4 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); 
      transform = CGAffineTransformScale(transform, 1.0, -1.0); 
      break; 

     case UIImageOrientationLeftMirrored: //EXIF = 5 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
      transform = CGAffineTransformRotate(transform, 3.0 * M_PI/2.0); 
      break; 

     case UIImageOrientationLeft: //EXIF = 6 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.width); 
      transform = CGAffineTransformRotate(transform, 3.0 * M_PI/2.0); 
      break; 

     case UIImageOrientationRightMirrored: //EXIF = 7 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeScale(-1.0, 1.0); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0); 
      break; 

     case UIImageOrientationRight: //EXIF = 8 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0); 
      break; 

     default: 
      [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 

    } 

    UIGraphicsBeginImageContext(bounds.size); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 
     CGContextScaleCTM(context, -scaleRatio, scaleRatio); 
     CGContextTranslateCTM(context, -height, 0); 
    } 
    else { 
     CGContextScaleCTM(context, scaleRatio, -scaleRatio); 
     CGContextTranslateCTM(context, 0, -height); 
    } 

    CGContextConcatCTM(context, transform); 

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef); 
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return imageCopy; 
} 

:(

+0

ridículo, pero funciona :) – byron

+0

super método, realmente es su trabajo! – freelancer

+0

¡Muchas gracias por este método! ¡El problema giratorio me hizo casi enojado! – applefreak

0

que necesitará para configurar la vista personalizada (con la barra de herramientas y título) como cameraOverlayView, también tendrá que establecer allowsEditing y showsCameraControls a NO ya que eso ocultará controles estándar y la vista previa. Eso es lo que he encontrado como necesario en la aplicación que estoy creando (pensé que necesitaba que el selector estuviera en retratos, pero necesito que aplique algunos cambios de usuario si el usuario rota su dispositivo al paisaje). Se puede proporcionar un código si es necesario.

P.S. Todavía hay algunos errores en mi código, pero estoy trabajando en ello :)

1

No creo que necesite el trabajo adicional para tratar con imageRotation o los datos EXIF ​​en absoluto. La imagen drawInRect se encargará de eso automáticamente.

Por lo tanto, solo necesita obtener este tamaño o la imagen y volver a dibujarla en una nueva imagen, eso sería suficiente.

1

No quiero rotar la imagen después de la captura; Quiero que la vista previa se muestre correctamente en modo horizontal. Así que en iOS 6, permito modo vertical a nivel de aplicación, pero puse controlador de vista raíz de la aplicación para ser de clase MyNonrotatingNavigationController, define como sigue:

@implementation MyNonrotatingNavigationController 

-(NSUInteger) supportedInterfaceOrientations 
{ 
    return UIInterfaceOrientationMaskLandscape; 
} 

@end 

así que todo lo que alguna vez se muestra el interior de este controlador de navegación estará en orientación horizontal (puede hacer esto con cualquier controlador de vista). Ahora, cuando necesito mostrar un selector de imágenes, reemplazo el controlador de vista raíz de la ventana de la aplicación por uno genérico que admite el modo vertical. Para evitar que el viejo controlador de vista raíz y sus vistas se desasignaran, mantengo los punteros hasta que esté listo para volver a colocarlos en la ventana de la aplicación.

#define APP_DELEGATE ((MyAppDelegate*)[[UIApplication sharedApplication] delegate]) 
static UIViewController *pickerContainer = nil; 
static UIViewController *oldRoot = nil; 
static UIView *holdView = nil; 

-(void) showPicker 
{ 
    ...create UIImagePickerController... 

    oldRoot = APP_DELEGATE.window.rootViewController; 
    holdView = [[UIView alloc] initWithFrame:APP_DELEGATE.window.bounds]; 
    [holdView addSubview:oldRoot.view]; 

    pickerContainer = [UIViewController new]; 
    pickerContainer.view = [[UIView alloc] initWithFrame:APP_DELEGATE.window.bounds]; 
    APP_DELEGATE.window.rootViewController = pickerContainer; 
    [pickerContainer presentViewController:picker animated:YES completion:NULL]; 
} 

-(void) imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info 
{ 
    [pickerContainer dismissViewControllerAnimated:YES completion:^{ 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      APP_DELEGATE.window.rootViewController = oldRoot; 
      [APP_DELEGATE.window addSubview:oldRoot.view]; 
      pickerContainer = nil; 
      oldRoot = nil; 
      holdView = nil; 
     }); 
    }]; 
} 

Es un poco molesto, pero parece funcionar tanto para fotos como para videos. Los controles del selector de imágenes se muestran en modo vertical, pero el resto de la aplicación es solo horizontal.

+0

Solución asombrosa, también funciona en iOS7. –

1

Resolví este problema al hacer que el UIImagePickerController apareciera en modo de pantalla completa, que también es lo que recomienda Apple para iPad.

De UIImagePickerController documentation:

En el iPad, si se especifica un tipo de fuente de UIImagePickerControllerSourceTypeCamera, puede presentar la forma modal imagen Recogedor (pantalla completa) o utilizando un popover. Sin embargo, Apple recomienda que presente la interfaz de la cámara solo a pantalla completa.

Cuestiones relacionadas