PNG / image optimization for iPhone

Since Apple has a 20 MB download restriction via 3G network, the final app need to be under this 20MB limit.

So we have optimized all PNG files in order to get them as small as possible. Compressed they are now all together under 10 MB - great!

But now comes Unity and blow up the whole thing - now we are somewhere above 20 MB only for the graphics. We know about this whole RGB / DXT5 stuff - but we don't want an optimization for the GPU, we want an optimization for the download size of our app. PVRTC isn't an option either - first it compresses badly concerning file size and second you get eye cancer watching the results.

Here some numbers to think about: A PNG file has approx. 50 kB per graphic - imported into Unity (as RGBA 32-bit) the same file is now 4 MB. Compressed in the final app the size of the PNG file would reduce to 45 kB while the compressed RGBA 32-bit file in the resource folder is 242 kB - five times the size of the original PNG file.

So PNG would be great - lossless compression, great optimization possibilities concerning file size and high quality results. But unfortunately Unity destroys all these advantages by converting it to a format suitable for the GPU but not for small file size (good for runtime performance but bad for the final app size).

The WWW.LoadImageIntoTexture method (which can load PNG files) is not an option either - it is to slow at runtime and produces an enormous memory overhead.

So does anybody know a way to keep the quality of the original images while compressing the images to the size of the compressed PNG files (or even smaller)?

4 Replies

The GPU does not use PNG, so it's impossible to use that format natively. You could try reading the files and parsing the PNG images yourself, but I'm not sure you can do better than LoadImageIntoTexture. Alternately, if you stick with uncompressed Unity formats, you can use 16 bit instead of 32 bit.

In any case, your game does not need to be under 20MB. Infinity Blade, for example, is well over 500MB, and there have been many popular games over 20MB. By far the best thing you can do for sales is to be featured by Apple, and it's harder to do impressive stuff under 20MB. None of the 50 million iPod touches sold can even use 3G (and most iPads are wifi too), and all iPhone owners can use wifi or download via iTunes, so it's generally a moot point.

Well, that's totally possible, just don't use GPU, there's a thing called CPU there... And then store in memory in any format you want. The issue here that Unity and it's editor don't support that approach, preloading PNG images into whatever it needs for the GPU.

I have the same problem, making a 2D game and compression is not an option, it makes the images unusable. The source images are less than 45MB but according to the editor log my images are being exported at almost 500MB!! The lossless PNG source files would work great on iOS (even though they are slower to load) due to the simple nature of the game I don't have performance problems. But a half Gig for 45MB of data is just insane. Where's the hidden option to use PNGs instead of whatever Unity uses by default?

I guess you need one background at a time, so you just have to load one image. You could embed your images as TextAssets and load them manually with Texture2D.LoadImage. Of course loading in a png file and generating a texture out of it is not that fast, but there's no way around that. PNG is a zipped format and unpacking always takes some time.

As far as i remember you can control the generation of mipmaps and which format the loaded texture will use by specifying those when you create the Texture2D. Take a look at the TextureFormat. But keep in mind, as the docs on LoadImage stated, The format might change when you load the texture.

However if you need a certain format at runtime you can of course copy the texture to another texture with GetPixels32 and SetPixel32, but that's of course more processing overhead ;)