iosperformanceimageipaduiimagepickercontroller

Resizing UIImage takes long time?


In my app when I use the UIImagePickerController, I resize the image taken from the picker in order to reduce it from the very large size it begins with. On the iPhone and iPod Touch it works fine and there is minor lag. However, since the iPad screen is much larger it takes MUCH, MUCH longer since I resize it according to pixels.

This is my code:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    CGFloat screenScale = [[UIScreen mainScreen] scale];
    CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale);

    UIGraphicsBeginImageContext(screenSize);
    [image drawInRect:CGRectMake(0,0,screenSize.width,screenSize.height)];
    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
    [currentDefaults setObject:UIImagePNGRepresentation(newImage) forKey:@"newImageKey"];
    [currentDefaults synchronize];

    [popoverController dismissPopoverAnimated:YES];
    [picker dismissModalViewControllerAnimated:YES];
}

Is there any way to resize it quicker or do it some other way so the user won't notice the lag when the system is resizing the large images?

Thanks!


Solution

  • In general there are two things I recommend you do. The first, consider using GCD to make your resizing and saving operations happen off the main thread (this requires iOS 4.0 and up). Your method would look something like this (off the top of my head and not compiled)

    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        CGRect screenBounds = [[UIScreen mainScreen] bounds];
        CGFloat screenScale = [[UIScreen mainScreen] scale];
        CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale);
        
        UIGraphicsBeginImageContext(screenSize);
        [image drawInRect:CGRectMake(0,0,screenSize.width,screenSize.height)];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
        [currentDefaults setObject:UIImagePNGRepresentation(newImage) forKey:@"newImageKey"];
        [currentDefaults synchronize];
    });
    
    [popoverController dismissPopoverAnimated:YES];
    [picker dismissModalViewControllerAnimated:YES];
    }
    

    The second thing I strongly recommend is to not store the resulting image in NSUserDefaults. NSUserDefaults is only intended to be a small key-value store. If you're going to store images, store them on disk using NSFileManager and store the path as the value in NSUserDefaults.