miham
miham

Reputation: 495

Bad performance with UIImageView (for local images)

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

Answers (1)

Seamus Campbell
Seamus Campbell

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

Related Questions