Как сделать рендеринг изображения быстрее?

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

    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: использовать графический процессор?

1 ответ

Решение

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

Способы рендеринга контента 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:,

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


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

Это ограничивает выполнение блока по одному и сбрасывает другие. От этого ТАКОГО ответа.

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.
  • Если горит зеленый свет, запустите блок асинхронно и снова установите зеленый свет.
Другие вопросы по тегам