【问题标题】:Converting a 24-bit PNG image to an array of GLubytes将 24 位 PNG 图像转换为 GLubytes 数组
【发布时间】:2013-04-22 19:19:51
【问题描述】:

我想做以下事情:

  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 颜色空间):

【问题讨论】:

标签: ios objective-c opengl-es png


【解决方案1】:

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

【讨论】:

  • 嗯。关于溢出的很好的一点。我会尝试看看这是否有效。
  • 嗨,我改变了它,以便我将其类型转换为 int,然后将设备类型转换为 3,然后将其类型转换回一个字节。但现在我得到所有平均像素的值 85。不知道发生了什么。
  • 可能是巧合,但 255/3 = 85。奇怪的是,我的测试图像中的大部分像素都是黑色的!
  • 事实证明,在读取图像之前,我先将其转换为 ARGB。所以我通过读取 4 个组件来修复它,丢弃第一个字节,即 alpha 组件。
【解决方案2】:

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

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 2020-09-09
    • 2012-10-14
    • 1970-01-01
    相关资源
    最近更新 更多