【问题标题】:Using image created with CGBitmapContextCreate as an opengl texture使用 CGBitmapContextCreate 创建的图像作为 opengl 纹理
【发布时间】:2010-08-02 09:54:15
【问题描述】:

我正在使用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 中所述,这是CGBitmapContextCreate 唯一受支持的RGB 像素格式,每像素使用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 等手动交换字节,因为这似乎非常低效。

【问题讨论】:

  • 为什么要关注每像素 5 位?为什么不让你的上下文成为最适合opengl的东西,如果你的源图像不同,让石英在将它绘制到你的上下文时进行转换?我的游戏中有各种动态纹理,从来没有遇到过这些问题。
  • 我早在 2010 年就提出了这个问题,当时我们还支持 2g 设备。 2g 和 3g 的内存都很小,而且这个应用程序不是一个游戏——它是一个电子书阅读器。我们必须为我们的文本解析/样式/布局引擎使用至少 10MB 的数据,每一点字节都是至关重要的。我不确定是否有人在 2012 年必须使用它,但也许仍然有一些应用程序会因内存警告而被杀死并希望减少内存占用。
  • @Alexey:您能否告诉我们,您为纹理加载的图像数据的分辨率是多少?

标签: iphone opengl-es core-graphics


【解决方案1】:

您确实需要交换位以将其转换为更密集的格式,例如 RGBA551 或 RGB565,因为正如您所指出的,CGBitmapContext 不支持这些格式的绘图(为了简单和高效)。

memset 不会成功,但Accelerate.framework 中有“快速”转换例程。

请参阅vImageConvert_ARGB8888toRGB565(…)vImageConvert_ARGB8888toARGB1555(…),适用于 iOS 5 及更高版本。

【讨论】:

    【解决方案2】:

    对于 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 | kCGBitmapByteOrder16 小。 5551_REV 是 kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder16Little

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 2017-10-22
      • 1970-01-01
      • 2023-03-05
      • 2010-10-04
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 2015-03-26
      相关资源
      最近更新 更多