Подтвердить что ты не робот

Любой способ кодировать PNG быстрее, чем UIImagePNGRпредставление?

Я создаю кучу фрагментов для CATiledLayer. Требуется около 11 секунд, чтобы создать 120 плит с 256 x 256 с 4 уровнями детализации на iPhone 4S. Само изображение соответствует 2048 x 2048.

Мое узкое место UIImagePNGRepresentation. Для генерации каждого изображения размером 256 x 256 требуется около 0,10-0,15 секунды.

Я попытался создать несколько фрагментов в разных фоновых очередях, но это сократит его примерно до 9-10 секунд.

Я также пробовал использовать среду ImageIO с таким кодом:

- (void)writeCGImage:(CGImageRef)image toURL:(NSURL*)url andOptions:(CFDictionaryRef) options
{
    CGImageDestinationRef myImageDest = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, (__bridge CFStringRef)@"public.png", 1, nil);
    CGImageDestinationAddImage(myImageDest, image, options);
    CGImageDestinationFinalize(myImageDest);
    CFRelease(myImageDest);
}

В то время как это создает меньшие файлы PNG (выигрыш!), это занимает около 13 секунд, что на 2 секунды больше, чем раньше.

Есть ли способ быстрее закодировать изображение PNG из CGImage? Возможно, библиотека, использующая расширение NEON ARM (iPhone 3GS +), например libjpeg-turbo, делает?

Возможно, лучший формат, чем PNG для сохранения плиток, которые не занимают много места?

Единственный жизнеспособный вариант, который я смог придумать, - увеличить размер плитки до 512 x 512. Это сокращает время кодирования наполовину. Не уверен, что это будет делать с моим просмотром прокрутки. Приложение предназначено для iPad 2+ и поддерживает только iOS 6 (используя iPhone 4S в качестве базовой линии).

4b9b3361

Ответ 1

Оказывается, причина, по которой UIImageRepresentation выполняла так плохо, заключалась в том, что она каждый раз декомпрессировала исходное изображение, хотя я думал, что создаю новое изображение с CGImageCreateWithImageInRect.

Здесь вы можете увидеть результаты здесь:

enter image description here

Обратите внимание на _cg_jpeg_read_scanlines и decompress_onepass.

Я принудительно декомпрессировал изображение следующим образом:

UIImage *image = [UIImage imageWithContentsOfFile:path];
UIGraphicsBeginImageContext(CGSizeMake(1, 1));
[image drawAtPoint:CGPointZero];
UIGraphicsEndImageContext();

Сроки этого были около 0,10 секунды, что почти эквивалентно времени, затраченному на каждый вызов UIImageRepresentation.

В Интернете есть множество статей, которые рекомендуют рисовать как способ принудительной декомпрессии изображения.

Там статья о Cocoanetics Избегайте проблемы с декомпрессией изображения. В статье представлен альтернативный способ загрузки изображения:

NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                 forKey:(id)kCGImageSourceShouldCache];
CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)[[NSURL alloc] initFileURLWithPath:path], NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)dict);
UIImage *image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CFRelease(source);

И теперь тот же процесс занимает около 3 секунд! Использование GCD для генерации фрагментов параллельно уменьшает время значительно.

Функция writeCGImage выше занимает около 5 секунд. Поскольку размеры файлов меньше, я подозреваю, что сжатие zlib находится на более высоком уровне.