DevNote Dec-02-2009

ImageIO doesn't properly handle PNG transparency?

Dec-02-2009

As I mentioned in DevNote Nov-26-2009, OSG's imageio plugin doesn't properly draw PNG images with alpha channel. I posted this issue to the OSG list and got an interesting information that SDL has the same issue and they already have a workaround for it. According to the bug info, ImageIO premultiplies the color values with alpha (R, G, B *= A / 255) and this is the cause of the darker edges. Thus the workaround code un-multiplies the color values to get an expected result.

So I got SDL source and borrowed the workaround code from IMG_ImageIO.c. The code reverts the premultiplied RGB values for avoiding unexpected darken edge:

if ((bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst) {
  int i, j;
  Uint8 *p = (Uint8 *)surface->pixels;
  for (i = surface->h * surface->pitch/4; i--; ) {
#if __LITTLE_ENDIAN__
      Uint8 A = p[3];
      if (A) {
        for (j = 0; j < 3; ++j) {
          p[j] = (p[j] * 255) / A;
        }
      }
#else
//(snip -- Big Endian)
#endif /* ENDIAN */
     p += 4;
  }

I embedded this code to OSG's imageio plugin (src/osgPlugins/imageio/ReaderWriter.cpp) and tested it. What I got is the brighter cloud edges, Yay! But, but the tail lights doesn't look good. these still have dark (black) edges (middle picture). Ok, so my problem is half solved by SDL's workaround. I'll investigate the rest of the problem. (read part 2).

png-imageio-no-patch.png SIZE:800x600(?KB) png-imageio-SDL-patch.png SIZE:800x600(?KB) png-osgdb_png.png SIZE:800x600(?KB)

ImageIO with no patch (left), imageIO with SDL patch (center), with osgdb_png instead of imageIO (right ; expected).

You can click an image to enlarge.