Performing iPhone optimization on externally downloaded PNGs

| | August 8, 2015

When a PNG is added to an XCode iPhone project, the compiler optimizes it using pngcrush. Once on the device, the image’s rendering performance is very fast.

My problem is that my application downloads its PNGs from an external source at runtime (from Picasa Web albums, using the Google Data APIs). Unfortunately, these images’ performance is quite bad. When I do custom rendering on top of the image, it seems 100x slower than its internally stored counterparts. I strongly suspect this is because the downloaded images haven’t been optimized.

Does anyone know how I can optimize an externally downloaded PNG at runtime on the iPhone? I’m hoping for a class that does this. I even considered adding pngcrush’s source code to my app, which seems drastic. I haven’t been able to find an decent answer myself. I’d be very grateful for any help.


Some folks have suggested that it may be due to the file’s size, but it isn’t. During my tests, I added a toggle button to switch between using the embedded version and the downloaded version of exactly the same PNG. The only difference is that the embedded one was optimized by ‘pngcrush’ during compilation. This does some byte-swapping (from RGBA to BRGA) and pre-multiplication of alpha. (

Also, the performance I’m referring to isn’t the downloading, but the rendering. I superimpose custom painting on top of the image (overriding the drawRect method of the UIView), and it’s very choppy when the background is the downloaded version, and very smooth when it’s the embedded (and therefore optimized) version. Again, it’s exactly the same file. The only difference is the optimization, which I’m hoping I can perform on the image at runtime, on the device, after downloading it.

Thanks again for everyone’s help!

7 Responses to “Performing iPhone optimization on externally downloaded PNGs”

  1. try pincrush to trans the normal png file to the crushed png file

  2. You say you are drawing on top of the image by overriding a UIView’s drawRect: method. Are you trying to do some animation by repeatedly drawing the whole image with your custom stuff on top of it?

    You might get better results if you put your custom stuff in a separate view or layer, and let the OS deal with compositing the result over the background. The OS will only update the parts of the screen that you actually change, and won’t be repainting the entire image as often.

  3. That link you posted pretty much answers your question.

    During the build process XCode pre-processes your png so it’s in a format that’s more friendly to the graphics chip in the iPhone.

    Png’s that have not been processed like this will likely use a slower rendering path, one that deals with the non-native format and the fact that the alpha must be computed separately for each color.

    So you have two options;

    1. Perform the same work that pngcrush does and swap ordering/pre-multiply alpha. The speed up may be due to one or both of these.

    2. After you have loaded your image, you can “create” a new image from it. This new image should be in the iPhone’s native format and so should perform faster. The downside is it could potentially take up a bit more memory.


    CGRect area = CGRectMake(0, 0, width, height);
    CGSize size = area.size;
    [oldImage drawInRect:area];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
  4. Well it seems that a good way to do it (since you can’t run pngcrush on the iPhone and expect that to speed it up) would be to make your requests through a proxy that runs pngcrush. The proxy would have nice horse power to actually give you some gain over the 100x pain you feel.

  5. The fact that you say it “seems” 100x slower indicates that you have not performed any experimentation, but made a guess (it must be the PNG optimization), and are now going down a path based on a hunch.

    You should spend time to confirm what the problem is before you try to solve it. My gut says that PNG optimization shouldn’t be the issue: that mostly affects the loading of images, but once they are in memory it doesn’t matter what file format they were originally in.

    Anyway, you should try an A-B comparison, either get your code to load an optimized PNG from somewhere else and see how it compares, or make a test app that just does some drawing on the two PNG types. Once you’ve confirmed what the problem is, then you can figure out if you need to compile pngcrush into your app.

  6. On the surface, it sounds like something else is at play here. Any additional image manipulation should only add time until it’s displayed onscreen…

    Would it be at all possible to get the server to gzip the images by sending the appropriate HTTP header? (If it even helps file size much, that is.)

    Temporarily using the pngcrush source might be a good test as well, just to get some measurements.

  7. Are you storing the png at the original downloaded size? If it’s a large image it’ll take significantly longer to render.

Leave a Reply