Reputation: 225
When I'm trying to draw a PNG image with transparency, using OpenGL, I get a strange black border around it:
But the original images are clean and normal:
My code:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UIImage* allIcons = [[appDelegate load_image_from_zip: pl.icons[ico_index]] retain];
CGRect rect = CGRectMake( 0, 0, allIcons.size.width/nIcons, allIcons.size.height );
UIGraphicsBeginImageContext(rect.size);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM ( currentContext, 0, allIcons.size.height );
CGContextScaleCTM ( currentContext, 1, -1 );
CGRect clippedRect = CGRectMake(0, 0, rect.size.width, rect.size.height);
CGContextClipToRect( currentContext, clippedRect);
CGRect drawRect = CGRectMake(rect.origin.x * -1, rect.origin.y * -1, allIcons.size.width, allIcons.size.height);
CGContextDrawImage(currentContext, drawRect, allIcons.CGImage);
Upvotes: 2
Views: 2413
Reputation: 3835
This is the dreaded premultiplied alpha issue. I struggled with this for a good week before figuring it out. Telling your project to not compress .png files does not solve the problem as various API calls will re-multiply the alpha. This is how i solved it.
When setting blend modes and color:
blendFuncSource = premultAlpha ? GL_ONE : GL_SRC_ALPHA;
blendFuncDestination = GL_ONE_MINUS_SRC_ALPHA;
if (premultAlpha)
{
glColor4f(colorfilter.red*colorfilter.alpha, colorfilter.green*colorfilter.alpha, colorfilter.blue*colorfilter.alpha, colorfilter.alpha);
}
else
{
glColor4f(colorfilter.red, colorfilter.green, colorfilter.blue, colorfilter.alpha);
}
You'll need to figure out of you images are using premultiplied alpha. You can do this my checking the png headers when they are loaded:
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo( image );
...
switch( bitmapInfo & kCGBitmapAlphaInfoMask )
{
case kCGImageAlphaPremultipliedFirst:
premultAlpha = YES;
srcFormat = GL_BGRA;
break;
case kCGImageAlphaFirst:
srcFormat = GL_BGRA;
break;
case kCGImageAlphaNoneSkipFirst:
srcFormat = GL_BGRA;
break;
default:
srcFormat = GL_RGBA;
}
I'm paraphrasing a lot of code here, hopefully it's still helpful.
Upvotes: 3
Reputation: 7
try these
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Upvotes: 0
Reputation: 57139
The issue is that your images have premultiplied alpha, where the color of each pixel has been multiplied by its alpha value. UIKit on the iPhone prefers premultiplied-alpha images—blending them is faster—but OpenGL doesn’t assume that, so the transparency effect of your alpha channel is sort of getting applied twice, which results in the semitransparent pixels in your image appearing darker than they actually are. Try turning off the “Compress PNG Files” option in your project’s build settings.
Upvotes: 1
Reputation: 52083
Assuming your TexEnv is the default GL_MODULEATE
try a glColor4ub(255, 255, 255, 255)
before drawing.
Upvotes: 1