-
-
Save versluis/7615113 to your computer and use it in GitHub Desktop.
Preloading Images in iOS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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