有什么方法可以比UIImagePNGRepresentation更快地编码PNG? [英] Any way to encode a PNG faster than UIImagePNGRepresentation?
问题描述
我正在为 CATiledLayer
生成一堆磁贴。在iPhone 4S上以4个级别的细节生成120个256 x 256的图块需要大约11秒钟。图像本身适合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秒。
有没有办法更快地从 CGImage
编码PNG图像?也许是一个使用 NEON
ARM扩展(iPhone 3GS +)的库,如。本文提供了另一种加载图像的方法:
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(来源);
现在同样的过程大约需要3秒钟!使用GCD并行生成切片可以更加显着地减少时间。
上面的 writeCGImage
函数大约需要5秒。由于文件大小较小,我怀疑zlib压缩处于较高级别。
I'm generating a bunch of tiles for CATiledLayer
. It takes about 11 seconds to generate 120 tiles at 256 x 256 with 4 levels of detail on an iPhone 4S. The image itself fits within 2048 x 2048.
My bottleneck is UIImagePNGRepresentation
. It takes about 0.10-0.15 seconds to generate every 256 x 256 image.
I've tried generating multiple tiles on different background queue's, but this only cuts it down to about 9-10 seconds.
I've also tried using the ImageIO framework with code like this:
- (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);
}
While this produces smaller PNG files (win!), it takes about 13 seconds, 2 seconds more than before.
Is there any way to encode a PNG image from CGImage
faster? Perhaps a library that makes use of NEON
ARM extension (iPhone 3GS+) like libjpeg-turbo does?
Is there perhaps a better format than PNG for saving tiles that doesn't take up a lot of space?
The only viable option I've been able to come up with is to increase the tile size to 512 x 512. This cuts the encoding time by half. Not sure what that will do to my scroll view though. The app is for iPad 2+, and only supports iOS 6 (using iPhone 4S as a baseline).
It turns out the reason why UIImageRepresentation
was performing so poorly was because it was decompressing the original image every time even though I thought I was creating a new image with CGImageCreateWithImageInRect
.
You can see the results from Instruments here:
Notice _cg_jpeg_read_scanlines
and decompress_onepass
.
I was force-decompressing the image with this:
UIImage *image = [UIImage imageWithContentsOfFile:path];
UIGraphicsBeginImageContext(CGSizeMake(1, 1));
[image drawAtPoint:CGPointZero];
UIGraphicsEndImageContext();
The timing of this was about 0.10 seconds, almost equivalent to the time taken by each UIImageRepresentation
call.
There are numerous articles over the internet that recommend drawing as a way of force decompressing an image.
There's an article on Cocoanetics Avoiding Image Decompression Sickness. The article provides an alternate way of loading the image:
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);
And now the same process takes about 3 seconds! Using GCD to generate tiles in parallel reduces the time more significantly.
The writeCGImage
function above takes about 5 seconds. Since the file sizes are smaller, I suspect the zlib compression is at a higher level.
这篇关于有什么方法可以比UIImagePNGRepresentation更快地编码PNG?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!