2010-02-10 3 views
8

Wenn Sie Fotos Witha UIImagePickerController auf dem iPhone nehmen, ich und viele Internet-Bewohner haben Sie sie (und sie richtig orientieren müssen ausführen, um die Bilder, die durch diese Funktion gefundenen skalieren, während du bist dabei.Beschleunigung oder diese langsame Funktion in einer iPhone-Kamera-App beseitigen

Es gibt einen riesigen Thread über sie hier: http://discussions.apple.com/message.jspa?messageID=7276709

Leider kann diese Funktion Sekunden dauern, zu laufen und es ist wirklich ein Ärgernis. Wenn Sie diese Funktion verwenden und Benutzer schnell Bilder aufnehmen lassen möchten, müssen Sie sogar einen NSLock hinzufügen oder es kommt zu Abstürzen.

Wie kann ich beschleunigen oder diesen Code zu beseitigen?

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

Ich benutze auch diesen Code. Nur aus Neugier, wo müssten die NSLocks angewendet werden? Ich habe keine Abstürze bei der Verwendung dieses Codes gesehen. Wie meinst du "lassen Sie die Benutzer Bilder schnell machen"? – Jasarien

+0

Was ich mit NSLock meine, lesen Sie die letzten Kommentare in dem Forum, das ich verlinkt habe. Damit Benutzer schnell Bilder aufnehmen können, bezeichne ich das Speichern der Fotos als Hintergrund. Blockierst du beim Speichern von Fotos auf der Festplatte? Außerdem schreibt meine App in diesem Prozess EXIF-Daten in die Fotos, sodass zusätzliche Arbeit geleistet wird, die den Speicher beansprucht. –

+0

Ich benutze etwas ähnliches und es ist sehr, sehr langsam. Es gibt wahrscheinlich einen besseren Weg, den ich nicht kenne ... Gute Frage. – Jordan

Antwort

11

Müssen Sie diese Operation wirklich sofort durchführen? Die Bildschirmauflösung des iPhone ist 320x480 (und doppelt so hoch für Retina) - das Bild skalieren bis mindestens diese, dann die Transformationen anwenden (zumindest für die Anzeige, dann später, wenn der Benutzer etwas mit dem Bild machen will, Sie laufen die teurere Version im Hintergrund). Werfen Sie einen Blick auf die erste Zeile:

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

Für die meisten Anwendungen, die Sie Drehen dieses gigantische Bild, dann verläuft die meisten dieser berechneten Daten wegzuwerfen, wenn Sie es hinunter schrumpfen. Werfen Sie die Daten zuerst durch Skalieren weg (afaik, eine viel billigere Operation), und drehen Sie sie dann.

+2

Das wäre meine Antwort. Viele Geschwindigkeitsprobleme sind in der Tat Probleme der Benutzerwahrnehmung. Zum Beispiel sind Leute empfindlich auf Geschwindigkeit, wenn sie ein Foto machen, aber sie sind darauf vorbereitet, auf Uploads über IP zu warten. Sie können die Bilder bei der Aufnahme schnell im Standardformat speichern und dann nur verarbeiten, wenn sie verschoben/hochgeladen werden müssen. – TechZen

0

Ich frage mich, warum Sie denken, dass Sie ein Bild skalieren und drehen müssen, die von dem UIImagePicker kommt. Ich habe ein paar verschiedene Apps geschrieben, die die Kamera verwenden, und ich musste das nie tun. Wenn Sie genauer erklären, was Sie zu tun versuchen, können wir Ihnen vielleicht genauere Vorschläge machen.

+1

Sie müssen dies tun, wenn Sie nicht in der Kamerarolle speichern. Können Sie ein Foto, das Sie mit dem UIImagePickerController aufnehmen, auf Flickr oder Picasa hochladen, ohne dass diese falsch ausgerichtet sind? –

+0

Ich habe nicht versucht, Fotos direkt auf Flickr von meiner App hochladen, aber wenn Flickr nicht die Orientierung Flagge verstehen, wie tun sie das Richtige mit Kamera-Uploads? Sehr komisch. –

Verwandte Themen