Skip to content

Instantly share code, notes, and snippets.

@versluis
Forked from leovandriel/gist:3923434
Last active December 29, 2015 04:29
Show Gist options
  • Save versluis/7615113 to your computer and use it in GitHub Desktop.
Save versluis/7615113 to your computer and use it in GitHub Desktop.
Preloading Images in iOS
// ImagePreloadingViewController - An iOS view controller for trying out different
// UIImage preloading strategies. Results for 1 MB png on iPhone 4S:
// - No preload: drawing the image right away (80 ms)
// - Header preload: getting the width (10 ms) and then drawing (100 ms)
// - Data preload: getting the data (110 ms) and then drawing (75 ms)
// - Draw preload: drawing it once (100 ms) and then again (20 ms)
// In short: preload a UIImage by drawing it.
// License: BSD
// Author: Leonard van Driel, 2012
@interface ImagePreloadingViewController : UIViewController
@end
@implementation ImagePreloadingViewController {
UITextView *output;
}
- (void)viewDidLoad
{
[super viewDidLoad];
for (NSUInteger i = 0; i < 4; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(10, 10 + 50 * i, self.view.bounds.size.width - 20, 40);
[button addTarget:self action:@selector(run:) forControlEvents:UIControlEventTouchUpInside];
switch (i) {
case 0: [button setTitle:@"No preload" forState:UIControlStateNormal]; break;
case 1: [button setTitle:@"Header preload" forState:UIControlStateNormal]; break;
case 2: [button setTitle:@"Data preload" forState:UIControlStateNormal]; break;
case 3: [button setTitle:@"Draw preload" forState:UIControlStateNormal]; break;
}
button.tag = i;
[self.view addSubview:button];
}
output = [[UITextView alloc] init];
output.frame = CGRectMake(10, 210, self.view.bounds.size.width - 20, self.view.bounds.size.height - 270);
[self.view addSubview:output];
}
#pragma mark - Timing
- (void)run:(UIButton *)button
{
NSUInteger index = button.tag;
[self preload:index];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, .1 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self load:index];
});
}
- (void)preload:(NSUInteger)index
{
NSString *name = [NSString stringWithFormat:@"%i.png", index];
double time = CFAbsoluteTimeGetCurrent();
switch (index) {
case 0: break;
case 1: [self header:[UIImage imageNamed:name]]; break;
case 2: [self data:[UIImage imageNamed:name]]; break;
case 3: [self draw:[UIImage imageNamed:name]]; break;
}
output.text = [output.text stringByAppendingFormat:@"%i: %4.0f ms preload", index, (CFAbsoluteTimeGetCurrent() - time) * 1000];
}
- (void)load:(NSUInteger)index
{
NSString *name = [NSString stringWithFormat:@"%i.png", index];
double time = CFAbsoluteTimeGetCurrent();
[self draw:[UIImage imageNamed:name]];
output.text = [output.text stringByAppendingFormat:@" .. %4.0f ms draw\n", (CFAbsoluteTimeGetCurrent() - time) * 1000];
}
#pragma mark - Preload types
- (void)header:(UIImage *)image
{
CGImageRef ref = image.CGImage;
CGImageGetWidth(ref);
}
- (void)data:(UIImage *)image
{
CGImageRef ref = image.CGImage;
CGDataProviderRef provider = CGImageGetDataProvider(ref);
CGDataProviderCopyData(provider);
}
- (void)draw:(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, kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), ref);
CGContextRelease(context);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment