2010-02-10 7 views
8

Cuando toma fotos con UIImagePickerController en el iPhone, yo y muchos usuarios de Internet han encontrado que necesita ejecutar las imágenes a través de esta función para orientarlas correctamente (y escalarlas mientras estás en eso).Acelerar o eliminar esta función lenta en una aplicación de cámara para iPhone

Hay un hilo gigante sobre él aquí: http://discussions.apple.com/message.jspa?messageID=7276709

Desafortunadamente, esta función puede tomar segundos para correr y es realmente una molestia. Si desea utilizar esto y permitir que los usuarios tomen fotos rápidamente, incluso necesitará agregar un bloqueo NS o se producirán algunos bloqueos.

¿Cómo puedo acelerar o eliminar este código?

// orient photos and scale them to kMaxResolution 
+ (UIImage*)scaleAndRotateImage:(UIImage *)image { 

    // we upload photos at a maximum resolution of 2048 x 1536 
    int kMaxResolution = 2048; 

    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 = bounds.size.width/ratio; 
     } else { 
      bounds.size.height = kMaxResolution; 
      bounds.size.width = 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; 
} 
+1

Estoy usando este código también. Solo por curiosidad, ¿dónde se debería aplicar NSLock? No he visto ningún bloqueo al usar este código. ¿Cómo se refiere a "dejar que los usuarios tomen fotos rápido"? – Jasarien

+0

Por lo que quiero decir sobre NSLock, echa un vistazo a los últimos dos comentarios en ese foro que he vinculado. Al permitir que los usuarios tomen fotos rápido, me refiero a guardar el fondo de las fotos. ¿Bloqueas cuando guardas fotos en el disco? Además, mi aplicación escribe datos EXIF ​​para las fotos en este proceso, por lo que se realiza un trabajo adicional que acentúa la memoria. –

+0

Uso algo similar y es muy, muy lento. Probablemente haya una mejor manera, de la que no tengo conocimiento ... Buena pregunta. – Jordan

Respuesta

11

¿Realmente necesita hacer esta operación al instante? La resolución de pantalla del iPhone es 320x480 (y el doble que la retina): escala la imagen hasta al menos esto, luego aplica las transformaciones (al menos para mostrar, luego, si el usuario quiere hacer algo con la imagen, ejecuta la versión más costosa en el fondo). Echar un vistazo a esa primera línea:

// we upload photos at a maximum resolution of 2048 x 1536 
int kMaxResolution = 2048; 

Para la mayoría de las aplicaciones, que está girando esta imagen gigantesca, a continuación, proceder a tirar la mayor parte de esos datos calculada cuando se encogen hacia abajo. Bote los datos primero escalando (afaik, una operación mucho más económica), luego rote.

+2

Esta sería mi respuesta. Muchos problemas de velocidad son, de hecho, problemas de percepción del usuario. Por ejemplo, las personas son sensibles a la velocidad cuando toman una foto pero están condicionadas a esperar cargas por IP. Puede almacenar las imágenes rápidamente en el formato predeterminado cuando se toman y luego solo procesarlas cuando es necesario moverlas o cargarlas. – TechZen

0

Me pregunto por qué piensas que necesitas escalar y rotar una imagen que proviene del UIImagePicker. He escrito un par de aplicaciones diferentes que usan la cámara, y nunca tuve que hacer esto. Si explica con más detalle lo que está tratando de hacer, tal vez podamos darle sugerencias más específicas.

+1

Debe hacer esto cuando no esté guardando en el Camera Roll. ¿Puedes cargar una foto que tomes con UIImagePickerController a Flickr o Picasa sin que se oriente incorrectamente? –

+0

No he intentado subir fotos directamente a Flickr desde mi aplicación, pero si Flickr no entiende la bandera de orientación, ¿cómo hacen lo correcto con las cargas de la cámara? Muy raro. –

Cuestiones relacionadas