I'm in the process of coming up with a few functions that deal with rendering SVG data (vector paths, none of the cruft) to PNG files. To make life a bit easier and consistent I'm using Cairo to draw, then saving the 32-bits per pixel surface into a PNG file manually.
The thing is, as Cairo expects to composite 32-bit surfaces, the pixels use pre-multiplied alpha. PNG doesn't (Apple made the mistake of doing what they liked at this point).
It's surprisingly tricky to find concrete information on conversion between these two formats, so I've winged it a bit and come up with:-
It's probably quite inefficient, this is intended to be used in a process that focuses on quality over speed anyway.
unsigned char nAlpha, *pPtr;
// current format in memory: B G R A
// assume pPtr is pointing to B of a pixel
nAlpha = *(pPtr + 3);
if (nAlpha > 0)
d = ((*pPtr) * 255.0) + (nAlpha / 2.0);
*pPtr = (unsigned char)(d / nAlpha);
// repeat for G and R, then swap B and R as PNG pixels are R G B A
But is it right?