2010-02-10 4 views
8

Quando si scattano foto con UIImagePickerController su iPhone, io e molti abitanti di internet abbiamo trovato che è necessario eseguire le immagini attraverso questa funzione per orientarle correttamente (e ridimensionarle mentre ci sei)Accelerare o eliminare questa funzione lenta in un'app per fotocamera iPhone

C'è un filo rosso gigante su di esso qui: http://discussions.apple.com/message.jspa?messageID=7276709

Purtroppo, questa funzione può prendere secondi per eseguire ed è davvero una seccatura. Se si desidera utilizzare questo e consentire agli utenti di scattare foto velocemente, è anche necessario aggiungere un NSLock o si verificheranno alcuni arresti anomali.

Come posso velocizzare o eliminare questo codice?

// 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

Sto usando anche questo codice. Solo per curiosità, dove sarebbe necessario applicare NSLock? Non ho visto alcun arresto anomalo quando si utilizza questo codice. Come intendi "consentire agli utenti di scattare foto velocemente"? – Jasarien

+0

Per quello che voglio dire su NSLock, controlla l'ultimo paio di commenti su quel forum che ho collegato. Permettendo agli utenti di fare foto velocemente, intendo lo sfondo del salvataggio delle foto. Blocchi quando salvi le foto su disco? Inoltre, la mia app scrive i dati EXIF ​​sulle foto in questo processo, quindi c'è un lavoro aggiuntivo che sottolinea la memoria. –

+0

Io uso qualcosa di simile ed è molto, molto lento. Probabilmente c'è un modo migliore, di cui non sono a conoscenza ... Buona domanda. – Jordan

risposta

11

Avete davvero bisogno di fare questa operazione all'istante? La risoluzione dello schermo dell'iPhone è 320x480 (e raddoppia quella per retina) - ridimensiona l'immagine almeno fino a questo, quindi applica le trasformazioni (almeno per la visualizzazione, quindi più tardi se l'utente vuole fare qualcosa con l'immagine, corri la versione più costosa in background). Date un'occhiata a quella prima linea:

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

Per la maggior parte delle applicazioni, si sta ruotando questa immagine gigantesca, procedendo poi a buttare via la maggior parte di questi dati calcolato quando si restringerlo fino in fondo. Buttare via i dati prima ridimensionandoli (afaik, un'operazione molto più economica), quindi ruotare.

+2

Questa sarebbe la mia risposta. Un sacco di problemi di velocità sono in realtà problemi di percezione dell'utente. Ad esempio, le persone sono sensibili alla velocità quando scatta una foto ma sono condizionate ad attendere il caricamento su IP. È possibile archiviare rapidamente le immagini nel formato predefinito quando vengono acquisite e elaborarle solo quando devono essere spostate/caricate. – TechZen

0

Mi chiedo perché pensi che sia necessario ridimensionare e ruotare un'immagine proveniente da UIImagePicker. Ho scritto un paio di app diverse che usano la fotocamera e non ho mai avuto bisogno di farlo. Se spieghi più in dettaglio cosa stai cercando di fare, forse possiamo darti suggerimenti più specifici.

+1

È necessario eseguire questa operazione quando non si sta salvando sul Rullino foto. Sei in grado di caricare una foto scattata con UIImagePickerController su Flickr o Picasa senza che siano orientati in modo errato? –

+0

Non ho provato a caricare le foto direttamente su Flickr dalla mia app, ma se Flickr non capisce il flag di orientamento, come fanno la cosa giusta con i caricamenti delle telecamere? Molto strano. –

Problemi correlati