0

我想做以下事情:

  1. 从 24 位 PNG 图像中读取 RGB 颜色值
  2. 平均 RGB 值并将它们存储到 Glubytes 数组中。

我提供了我希望执行这两个步骤的函数。我的函数返回一个 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色彩空间): 在此处输入图像描述

4

2 回答 2

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;
}
于 2013-05-01T10:47:34.357 回答
1

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

于 2013-04-29T08:52:08.120 回答