Как сделать рендеринг изображения быстрее?
Я делаю приложение лупы, которое позволяет пользователю дотронуться до экрана и двигать пальцем, там будет лупа с траекторией пальца. Я реализую его, сделав снимок экрана и назначив изображение для увеличения изображения, как показано ниже:
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.- Если горит зеленый свет, запустите блок асинхронно и снова установите зеленый свет.