将24位PNG图像转换为GLubytes数组

时间:2013-04-29 07:29:21

标签: ios objective-c opengl-es png

我想做以下事情:

  1. 从24位PNG图像中读取RGB颜色值
  2. 平均RGB值并将其存储到Glubytes数组中。
  3. 我提供了我希望执行这两个步骤的功能。 我的函数返回一个Glubytes数组,但是所有元素的值都是0。 所以我猜我是不正确地读取图像数据。

    阅读图像我出了什么问题? (也许我的格式不正确)。

    这是我的功能:

    + (GLubyte *) LoadPhotoAveragedIndexPNG:(UIImage *)image numPixelComponents:    (int)numComponents
    {
    // Load an image and return byte array.
    CGImageRef textureImage = image.CGImage;
    if (textureImage == nil)
    {
        NSLog(@"LoadPhotoIndexPNG: Failed to load texture image");
        return nil;
    }
    
    NSInteger texWidth = CGImageGetWidth(textureImage);
    NSInteger texHeight = CGImageGetHeight(textureImage);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    GLubyte *indexedData = (GLubyte *)malloc(texWidth * texHeight);
    GLubyte *rawData = (GLubyte *)malloc(texWidth * texHeight * numComponents);
    
    CGContextRef textureContext = CGBitmapContextCreate(
                                                        rawData,
                                                        texWidth,
                                                        texHeight,
                                                        8,
                                                        texWidth * numComponents,
                                                        colorSpace,
                                                        kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(textureContext,
                       CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight),
                       textureImage);
    CGContextRelease(textureContext);
    
    int rawDataLength = texWidth * texHeight * numComponents;
    for (int i = 0, j = 0; i < rawDataLength; i += numComponents)
    {
        GLubyte b = rawData[i];
        GLubyte g = rawData[i + 1];
        GLubyte r = rawData[i + 2];
        indexedData[j++] = (r + g + b) / 3;
    }
    
    return indexedData;
    }
    

    这是加载测试图像(PNG格式的RGB色彩空间): enter image description here

2 个答案:

答案 0 :(得分:1)

如果参数bgr在上一个for循环中生成正常值,请检查一些日志记录。你犯了一个错误的地方是indexedData[j++] = (r + g + b) / 3;这3个参数的大小为1个字节,你不能这样总结它们。使用一个更大的整数,对它们进行类型转换并将结果强制转换回数组。 (你很可能会溢出)

答案 1 :(得分:1)

除了你原来的问题,这里有一个主要问题(甚至可能是相关的)

for (int i = 0, j = 0; i < rawDataLength; i += numComponents)
{
    GLubyte b = rawData[i];
    GLubyte g = rawData[i + 1];
    GLubyte r = rawData[i + 2];
    indexedData[j++] = (r + g + b) / 3;
}

即表达式

    (r + g + b)

此表达式将在GLubyte大小的整数运算上执行。如果r + g + b的总和大于GLubyte可以保持的类型,它将溢出。每当您通过中间变量(好样式!)处理数据时,请选择足够大的变量类型来保存您可能遇到的最大值。另一种方法是将表达式转换为

    indexedData[j++] = ((uint16_t)r + (uint16_t)g + (uint16_t)b) / 3;

但是读起来很麻烦。此外,如果您正在处理已知大小的整数,请使用stdint.h中的类型。你知道,你期望每个通道有8位。您还可以在for increment子句

中使用逗号运算符
uint8_t *indexedData = (GLubyte *)malloc(texWidth * texHeight);

/* ... */

for (int i = 0, j = 0; i < rawDataLength; i += numComponents, j++)
{
    uint16_t b = rawData[i];
    uint16_t g = rawData[i + 1];
    uint16_t r = rawData[i + 2];
    indexedData[j] = (r + g + b) / 3;
}