Похоже, что CGContextDrawImage (CGContextRef, CGRect, CGImageRef) выполняет НАМНОГО ХУЖЕ при отрисовке CGImage, созданного CoreGraphics (то есть с CGBitmapContextCreateImage), чем при отрисовке CGImage, который поддерживает UIImage. См. Этот метод тестирования:
-(void)showStrangePerformanceOfCGContextDrawImage
{
///Setup : Load an image and start a context:
UIImage *theImage = [UIImage imageNamed:@"reallyBigImage.png"];
UIGraphicsBeginImageContext(theImage.size);
CGContextRef ctxt = UIGraphicsGetCurrentContext();
CGRect imgRec = CGRectMake(0, 0, theImage.size.width, theImage.size.height);
///Why is this SO MUCH faster...
NSDate * startingTimeForUIImageDrawing = [NSDate date];
CGContextDrawImage(ctxt, imgRec, theImage.CGImage); //Draw existing image into context Using the UIImage backing
NSLog(@"Time was %f", [[NSDate date] timeIntervalSinceDate:startingTimeForUIImageDrawing]);
/// Create a new image from the context to use this time in CGContextDrawImage:
CGImageRef theImageConverted = CGBitmapContextCreateImage(ctxt);
///This is WAY slower but why?? Using a pure CGImageRef (ass opposed to one behind a UIImage) seems like it should be faster but AT LEAST it should be the same speed!?
NSDate * startingTimeForNakedGImageDrawing = [NSDate date];
CGContextDrawImage(ctxt, imgRec, theImageConverted);
NSLog(@"Time was %f", [[NSDate date] timeIntervalSinceDate:startingTimeForNakedGImageDrawing]);
}
Итак, я предполагаю, что вопрос в следующем: №1, что может вызывать это, и №2, есть ли способ обойти это, то есть другие способы создания CGImageRef, которые могут быть быстрее? Я понимаю, что могу сначала преобразовать все в UIImages, но это такое уродливое решение. У меня уже есть CGContextRef.
ОБНОВЛЕНИЕ: Это не обязательно верно при рисовании небольших изображений? Это может быть признаком того, что эта проблема усиливается, когда используются большие изображения (например, полноразмерные фото с камеры). 640x480 кажется очень похожим с точки зрения времени выполнения для любого метода
ОБНОВЛЕНИЕ 2: Хорошо, я обнаружил кое-что новое ... На самом деле это НЕ поддержка CGImage, которая меняет производительность. Я могу изменить порядок двух шагов и заставить метод UIImage вести себя медленно, тогда как «голое» CGImage будет очень быстрым. Кажется, что бы вы ни играли вторым, производительность будет ужасной. Кажется, это так, ЕСЛИ я не освободил память, вызвав CGImageRelease для изображения, созданного с помощью CGBitmapContextCreateImage.Тогда метод, поддерживаемый UIImage, впоследствии будет быстрым. Обратное - это неправда. Что дает? «Переполненная» память не должна так влиять на производительность, не так ли?
ОБНОВЛЕНИЕ 3: Слишком рано заговорил. Предыдущее обновление справедливо для изображений размером 2048x2048, но при увеличении до 1936x2592 (размер камеры) голый метод CGImage по-прежнему работает медленнее, независимо от порядка операций или ситуации с памятью. Возможно, существуют некоторые внутренние ограничения CG, которые делают изображение 16 МБ эффективным, тогда как изображение 21 МБ не может быть эффективно обработано. Его размер буквально в 20 раз медленнее отрисовки, чем у 2048x2048. Каким-то образом UIImage предоставляет свои данные CGImage намного быстрее, чем чистый объект CGImage. o.O
ОБНОВЛЕНИЕ 4: Я подумал, что это может быть связано с каким-то кешированием памяти, но результаты будут такими же, независимо от того, загружен ли UIImage с некэширующим [UIImage imageWithContentsOfFile], как если бы использовалось [UIImage imageNamed].
ОБНОВЛЕНИЕ 5 (День 2): После создания вопросов, на которые были даны ответы вчера, сегодня у меня что-то твердое. Что я могу сказать с уверенностью, так это следующее:
Я доказал это 1) сначала создав не-альфа-контекст (1936x2592). 2) Заполните его произвольно раскрашенными квадратами 2х2.3) Полнокадровая отрисовка CGImage в этом контексте была БЫСТРОЙ (0,17 секунды). 4) Повторный эксперимент, но с заполнением контекста нарисованным CGImage, поддерживающим UIImage. Последующее рисование полнокадрового изображения длилось 6+ секунд. SLOWWWWW.
Каким-то образом рисование в контексте с (Large) UIImage резко замедляет все последующие рисования в этом контексте.