0

私は次のことをしたいと思います:

  1. 24 ビット PNG 画像から RGB カラー値を読み取る
  2. RGB 値を平均し、それらを Glubytes の配列に格納します。

これらの2つのステップを実行することを望んでいた機能を提供しました。私の関数は 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、いくつかのロギングで確認してください。間違いを犯したのは、これらの 3 つのパラメーターが sizeof 1 バイトであり、そのように合計できないことです。より大きな整数を使用して型キャストし、結果を型キャストして配列に戻します。(オーバーフローしている可能性が高いです)grforindexedData[j++] = (r + g + b) / 3;

于 2013-04-29T08:52:08.120 に答える