July 2012

Dev diary: Creation of PNG animation renderer

3 Animation file size reduction

APNGs have one issue, the file size is pretty large because every frame is standalone PNG image. I've addressed this issue by implementing two optimizations described below.

3.1 Anti-aliasing

To allow better PNG compression, anti-aliasing could be turned off. This will result in worst quality of images but interestingly enough the savings are quite large. Figure 1 shows example of animated plant where disabling of anti-aliasing saved around 50% of file size.

By default, anti-aliasing is on but you can turn it off using set antiAlias = false;.

Anti-aliased (514 KB) — Comparison of Anti-aliasing effect on quality and file size.
(a) Anti-aliased (514 KB)
No anti-aliasing (263 KB) — Comparison of Anti-aliasing effect on quality and file size.
(b) No anti-aliasing (263 KB)

3.2 Trimming frames & relative positioning

More advanced optimization is taking advantage of the fact, that APNg allows to position individual frames on arbitrary position in the resulting animation frame. Thanks to this feature, background of individual frames can be trimmed and positioned to original position.

Background of each frame is trimmed and the correct offset is set in the Frame Control Chunk (fcTL) of APNG. However this brings a bunch of problems.

L-systems in Malsys are rendered in floating-point space but bitmap (png image) has integer space as well as PNG offset. If every frame would be trimmed in floating-point space (which is the easiest way), frames will be jumping on sub-pixel level because offset is integral. Trimming must be by integer-amount.

The second problem is with background. Some browsers (good old Opera :) do not "turn on" transparency if PNG frames are without transparency channel (24 bpp). This makes background around frames black. To avoid this behavior, we can force 32 bpp rendering by for example this set bgColor = #FF000000; which will set background color to fully transparent black.

To visualize how trimming optimizes frames we can set background color to some non-fully transparent color (like set bgColor = #01AAAAAA;) to see individual frames background (Figure 2). This is also a limitation, only transparent background are supported.

By default, trimming is off but you can turn it on using set autoTrim = true;.

Visualization of frame trimming.

For those who do not see animation, Figure 3 shows all frames as individual PNGs. Note the gray background — every frame has different size.

3.3 Results

Size reduction depends on actual L-sytem. Some benefit from disabled anti-aliasing, some from trimming, some are the same no matter the optimizations. Figure 4 shows results on images from Figure 5.

JavaScript is needed for visualization of this chart.
Growing flower — L-systems from
(a) Growing flower
Dragon curve — L-systems from
(b) Dragon curve