昨天夜里到今天夜里,解决了两个主要问题:如何读取BMP文件来构建CGImage对象,以及如何把24-bit的BMP做成纹理放到OpenGL里。
第一个问题就贴一段代码好了。
CFBundleRef bundle = CFBundleGetMainBundle();
CFURLRef url = CFBundleCopyResourceURL(bundle, CFSTR(“filename”), CFSTR(“bmp”), NULL);
//然后调用LoadImage(CFURLRef url),就可以得到一个CGImageRef了。
CGImageRef LoadImage(CFURLRef url)
{
if (!url)
return NULL;
CGImageSourceRef isr = CGImageSourceCreateWithURL (url, NULL);
CGImageRef ir = CGImageSourceCreateImageAtIndex (isr, 0, NULL);
return ir;
}
整个过程相当郁闷,折腾了半天url总是NULL,后来才找到这个比较通用的流程。如果在windows下应该只需要读进来一个File扔给auxDIBImageLoad()就可以了,无奈在Mac下最好的替代也许就是这个CGImage,只好硬着头皮上。
第二个问题就更是体现出CGImage的怪异。
事情是这样的。glTexImage2D需要的纹理数据存放在一个空间(就叫myData)里面。已经读入的要作为纹理的图片构成的CGImage对象由ir这个指针指向。于是,必须用CGBitmapContextCreate(…)来把CGImage的数据提取出来放到myData里。而这个函数只支持有限的几种图片模式(具体可见http://developer.apple.com/qa/qa2001/qa1037.html),也就是说OS/2下面24-bit的RGB三通道的BMP是不能直接用的。然后,我就迷糊了:我读入这个图片之后,在CGImage对象里面被存成什么样了呢?如果直接读取它的BitmapInfo传进去,报错说不支持这种模式。于是就得从支持的模式里面挑一中来强制转换。最后我才算明白,恶心之处就在于CGImage把RGB的存放方式改了,而且加上了Alpha通道,放在一个32-bit的结构里,但你用CGImageGetBitmapInfo()读取出来的只是转换之前的信息。经过半天摸石头过河的实验之后才搞清楚,RGB的24-bit被变成了顺序为RGBA的32-bit。所以应该用kCGImageAlphaPremultipliedLast或者kCGImageAlphaNoneSkipLast把Alpha扔掉才行。
并且,在glTexImage2D函数里面,internalformat要用GL_RGB,format要用GL_RGBA,才能把纹理正确渲染出来。因为前者是指定纹理的储存和绘制方式,后者是指定myData里的数据是以什么格式储存的。
最后,我用Photoshop做了个RGBA的32-bit BMP放进去,BitmapInfo参数用实际读取的结果做参数居然还是报告不支持该模式,nnd,也不应该是Big-endian和Little-endian的问题啊……再说了。
4 replies on “OpenGL notes(2)”
lz
为什么我这里执行
CFURLRef url = CFBundleCopyResourceURL(bundle, CFSTR(“filename”), CFSTR(“bmp”), NULL);
会在CFSTR处出现
error: expected ‘)’
的错误?
换了种方法算是好了,lz能提供一下用图片贴图例子的源代码么?谢谢了
请在这里下载xcode project:
http://www.523b3.cn/Attachment/Lesson06-Texture_with_NeHe_bmp.zip
万分感谢,已经做好了,谢谢~~