2013-12-17 28 views
1

我有几个具有alpha透明度的PNG图像。这些显示适用于一般石英的东西,如在用户界面。但是,当我去拍摄图像并将其导入OpenGL时,我发现我得到的数据具有255的固定alpha值。我正在使用通常的UIImage转换为CGImage并渲染到上下文中。我将在下面发布相关代码。iOS PNG在将UIImage转换为CGImage for OpenGL时,Alpha通道是固定的

我做了很多搜索,最后偶然发现了这个问题,我想在这里分享一下,但它很慢,因为它必须遍历每个像素,并将原始alpha复制到alpha通道中。我很想知道解决这个问题的方法。我没有任何转换选项PNG在我的版本(不知道在哪里设置),看看它是否有助于..

感谢

首先我从我的应用程序一个UIImage我添加这样的:

UIImage *image = [UIImage imageNamed:imageName]; 

然后我转换为CGImageRef,我做平常环境中创建像仅此相关行:

CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 
              bitsPerComponent, bytesPerRow, 
              CGImageGetColorSpace(spriteImage), 
                kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

然后将这些接下来的两行是魔术让我在真正的PNG生达ta ...我可能应该检查RGBA vs其他格式,但我很懒...之后,我画了图像,然后回去修复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

如果CGDataProviderCopyData()为您提供了正确的原始数据,为什么不使用你的质地,而不是用CGContextDrawImage重绘()?你不应该需要后者,或者你的循环。 –

+0

好点....我应该尝试一下。我确实尝试过以其他方式使用它,它给出了一个错误,因为它当然是只读的,但也限制了我传入...我忘记了它是什么...好主意tho ...我应该提到这个代码来自Apple。还有的是,在它与正确的代码读取无需预先MULT阿尔法..文件的范例苴我真正的问题是,为什么是正确的,CGImage是不正确的...... – mcomet

+0

CGBitmapContextCreate()只支持预乘alpha(iOS上,至少),但CGDataProviderCopyData()从图像中提取原始像素数据,我相信这通常不是预乘。 –

回答

2

好吧,我想我会回答将q我根据我的调查和surmising ...

首先,通过的UIImage和CGImage提供的数据将有阿尔法预乘。如果您使用的是经过优化的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 

这适用于我,我得到适当的阿尔法,它是快速和正确的。一个注意我不必重新调整我的图像...如果你关心那个,那么你会像往常一样执行通常的CGBitmapContextCreate和ContextDraw,它仍然可以正确地处理数据。不要忘记释放以及...我忘了这是泄漏记忆..嘿。

希望这可以帮助别人......

0

它看到CGImageGetDataProvider(CGImage)确实阿尔法预乘。 我有一个红色= 255和alpha = 128的PNG,加载的像素有红色= 128。这是伤心....

相关问题