Кажется, что CGContextDrawImage (CGContextRef, CGRect, CGImageRef) выполняет MUCH WORSE при рисовании 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-й день): после создания вопросов в mroe, чем вчера, я получил сегодня что-то твердое. Я могу сказать наверняка следующее:
- CGImages за UIImage не используют альфа. (KCGImageAlphaNoneSkipLast). Я думал, что, возможно, они были быстрее, потому что мой контекст использовал альфа. Поэтому я изменил контекст, чтобы использовать kCGImageAlphaNoneSkipLast. Это делает рисунок МНОГО быстрее, БЕСПЛАТНО:
- Рисунок в CGContextRef с UIImage FIRST, делает ВСЕ последующее изображение медленным.
Я доказал это 1), сначала создав не-альфа-контекст (1936x2592). 2) Заполнил его случайно цветными квадратами 2x2. 3) Полный кадр чертежа CGImage в этом контексте был FAST (.17 секунд). 4) Повторяемый эксперимент, но заполненный контекст с нарисованным CGImage, поддерживающим UIImage. Последующий рисунок всего кадра составлял 6 секунд. SLOWWWWW.
Как-то рисование в контексте с помощью (Large) UIImage резко замедляет весь последующий рисунок в этом контексте.