Reputation: 495
I'm developing an app with gallery. All images are on device disc (documents directory), but I cannot display then smoothly.
Since some images are large (2000px * 2000px) I load them in background thread, scale them down and than display them on main thread.
Here is my UIImageView extension:
@implementation UIImageView (BackgroundResize)
- (void)localImageFromPath: (NSString *) path scaledTo: (CGSize) size {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_async(queue, ^{
//Load image
NSData * imgData = [[NSData alloc] initWithContentsOfFile:path];
UIImage * original = [[[UIImage alloc] initWithData:imgData] autorelease];
[imgData release];
CGSize imgSize = original.size;
float widthScale = size.width / imgSize.width;
float heightScale = size.height / imgSize.height;
float scaleFactor = widthScale;
if (heightScale < scaleFactor) {
scaleFactor = heightScale;
}
UIImage * result = nil;
//Scale if necessary
if (scaleFactor < 1.0) {
result = [[UIImage alloc] initWithCGImage:original.CGImage scale:1/scaleFactor orientation:original.imageOrientation];
} else {
result = [original retain];
}
NSLog(@"Image prepeared on backgroud thread, update ui image on main..");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Begin updating image on main thread");
self.image = result;
[result release];
[[NSNotificationCenter defaultCenter] postNotificationName:NTF_IMG_LOADED object:self];
NSLog(@"Updated");
});
});
dispatch_release(queue);
}
@end
In console output everything seems perfect, all debug strings are displayed in less than 1 sec (for 6 very large images), but UI is blocked and images are displayed with 10 sec delay.
What is the right approach to display large local images on iOS ?
App is build for iOS5+..
Thanks,
Upvotes: 2
Views: 259
Reputation: 17916
You are not actually resizing your images. The scale
parameter to -initWithCGImage:scale:
sets the ratio of image pixels to screen coordinate points; it does not do anything to the underlying image. You need to actually draw the image to a CGContext
to shrink it:
//Load image
UIImage * original = [[[UIImage alloc] initWithContentsOfFile:path] autorelease];
CGSize imgSize = original.size;
float widthScale = size.width / imgSize.width;
float heightScale = size.height / imgSize.height;
float scaleFactor = widthScale;
if (heightScale < scaleFactor) {
scaleFactor = heightScale;
}
UIImage * result = nil;
//Scale if necessary
if (scaleFactor < 1.0) {
CGSize newSize = CGSizeMake(floorf(imgSize.width * scaleFactor),
floorf(imgSize.height * scaleFactor));
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
[original drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
result = UIGraphicsGetImageFromCurrentImageContext();
[result retain];
UIGraphicsEndImageContext();
} else {
result = [original retain];
}
Upvotes: 2