1

私はandroidndkを初めて使用します。
ラッカス、IBMブログによる画像処理の例から学び始めました。以下の行が数行ありません。コードスニペットを理解するのを手伝ってくれる人はいますか? `

static void brightness(AndroidBitmapInfo* info, void* pixels, float brightnessValue){
    int xx, yy, red, green, blue;
    uint32_t* line;

    for(yy = 0; yy < info->height; yy++){
            line = (uint32_t*)pixels;
            for(xx =0; xx < info->width; xx++){


              //extract the RGB values from the pixel
                red     = (int) ((line[xx] & 0x00FF0000) >> 16);
                green   = (int)((line[xx] & 0x0000FF00) >> 8);
                blue    = (int) (line[xx] & 0x00000FF );

        //manipulate each value
        red = rgb_clamp((int)(red * brightnessValue));
        green = rgb_clamp((int)(green * brightnessValue));
        blue = rgb_clamp((int)(blue * brightnessValue));

        // set the new pixel back in
        line[xx] =
          ((red << 16) & 0x00FF0000) |
          ((green << 8) & 0x0000FF00) |
          (blue & 0x000000FF);
            }

            pixels = (char*)pixels + info->stride;
        }
}
`
    static int rgb_clamp(int value) {
  if(value > 255) {
    return 255;
  }
  if(value < 0) {
    return 0;
  }
  return value;
}

RGB値がどのように抽出され、このrgb_clampがどのように実行されるのか。新しいPixellを設定する理由と、pixels =(char *)pixels + info-> stride; 動作しますか?私はac/c ++の人ではなく、画像処理の知識もあまりありません。ありがとう

4

2 に答える 2

4

まず、1ピクセルについて話しましょう。私が見る限り、これは少なくとも3つのチャネルの構成です:r、g、bはすべて、1つのuint32_t値に格納され、0x00RRGGBB(32ビット/4チャネル=チャネルあたり8ビット)の形式であり、値の範囲は0..255)。したがって、分離されたr、g、およびb値を取得するには、それらをマスクする必要があります。これは、以下の3行で実行されます//extract the RGB values。たとえば、赤のコンポーネント...マスク0x00FF0000と&演算子を使用して、赤のチャネルに設定されているビットを除くすべてのビットを0に設定します。しかし、それらをでマスクすると0x00RRGGBB & 0x00FF0000 = 0x00RR0000、非常に大きな数になります。0から255の間の値を取得するには、ビットを右にシフトする必要もあります。これは、>>-オペレーター。したがって、後者の例の場合:マスクを適用した後、0x00RR0000を取得し、この16ビットを右にシフトすると(>> 160x000000RR、0〜255の数値になります。同じことが緑のチャネルでも発生しますが、8ビットの右シフトと青の値はすでに「右」ビット位置にあるため、シフトする必要はありません。

2番目の質問:何rgb_clampを説明するのは簡単です。これにより、r、gまたはb値に輝度係数を掛けた値が、値の範囲0..255を超えないことが保証されます。

輝度係数との乗算後、新しい値がメモリに書き戻されます。これは、上記の抽出とは逆の順序で行われ、今回はそれらを左にシフトして、マスクでは不要なビットを削除します。

画像の1行が処理された後、info->strideが追加されます。これは、最適化の目的で、メモリがおそらく32バイトの境界を満たすように調整されるため、1行が画像の幅だけより長くなる可能性があるため、バイトの「残り」がに追加されるためです。ポインタ。

于 2012-10-17T12:07:31.070 に答える
2

何よりもまず、ここでCの本を読むことをお勧めします:http://publications.gbdirect.co.uk/c_book/

次に、あなたの質問に答えます。

  1. RGB値はどのように抽出されますか

    lineピクセルパラメータを指すように設定されています:

    line = (uint32_t*)pixels;

    つまりpixels、32ビットの符号なし整数の配列です。

    &次に、ビットマップの高さと幅について、ビット単位のAND演算( )とビットシフト右( )の組み合わせを使用してRGB値が抽出されます>>

    あなたがどのように赤くなるか見てみましょう:

    red = (int) ((line[xx] & 0x00FF0000) >> 16);

    ここで現在の行を取得し、次に0x00FF0000マスクとしてANDを使用して、からビット24〜16を取得しますline。したがって、例としてRGBコード#123456を使用すると0x00120000red変数に残されます。ただし、まだ24〜16ビットの位置にあるため、16ビットを右シフトしてビットをにシフトダウンし0x00000012ます。

    緑と青の値に対してこれを行い、ANDマスクとビット数を調整して右にシフトします。

    バイナリ演算の詳細については、http://publications.gbdirect.co.uk/c_book/chapter2/expressions_and_arithmetic.htmlを参照してください。

  2. 何をしrgb_clampますか

    この関数は、赤、緑、または青の値が0以上または255以下であることを確認するだけです。

    のパラメータrbg_clampが-20の場合、0が返され、RGB値の設定に使用されます。パラメータがrbg_clamp270の場合、255を返します。

    各色のRGB値は、225を超えてはならず、0未満であってはなりません。この例では、255が最も明るく、0が最も暗い値です。

  3. なぜピクセルを元に戻すのですか

    ピクセルの明るさを変更し、表示できるように値を設定し直しているようです。

  4. どのように機能しpixels = (char*)pixels + info->stride;ますか?

    infoタイプの変数の構造を知らなくても、バイト単位のビットマップの幅を参照しているAndroidBitmapInfoと思いますので、次のループ反復で次の行になります。info->strideline

お役に立てば幸い

于 2012-10-17T11:59:09.127 に答える