Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

loading images from disk in iPhone app is slow

In my iPhone app, I am using the iPhone's camera to take a photo and save it do disk (the application's documents folder). This is how i save it:

[UIImageJPEGRepresentation(photoTaken, 0.0) writeToFile:jpegPath atomically:YES];

Using the most compression, I figured reading the image from disk would be quick. But its not! I use the image as the background image for a button in one of my views. I load it like this:

[self.frontButton setBackgroundImage:[UIImage imageWithContentsOfFile:frontPath] forState:UIControlStateNormal];

When I navigate to the view with this button, it is slow and choppy. How do I fix this?

like image 825
user1007895 Avatar asked Nov 04 '11 22:11

user1007895


People also ask

Why do my pictures take long to load?

The most common reason behind slow uploads is your internet connection itself. On average, your upload speed is about 10 times slower than your download speed, and both are regulated by your Internet Service Provider.

Why wont my pictures load on my iPhone?

A common reason as to why multimedia files like photos, videos and audio files are not loading on an iPhone is due to a problematic internet connection. This is often the case when the device is experiencing slow internet, intermittent or unstable Wi-Fi.

Why is iPhone slow?

Make sure you have enough storage You can check your device's storage in Settings > General > [Device] Storage. For best performance, try to maintain at least 1GB of free space. If your available storage is consistently less than 1GB, your device might slow down as iOS repeatedly makes room for more content.

Why won't pictures load on my iPad?

iPhone, iPad, or iPod touchCheck that Wi-Fi is on and you have an internet connection. Tap Settings > [your name] > iCloud > Photos. Make sure Upload to My Photo Stream is turned on. If you don't see this option, turn on iCloud Photos to keep your photos and videos in iCloud instead.


2 Answers

+imageWithContentsOfFile: is synchronous, so the UI on your main thread is being blocked by the image loading from disk operation and causing the choppiness. The solution is to use a method that loads the file asynchronously from disk. You could also do this in a background thread. This can be done easily by wrapping the +imageWithContentsOfFile: in dispatch_async(), then a nested dispatch_async() on the main queue that wraps -setBackgroundImage: since UIKit methods need to be run on the main thread. If you want the image to appear immediately after the view loads, you'll need to pre-cache the image from disk so it's in-memory immediately when the view appears.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

    UIImage *image = [UIImage imageWithContentsOfFile:frontPath];

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.frontButton setBackgroundImage:image forState:UIControlStateNormal];
    });

});

As an aside, if the button image happens a gradient, consider using the following properties to ensure the image file loaded from disk is tiny:

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets

or (deprecated, only use if you need to support iOS 4.x):

- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight
like image 145
Andrew Avatar answered Oct 27 '22 10:10

Andrew


This is the faster way I know. You'll need to import #import <ImageIO/ImageIO.h>

I use this code to download and compress images during a scroll, inside a scrollview and you barely notice the delay.

CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)mutableData, NULL);
CFDictionaryRef options = (CFDictionaryRef)[[NSDictionary alloc] initWithObjectsAndKeys:(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform, (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent, (id)[NSNumber numberWithDouble:200.0], (id)kCGImageSourceThumbnailMaxPixelSize, nil];
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);

UIImage *image = [[UIImage alloc] initWithCGImage:thumbnail];
// Cache
NSString *fileName = @"fileName.jpg";
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"thumbnail"];
path = [path stringByAppendingPathComponent:fileName];
if ([UIImagePNGRepresentation(image) writeToFile:path atomically:YES]) {
    // Success
}
like image 30
Ivan Carosati Avatar answered Oct 27 '22 10:10

Ivan Carosati