From 8c11e7be48e8c1de636cf7a4f2305cf883cbac55 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 4 Dec 2009 17:25:23 +0000 Subject: [PATCH] From Tatsuhiro Nishioka, "> The workaround/solution was to add a block of code at the end of the > loader to un-premultiply the alpha (now in the codebase). Applying the code brightens the semi-transparent portion, but the black edges are still there (same on both osgviewer and FlightGear). Therefore I believe that the alpha channel is completely ignored (on png, gif, tiff, etc...). I tweaked and tweaked and finally got a workaround. Please commit the enclosed file to fix these issues. My workaround is a bit tricky (and some lines are even weird for me), but it resolves the black edges. These workarounds also work on GIF, TIFF, TGA, and PSD as long as I've tested so far. Please read this for more info on this issue: http://macflightgear.sourceforge.net/home/development-notes/devnote-dec-02-2009 http://macflightgear.sourceforge.net/home/development-notes/devnote-dec-03-2009 I'm very happy if some of you guys find a better means of solving the black edges. " --- .../imageio/ReaderWriterImageIO.cpp | 58 +++++++++++++++---- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/src/osgPlugins/imageio/ReaderWriterImageIO.cpp b/src/osgPlugins/imageio/ReaderWriterImageIO.cpp index 919e219b1..8ba4accca 100644 --- a/src/osgPlugins/imageio/ReaderWriterImageIO.cpp +++ b/src/osgPlugins/imageio/ReaderWriterImageIO.cpp @@ -311,16 +311,6 @@ osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) break; } - case 16: - { - // FIXME: Is this really a reasonable assumption: GL_LUMINANCE_ALPHA? - internal_format = GL_LUMINANCE_ALPHA; - pixel_format = GL_LUMINANCE_ALPHA; - data_type = GL_UNSIGNED_BYTE; -// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); - color_space = CGColorSpaceCreateDeviceGray(); - break; - } case 24: { internal_format = GL_RGBA8; @@ -337,9 +327,17 @@ osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) #endif break; } + // + // Tatsuhiro Nishioka + // 16 bpp grayscale (8 bit white and 8 bit alpha) causes invalid argument combination + // in CGBitmapContextCreate. + // I guess it is safer to handle 16 bit grayscale image as 32-bit RGBA image. + // It works at least on FlightGear + // + case 16: case 32: { - + internal_format = GL_RGBA8; pixel_format = GL_BGRA_EXT; data_type = GL_UNSIGNED_INT_8_8_8_8_REV; @@ -348,6 +346,7 @@ osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); // bitmap_info = kCGImageAlphaPremultipliedFirst; + #if __BIG_ENDIAN__ bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else @@ -380,6 +379,43 @@ osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) CGContextRelease(bitmap_context); + // + // Reverse the premultiplied alpha for avoiding unexpected darker edges + // by Tatsuhiro Nishioka (based on SDL's workaround on the similar issue) + // http://bugzilla.libsdl.org/show_bug.cgi?id=868 + // + if (bits_per_pixel > 8 && (bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst) { + int i, j; + GLubyte *pixels = (GLubyte *)image_data; + for (i = the_height * the_width; i--; ) { + GLuint *value = (GLuint *)pixels; +#if __BIG_ENDIAN__ + // + // swap endian of each pixel for avoiding weird colors on ppc macs + // by Tatsuhiro Nishioka + // FIXME: I've tried many combinations of pixel_format, internal_format, and data_type + // but none worked well. Therefore I tried endian swapping, which seems working with gif,png,tiff,tga,and psd. + // (for grayscaled tga and non-power-of-two tga, I can't guarantee since test images (made with Gimp) + // get corrupted on Preview.app ... + *value = ((*value) >> 24) | (((*value) << 8) & 0x00FF0000) | (((*value) >> 8) & 0x0000FF00) | ((*value) << 24); +#endif + GLubyte alpha = pixels[3]; + if (alpha) { + for (j = 0; j < 3; ++j) { + pixels[j] = (pixels[j] * 255) / alpha; + } + } + pixels += 4; + } + } + + // + // Workaround for ignored alpha channel + // by Tatsuhiro Nishioka + // FIXME: specifying GL_UNSIGNED_INT_8_8_8_8_REV or GL_UNSIGNED_INT_8_8_8_8 ignores the alpha channel. + // changing it to GL_UNSIGNED_BYTE seems working, but I'm not sure if this is a right way. + // + data_type = GL_UNSIGNED_BYTE; osg::Image* osg_image = new osg::Image; osg_image->setImage(