2013-04-29 131 views
0

数组我想做到以下几点:转换的24位PNG图像GLubytes

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

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

+0

希望这个链接帮助http://stackoverflow.com/questions/448125/how-to-get-pixel-data-from-a-uiimage- cocoa-touch-or-cgimage-core-graphics – Ram 2013-04-29 09:52:24

回答

1

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

+0

嗯。关于溢出非常好的一点。我会试着看看这是否有效。 – AlvinfromDiaspar 2013-04-30 09:16:13

+0

嗨,我改变了它,所以即时类型转换为int,然后是3,然后将它转换为一个字节。但现在我得到所有平均像素的值85。不知道发生了什么事。 – AlvinfromDiaspar 2013-05-01 10:34:33

+0

也许这是巧合,但255/3 = 85.奇怪的是,我的测试图像中的大部分像素都是黑色! – AlvinfromDiaspar 2013-05-01 10:35:41

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位。你也可以在增量子句中使用逗号运算符

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