Graphics Reference
In-Depth Information
Deferred Decompression
Once an image file has been loaded, it must then be decompressed. This decompression can
be a computationally complex task and take considerable time. The decompressed image
will also use substantially more memory than the original.
The relative CPU time spent loading versus decompressing will depend on the image
format. For PNG images, loading takes longer than for JPEGs because the file is
proportionally larger, but decompression is relatively fast, especially since Xcode
recompresses any PNGs included in the project using optimal settings for fast decoding.
JPEG images are smaller and load quicker, but the decompression step is more expensive
because the JPEG decompression algorithm is more complex than the zip-based algorithm
used in PNG.
When you load an image, iOS usually defers decompression until later to conserve
memory. This can cause a performance hiccup when you actually try to draw the image, as
it has to be decompressed at the point of drawing (which is often the worst possible time).
The simplest way to avoid deferred decompression is to load images using the UIImage
+imageNamed: method. Unlike +imageWithContentsOfFile: (and all the other UIImage
loading methods), this method decompresses the image immediately after loading (as well
as having other benefits that we discuss later in the chapter). The problem is that
+imageNamed: works only for images loaded from within the application resources bundle,
so it's not an option for user-generated content, or downloaded images.
Another way to decompress an image immediately is to assign it as the contents of a layer
or as the image property of a UIImageView . Unfortunately, this has to be done on the main
thread and so usually won't help with performance problems.
A third approach is to bypass UIKit altogether and load the image using the ImageIO
framework instead, as follows:
NSInteger index = indexPath.row;
NSURL *imageURL = [ NSURL fileURLWithPath : self . imagePaths [index]];
NSDictionary *options = @{ ( __bridge id ) kCGImageSourceShouldCache : @YES} ;
CGImageSourceRef source = CGImageSourceCreateWithURL (
( __bridge CFURLRef )imageURL, NULL );
CGImageRef imageRef = CGImageSourceCreateImageAtIndex (source, 0 ,
( __bridge CFDictionaryRef )options);
UIImage *image = [UIImage imageWithCGImage:imageRef];
CGImageRelease (imageRef);
CFRelease (source);
This allows you to make use of the kCGImageSourceShouldCache option when creating the
image, which forces it to decompress immediately and retain the decompressed version for
the lifetime of the image.
Search WWH ::




Custom Search