views:

564

answers:

3

How do I display a low resolution image on a page and then after a second delay load a high resolution version? Is this done with layers? Threads?

+1  A: 

In general this feature is achieved with image files saved in some interlaced/progessive mode. This allows the displaying application (i.e. browser) to display the image successively starting in a low quality as the first chunks of data arrive. The more of the data is available, the higher the quality of the image gets.

This feature is independent of the web server. Only the client application is responsible of supporting this mode

This site shows some examples.

Frank Bollack
+1  A: 

It sounds like you a describing something like the TTPhotoViewController from Three20 (used in the Facebook iPhone app). When you first start looking at an image it's simply a thumbnail that has been stretched out. The "high res" version is being downloaded in the background, and when that download is complete it replaces the existing stretched image.

Pyro2927
In this case it is done with Threads. Most commonly done is to load the thumbnail, spin off a thread to start downloading the larger image, and then run a self performSelectorOnMainThread:Since you need to be in the main thread to meddle with the UI.
Pyro2927
+1  A: 

There are several options:

1) Save the images on the server in a format that supports progressive download (progressive JPEG, interlaced PNG). I think you’d have to come up with a special support on the client, ie. write the image decoding part from PNG/JPEG to UIImage yourself, presumably using some library.

2) Save a small thumbnail along each image on the server. When you want to download an image, you’d first download the thumbnail, do a simple scaling to stretch it to the full image size and in the meantime download the full version. There can be multiple thumbnails in various sizes if you really want to get fancy. You’ll have more data on the server, but the client code should be fairly straightforward.

3) Maybe you already have the thumbnails on the client? In that case you can stretch the thumbnail to the full image size to create a low-resolution version while you load the rest.

And if you are asking about how to exactly code the second or third solution… You don’t really need explicit threads and I’m not sure what does “layer” mean in this context. Loading an UIImage from network is pretty easy, a bit like this:

 NSURL *url = [NSURL URLWithString:@"http://somewhere/foo.png"];
 NSURLRequest *request = [NSURLRequest requestWithURL:url];
 NSData *data = [NSURLConnection sendSynchronousRequest:request
    returningResponse:NULL error:NULL];
 UIImage *image = [UIImage imageWithData:data];

You can turn this code into a function, load and display the thumbnail and then load and display the full image. All this could be done in background so that you can do something while the data is loading.

zoul
Loading a syncrhonous request on the main thread stalls it (which is a bad user experience) and loading an `UIImage` on the main thread is unsafe (like all other `UI*` classes), so as-written this code shouldn't be recommended. Using the asynchronous `NSURLConnection` from the main thread is okay though.
rpetrich
Loading a synchronous request blocks the current thread, but as I wrote, you can run the whole code in background. That way you won’t block the main thread and still can use the simple synchronous interface to `NSURLConnection` instead of the clumsy callbacks. Loading an `UIImage` in background thread is safe, I use such code myself.
zoul