Ускорение или устранение этой медленной функции в приложении камеры iPhone - PullRequest
8 голосов
/ 10 февраля 2010

Когда вы снимаете фотографии с помощью UIImagePickerController на iPhone, я и многие интернет-обитатели обнаружили, что вам необходимо запустить изображения с помощью этой функции, чтобы правильно ориентировать их (и масштабировать, пока вы там).

Здесь есть гигантская нить: http://discussions.apple.com/message.jspa?messageID=7276709

К сожалению, эта функция может занять несколько секунд, и это действительно неприятно. Если вы хотите использовать это и позволить пользователям быстро делать снимки, вам даже нужно добавить NSLock, или вы получите некоторые сбои.

Как я могу ускорить или устранить этот код?

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

Ответы [ 2 ]

11 голосов
/ 13 февраля 2010

Вам действительно нужно сделать эту операцию мгновенно? Разрешение экрана iPhone составляет 320x480 (и вдвое больше, чем для сетчатки) - уменьшите изображение до как минимум этого, затем примените преобразования (хотя бы для отображения, затем позже, если пользователь хочет что-то сделать с изображением, вы запускаете более дорогая версия в фоновом режиме). Посмотрите на эту первую строку:

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

Для большинства приложений вы поворачиваете это гигантское изображение, а затем отбрасываете большую часть вычисленных данных, когда вы уменьшаете его до предела. Сначала выбросьте данные путем масштабирования (afaik, гораздо более дешевая операция), а затем поверните.

0 голосов
/ 17 февраля 2010

Интересно, почему вы думаете, что вам нужно масштабировать и поворачивать изображение, полученное из UIImagePicker. Я написал пару разных приложений, которые используют камеру, и мне никогда не нужно было это делать. Если вы объясните более подробно, что вы пытаетесь сделать, возможно, мы сможем дать вам более конкретные предложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...