Black borders around PNG image, drawn with OpenGL
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, allIc开发者_如何转开发ons.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);
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.
Assuming your TexEnv is the default GL_MODULEATE
try a glColor4ub(255, 255, 255, 255)
before drawing.
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.
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);
精彩评论