How do I display a progressive JPEG in an UIImageView while it is being downloaded?
Asked Answered
D

3

8

Downloading an image from the net and showing it in an UIImageView is fairly easy. However, this requires the image to be completely downloaded before it is shown to the user, completely defeating progressive JPEG (and PNG) images.

How can I render the partially downloaded images while the transfer is being done? I would imagine the SDK to have some callback function which would update the image, but I can't find such a function. Is it possible at all with the current iOS SDK?

Defoliant answered 19/1, 2011 at 22:22 Comment(0)
G
0

Did you try to render the UIImage partially as didReceiveData gets called … ? Something like …

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //TODO: add some error handling in case the image could not be created
    UIImage *img=[UIImage imageWithData:data];
    if (img) {
        self.imageView.image=img;
    }
}
Graiae answered 24/1, 2011 at 14:37 Comment(2)
That doesn't work as bad as I expected so I guess will do for the moment. Still, it's a little bit ugly the way the image displays the not yet downloaded areas of the image and seems to be much worse in terms of performance than progressively decompressing the image like with the raw libjpeg due to complete recalculation of the image.Defoliant
Another approach (the better one, i guess) would be to use a library like libjpeg (if available for iOS).Graiae
P
10

I know this post has about 1 year, but just in case anyone is looking for it, there is a project called NYXImagesKit that does what you are looking for.

It has a class named NYXProgressiveImageView that is a subclass of UIImageView.

All you have to do is:

NYXProgressiveImageView * imgv = [[NYXProgressiveImageView alloc] init];
imgv.frame = CGRectMake(0, 0, 320, 480);
[imgv loadImageAtURL:[NSURL URLWithString:@"http://yourimage"]];
[self.view addSubview:imgv];
[imgv release];

Also, a good option is to save your images as interlaced so that it loads with low quality and improve with the download. If the image is not interlaced it is loaded from top to bottom.

Perineurium answered 6/2, 2012 at 20:6 Comment(3)
Thanks, didn't know that ImageIO.framework was capable of doing that, and even for different file types.Defoliant
NYXProgressiveImageView is not load low quality part of progressive jpeg file. It just show the image completely once download it all.Upwind
It's baseline, not progressive as Facebook app asRetriever
G
1

There is now a small open-source library on top of libjpeg-turbo which allows decoding and displaying progressive JPEGs easily:

let imageView = CCBufferedImageView(frame: ...)
if let url = NSURL(string: "http://example.com/yolo.jpg") {
    imageView.load(url)
}

see https://github.com/contentful-labs/Concorde

Gamma answered 20/4, 2015 at 13:11 Comment(0)
G
0

Did you try to render the UIImage partially as didReceiveData gets called … ? Something like …

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //TODO: add some error handling in case the image could not be created
    UIImage *img=[UIImage imageWithData:data];
    if (img) {
        self.imageView.image=img;
    }
}
Graiae answered 24/1, 2011 at 14:37 Comment(2)
That doesn't work as bad as I expected so I guess will do for the moment. Still, it's a little bit ugly the way the image displays the not yet downloaded areas of the image and seems to be much worse in terms of performance than progressively decompressing the image like with the raw libjpeg due to complete recalculation of the image.Defoliant
Another approach (the better one, i guess) would be to use a library like libjpeg (if available for iOS).Graiae

© 2022 - 2024 — McMap. All rights reserved.