我正在使用quartz2d
生成图像,我希望将其用作opengl
纹理。
棘手的部分是我想尽可能少地使用每个像素的位数,所以我创建cgContext
如下:
int bitsPerComponent = 5;
int bytesPerPixel = 2;
int width = 1024;
int height = 1024;
void* imageData = malloc(width * height * bytesPerPixel);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageContext context = CGBitmapContextCreate(imageData, width, height, bitsPerComponent, width * bytesPerPixel, colorSpace, kCGImageAlphaNoneSkipFirst);
//draw things into context, release memory, etc.
正如文档here中所述,这是RGB
唯一支持的CGBitmapContextCreate
像素格式,每个像素使用16位。
所以现在我想将这个看起来像“1位跳过 - 5位红色 - 5位绿色 - 5位蓝色”的imageData上传到opengl纹理中。所以我应该这样做:
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, imageData);
这不起作用,因为在此调用中我将像素格式指定为5 red - 5 green - 5 blue - 1 alpha
。这是错误的,但似乎没有与核心图形输出相匹配的格式
还有一些其他选项,例如GL_UNSIGNED_SHORT_1_5_5_5_REV
,但这些选项不适用于iphone
。
我需要一些方法来使用这个imageData
作为纹理,但我真的不想使用memset等手动交换字节,因为这看起来非常低效。
答案 0 :(得分:2)
你需要交换位以使其变为更密集的格式,如RGBA551或RGB565,因为正如您所注意到的,CGBitmapContext不支持这些绘图格式(为了简单和高效)。
memset
不会做到这一点,但Accelerate.framework
中有“快速”转换例程。
请参阅iOS 5及更高版本中提供的vImageConvert_ARGB8888toRGB565(…)
和vImageConvert_ARGB8888toARGB1555(…)
。
答案 1 :(得分:1)
对于iOS 7.0,OS X.9及更高版本:
vImage_CGImageFormat fmt = {
.bitsPerComponent = 5,
.bitsPerPixel = 16,
.colorSpace = NULL, // faster with CGImageGetColorSpace(cgImage) if known to be RGB
.bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder16Little // ARGB1555 little endian
};
vImage_Buffer buf;
vImageBuffer_InitWithCGImage( &buf, &fmt, NULL, cgImage, kvImageNoFlags );
...
free(buf.data);
数据在buf.data中,还有图像高度,宽度和rowBytes信息。我不记得GL对是否允许行填充的要求。您可以通过预先分配buf.data和buf.rowBytes字段并在标志中传递kvImageDoNotAllocate来控制它。
565_REV是kCGImageAlphaNone | kCGBitmapByteOrder16Little。 5551_REV是kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder16Little