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. "
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user