Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing the load of images on iOS to preload

Tags:

ios

image

preload

I want to preload images sot that when I add their UIImageView to my currentView, the PNG are already in memory, loaded, inflated etc.

As you can see from this time profiling, the images are loaded when they are displayed: enter image description here

In the same time, I'm already preloading these images before. Just when I load that view, I thoroughly create all images and image views for these animations using that code:

- (UIImageView*)createAnimationForReel:(NSString*)reel ofType:(NSString*)type usingFrames:(NSInteger)frames{
    UIImageView *imageView = [[UIImageView alloc] init];
    NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:frames];

    for (int i=0;i<frames;i++){
        NSString *image;
        if(i<10){
            image = [NSString stringWithFormat:@"%@_0%i", reel, i];
        } else {
            image = [NSString stringWithFormat:@"%@_%i", reel, i];
        }
        NSString *path = [[NSBundle mainBundle] pathForResource:image ofType:@"png" inDirectory:type];
        UIImage *anImage = [[UIImage alloc] initWithContentsOfFile:path];
        [imageArray addObject:anImage];
    }
    imageView.animationImages = [NSArray arrayWithArray:imageArray];
    imageView.animationDuration = 2.0;
    return imageView;
}

And when I read the documentation it says: "This method loads the image data into memory and marks it as purgeable. If the data is purged and needs to be reloaded, the image object loads that data again from the specified path." talking about initWithContentOfFile. So my image "should" be loaded.

But no.

Surely something is missing in my reflection. But what?

like image 811
Cyril Godefroy Avatar asked Feb 10 '12 09:02

Cyril Godefroy


1 Answers

To force the full preloading of a UIImage, you'll need to actually draw it, or so it seems. For example using:

- (void)preload:(UIImage *)image
{
    CGImageRef ref = image.CGImage;
    size_t width = CGImageGetWidth(ref);
    size_t height = CGImageGetHeight(ref);
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, space, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(space);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), ref);
    CGContextRelease(context);
}

Not pretty, but it makes drawing the image about 4x faster. I tested this with an 1 MB 640 × 1136 PNG on an iPhone 4S:

  • Drawing it without preload takes about 80 ms.
  • Preloading the image header takes about 10 ms, but doesn't speedup the drawing afterwards.
  • Preloading the data though the data provider takes about 100 ms, but hardly speeds up the drawing afterwards.
  • Preloading by drawing, illustrated in the code above, takes 100 ms but the next draw only 20 ms.

Check https://gist.github.com/3923434 for the test code.

like image 152
leo Avatar answered Sep 18 '22 23:09

leo