Friday, March 6, 2009

Animating transparent PNGs using UIKit

Lately I've come to the conclusion that it is not possible to animate a series of PNGs that have areas of transparency on top of an existing background image without incurring some sort of a performance hit the very first time the sequence is played.

Whether you use imageNamed: (automated caching) or imageWithContentsOfFile: (using manual caching of the images using NSDictionary, etc.) and drawing the images to an UIImageView instance, unless the images are visible to the user, there will be no benefit from pre-drawing the images to a disconnected UIImageView, one that has alpha = 0, or by using any other method that hides this initial first render pass of the animation IF the PNGs have any sort of transparency within them as far as I can determine.

The main reason for this is due to the fact that the hardware renderer has to composite each PNG onto the current visible background the first time the PNG is rendered. Afterwards, this information is cached and doesn't have to be recomposited, even if you move the location of the PNG (as far as my tests show anyway). If you can't see the PNG, then the compositing step of the renderer isn't occurring (as far as I know).

If you have PNGs with areas of transparency and need to animate them without an initial performance hit the first time the sequence is displayed, I suggest using OpenGL ES's support for double-buffers. The one caveat here is that the version of OpenGL ES that the iPhone supports (1.1) only accepts textures that have dimensions that are powers of 2 (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024). So if you have a series of images with dimensions 320x480 for instance, you will need to attach it to larger blank texture with dimensions 512x512 for instance (this is one method anyway). Normally image animations in OpenGL are done via a single texture that has all of the frames in it next to each other and then you simply change the texture coordinates in sequence, but I'm not sure how you would fit a series of 320x480 images inside of a single texture this way.

Any thoughts/comments on this are appreciated.