我有几张带alpha透明度的PNG图片。当用于一般的Quartz内容时,例如在UI中,这些显示正确。然而,当我去拍摄图像并将其转换为OpenGL时,我发现我获得的数据具有255的实心alpha。我正在使用看似通常的UIImage转换为CGImage并渲染到上下文中。我将在下面发布相关的代码。
我已经做了很多搜索,最后偶然发现了一个方法,我想在这里分享,但它很慢,因为它必须遍历每个像素,并将原始alpha复制到alpha通道。我很想知道解决这个问题的方法。我没有在我的构建中切换任何PNG选项(不知道在哪里设置)以查看它是否有帮助..
感谢
首先,我从我的应用程序中获取了一个UIImage,我这样添加:
UIImage *image = [UIImage imageNamed:imageName];
然后我转换为CGImageRef,我做通常的上下文创建只有这个相关的行:
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height,
bitsPerComponent, bytesPerRow,
CGImageGetColorSpace(spriteImage),
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
接下来的两行是魔术让我获得REAL png原始数据......我可能应该检查RGBA与其他格式但我很懒...之后我绘制图像,然后返回并修复alpha ...是的,我知道我可以在一个循环中跳过这个字节,这对于现在来说更具可读性......
// THIS data actually HAS the alpha!!
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(spriteImage));
GLubyte *pixels = (GLubyte *)CFDataGetBytePtr(data);
// 3
CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
// Sadly we now have to loop and fix the ALPHA directly from the raw PNG source
// data as otherwise we get wrong/missing alpha...
for (int y=0; y < height; ++y) {
for (int x=0; x < width; ++x) {
int byteIndex = (bytesPerRow * y) + (x * bytesPerPixel);
spriteData[byteIndex + 3] = pixels[byteIndex +3 ];
}
}
然后我做通常的glTexture调用等...并且它工作正常..如果我遗漏上面的复制循环我得到没有alpha的实体精灵。如果我执行上述操作,我的精灵会正确地绘制透明度。
我知道iOS所做的整个预先增加的东西,但这似乎已经破了......至少希望以上可能对某人有帮助,但必须有更好的方法???
思考?谢谢!
答案 0 :(得分:2)
好吧我想我会根据自己的发现和猜测自己回答问题......
首先,UIImage和CGImage提供的数据将预先进行alpha预测。如果您正在使用经过优化的PNG,那就是它。在这一点上似乎alpha是无用的。基于Apple直接提供的示例GLImageProcessing代码,似乎获得原始PNG alpha的正确方法是使用CGImageGetDataProvider方法,如他们的示例中所示。这专门在没有任何处理的情况下获得图像。需要注意的是,数据可能是BGR而不是RGB顺序,这对于优化来说是有意义的。如果需要,他们的示例代码有转换。就我而言,我这样做:
CGImageRef spriteImage = image.CGImage;
if (!spriteImage) {
NSLog(@"Failed to load image");
exit(1);
}
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(CGImage));
pixels = (GLubyte *)CFDataGetBytePtr(data);
// … do other GL calls here like gl Gen and Bind…
// NOTE the reverse BGRA here for the 7th parameter only!:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)width, (int)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
// Don't forget to release BOTH the CF data and the CGImage or you will get memory leaks!
CFRelease(data); // Release the CF data
这适合我,我得到适当的alpha,它快速而正确。一个注意事项我不需要重新调整我的图像...如果你关心它那么你会想像往常一样做通常的CGBitmapContextCreate和ContextDraw的东西,这仍然适用于正确提供的数据。别忘了发布......我忘了这就像泄漏记忆......嘿。
希望这有助于某人...
答案 1 :(得分:0)
它看到CGImageGetDataProvider(CGImage)执行 alpha预乘。 我有一个PNG,红色= 255,alpha = 128,加载的像素为红色= 128。这很难过......