Displaying interlaced (progressive) Image in UIImageView

后端 未结 5 1870
南方客
南方客 2021-02-14 05:51

I am trying to display a JPEG image as it downloads, using part of the data, similiar to many web browsers do, or the facebook app.

there is a low-quality version of the

5条回答
  •  野的像风
    2021-02-14 06:34

    I have implemented a progressive loading solution for an app I am currently working on. It does not use progressive Jpeg as I needed more flexibility loading different-res versions, but I get the same result (and it works really well, definitely worth implementing).

    It's a camera app working in tandem with a server. So the images originate with the iPhone's camera and are stored remotely. When the server gets the image, it gets processed (using imageMagick, but could be any suitable library) and stored in 3 sizes - small thumb (~160 x 120), large thumb (~400x300) and full-size (~ double retina screensize). Target devices are retina iPhones.

    I have an ImageStore class which is responsible for loading images asynchronously from wherever they happen to be, trying the fastest location first (live cache, local filesystem cache, asset library, network server).

      typedef void (^RetrieveImage)(UIImage *image);
    
    - (void)  fullsizeImageFromPath:(NSString*)path
                                 completion:(RetrieveImage)completionBlock;
    - (void)largeThumbImageFromPath:(NSString*)path
                                 completion:(RetrieveImage)completionBlock;
    - (void)smallThumbImageFromPath:(NSString*)path
                                 completion:(RetrieveImage)completionBlock;
    

    Each of these methods will also attempt to load lower-res versions. The completion block actually loads the image into it's imageView.

    Thus
    fullsizeImageFromPath
    will get the fullsized version, and also call largeThumbImageFromPath
    largeThumbImageFromPath
    will get the large thumb and also call smallThumbImageFromPath
    smallThumbImageFromPath
    will just get the small thumb

    These methods invoke calls that are wrapped in cancellable NSOperations. If a larger-res version arrives before any of it's lower-res siblings, those respective lower-res calls are cancelled. The net result is that fullsizeImageFromPath may end up applying the small thumb, then the large thumb, and finally the full-res image to a single imageView depending on which arrives first. The result is really smooth.

    Here is a gist showing the basic idea

    This may not suit you as you may not be in control of the server side of the process. Before I had implemented this, I was pursuing the solution that David H describes. This would have been a lot more work, and less useful once I realised I also needed access to lower-res images in their own right.

    Another approach which might be closer to your requirements is explained here

    This has evolved into NYXProgressiveImageView, a subclass of UIImageView which is distributed as part of NYXImagesKit

    Finally ... for a really hacky solution you could use a UIWebView to display progressive PNGs (progressive JPegs do not appear to be supported).

    update

    After recommending NYXProgressiveImageView, I realised that this is what you have been using. Unfortunately you did not mention this in your original post, so I feel I have been on a bit of a runaround. In fact, reading your post again, I feel you have been a little dishonest. From the text of your post, it looks as if the "DEMO" is a project that you created. In fact you didn't create it, you copied it from here:

    http://cocoaintheshell.com/2011/05/progressive-images-download-imageio/ProgressiveImageDownload.zip

    which accompanies this blog entry from cocoaintheshell The only changes you have made is one NSLog line, and to alter the JPG test URL. The code snippet that you posted isn't yours, it is copied from this project without attribution. If you had mentioned this in your post it would have saved me a whole heap of time.

    Anyway, returning to the post... as you are using this code, you should probably be using the current version, which is on github:

    https://github.com/Nyx0uf/NYXImagesKit

    see also this blog entry

    To keep your life simple, you only need these files from the project:

    NYXProgressiveImageView.h
    NYXProgressiveImageView.m
    NYXImagesHelper.h
    NYXImagesHelper.m
    

    Next you need to be sure you are testing with GOOD images

    For example, this PNG works well:

    http://www.libpng.org/pub/png/img_png/pnglogo-grr.png

    You also need to pay attention to this cryptic comment:

    /// Note: Progressive JPEG are not supported see #32
    

    There seems to be an issue with JPEG tempImage rendering which I haven't been able to work out - maybe you can. That is the reason why your "Demo" is not working correctly, anyway.

    update 2
    added gist

提交回复
热议问题