Как сделать просмотр изображений быстрее?

Я создаю приложение лупы, которое позволяет пользователю прикоснуться к экрану и поместить его палец, будет лупа с его пальцем. Я реализую его с помощью скриншота и назначаю изображение для увеличения изображения лупы, как показано ниже:

    CGSize imageSize = frame.size;
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextScaleCTM(c, scaleFactor, scaleFactor);
    CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-frame.origin.x, -frame.origin.y));
    [self.layer renderInContext:c];
    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return screenshot;

проблема в том, что self.layer renderInContext является медленным, поэтому пользователь чувствует себя неравномерным, когда он двигает пальцем. и я попытался запустить self.layer renderInContext в другом потоке, однако, это делает изображение лупы выглядело странно, потому что изображение в лупе показало задержку.

Есть ли лучший способ визуализации изображения? использует renderInContext: GPU?

Ответ 1

Нет. В iOS6, renderInContext: это единственный способ. Это медленно. Он использует CPU.

Способы отображения содержимого UIKit

renderInContext:

[view.layer renderInContext:UIGraphicsGetCurrentContext()];
  • Требуется iOS 2.0. Он работает в ЦП.
  • Он не захватывает представления с неаффинными преобразованиями, OpenGL или видеоконтентом.
  • Если анимация запущена, у вас может быть возможность захвата:
    • view.layer, который фиксирует окончательный кадр анимации.
    • view.presentationLayer, который фиксирует текущий кадр анимации.

snapshotViewAfterScreenUpdates:

UIView *snapshot = [view snapshotViewAfterScreenUpdates:YES];
  • Требуется iOS 7.
  • Это самый быстрый метод.
  • Вид contents неизменен. Нехорошо, если вы хотите применить эффект.
  • Он отображает все типы контента (UIKit, OpenGL или видео).

resizableSnapshotViewFromRect: afterScreenUpdates: withCapInsets

[view resizableSnapshotViewFromRect:rect afterScreenUpdates:YES withCapInsets:edgeInsets]
  • Требуется iOS 7.
  • То же, что и snapshotViewAfterScreenUpdates:, но с изменяемыми размерами вставками. content также является неизменным.

drawViewHierarchyInRect: afterScreenUpdates:

[view drawViewHierarchyInRect:rect afterScreenUpdates:YES];
  • Требуется iOS 7.
  • Он рисует в текущем контексте.
  • Согласно сеансу 226 он быстрее, чем renderInContext:.

См. сессию WWDC 2013 226 Внедрение взаимодействия с пользовательским интерфейсом iOS о новых API-методах создания снимков.


Если это какая-то помощь, вот какой-то код, чтобы отменить попытки захвата, пока он еще работает.

Этот дроссель блокирует выполнение по одному за раз и отбрасывает другие. Из этого SO ответьте.

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t renderQueue = dispatch_queue_create("com.throttling.queue", NULL);

- (void) capture {
    if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) == 0) {
        dispatch_async(renderQueue, ^{
            // capture
            dispatch_semaphore_signal(semaphore);
        });
    }
}

Что это делает?

  • Создайте семафор для одного (1) ресурса.
  • Создайте последовательную очередь.
  • DISPATCH_TIME_NOW означает, что тайм-аут - нет, поэтому он сразу возвращает нуль на красный свет. Таким образом, не выполнение содержимого if.
  • Если зеленый индикатор, выполните асинхронный блок и снова установите зеленый свет.