0
 for(unsigned int  h=0; h<ImageBits.iHeight; h++)
  {
        for(unsigned int  w=0; w<ImageBits.iWidth; w++)
        {
              // So in this loop - if our data isn't aligned to 4 bytes, then its been padded
              // in the file so it aligns...so we check for this and skip over the padded 0's
              // Note here, that the data is read in as b,g,r and not rgb as you'd think!
              unsigned char r,g,b;
              fread(&b, 1, 1, fp);
              fread(&g, 1, 1, fp);
              fread(&r, 1, 1, fp);

              ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);

        }// End of for loop w

        //If there are any padded bytes - we skip over them here
        if( iNumPaddedBytes != 0 )
        {
              unsigned char skip[4];
              fread(skip, 1, 4 - iNumPaddedBytes, fp);
        }// End of if reading padded bytes

  }// End of for loop h

私はこのステートメントを理解していません、そしてそれはどのようにピクセルのrgb値を保存しますか

ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);

<<ビット単位のシフト演算子を読みましたが、それがどのように機能するのかまだわかりません。誰かがここで私を助けてくれますか。

4

3 に答える 3

2

赤、緑、青の別々の値を1つの変数に変換する必要があるため、それぞれ16ビットと8ビットを「左」にプッシュして、赤の8ビットを整列させ(開始-16)、8ビットを取得します。緑(開始-8)と残りの色の場合。

次のことを考慮してください。

 Red   -> 00001111
 Green -> 11110000
 Blue  -> 10101010

Then RGB -> that has 24 bits capacity would look like this initially ->
-> 00000000 00000000 00000000
(there would actually be some random rubbish but it's easier to
demonstrate like this)

Shift the Red byte 16 places to the left, so we get 00001111 00000000 00000000.
Shift the Green byte 8 places to the left, so we have 00001111 11110000 00000000.
Don't shift the Blue byte, so we have 00001111 11110000 10101010.

ユニオンでも同様の結果を得ることができます。これが、なぜこのようにするのかについての詳細です。変数にアクセスする唯一の方法は、そのアドレス(通常は変数名またはエイリアスにバインドされている)を取得することです。

つまり、最初のバイトのアドレスのみがあり、それが3バイト幅の変数である場合、アドレス指定されたバイトの隣にある次の2バイトが私たちに属することが保証されます。したがって、文字通り左に「ビットをプッシュ」(シフト)して、変数の残りのバイトに「フロー」することができます。そこにポインタ算術ポインタを置くこともできますし、すでに述べたように、ユニオンを使用することもできます。

于 2012-05-25T14:46:54.287 に答える
1

ビットシフトは、値を構成するビットを指定した数だけ移動します。

この場合、色の値を使用して行われるため、intなどの単一の4バイト構造に複数の1バイトコンポーネント(0〜255の範囲にあるRGBAなど)を格納できます。

このバイトを取る:

00000011

これは10進数で3に相当します。RGBおよびAチャネルの値3を格納する場合は、この値をintに格納する必要があります(intは32ビットです)。

R        G        B        A
00000011 00000011 00000011 00000011 

ご覧のとおり、ビットは8つの4つのグループに設定されており、すべて値3に等しくなっていますが、この方法で保存された場合のR値をどのように判断しますか?

G / B / A値を削除すると、

00000011 00000000 00000000 00000000

これはまだ3-に等しくありません-(実際にはそれはかなりの数です-12884901888私は思います)

この値をintの最後のバイトに入れるには、ビットを24桁右にシフトする必要があります。例えば

12884901888 >> 24

その場合、ビットは次のようになります。

00000000 00000000 00000000 00000011

そして、あなたはあなたの価値「3」を持っているでしょう

基本的には、値をより適切に操作できるように、ストレージ構造内でビットを移動する方法にすぎません。RGBA値を単一の値に入れることは、通常、ビットの詰め込みと呼ばれます

于 2012-05-25T14:51:07.773 に答える
1

これを視覚化していくつかのステップに分けてみましょう。そうすれば、それがいかに簡単であるかがわかります。

ARGB32ビット変数があるとしましょう。これは次のように表示できます。

int rgb = {a: 00, r: 00, g: 00, b: 00} (もちろん、これは有効なコードではありません。今のところ、Aは除外しておきましょう)。

もちろん、これらの各色の値は8ビットです。

ここで、新しい値を配置する必要があり、各色に3つの8ビット変数があります。

unsigned char r = 0xff, g=0xff, b=0xff

基本的に実行しているのは、32ビット変数を取得し、これを実行することです。

rgb |= r << 16(赤の16ビットを左にシフトします。その右のすべては0のままになります)

だから今私たちは持っています

rgb = [a: 00, r: ff, g: 00, b: 00]

そして今、私たちはします:

rgb = rgb | (g << 8)(既存の値を取得し、それをその場所にシフトされた緑とORすることを意味します)

だから私たちは [a: 00, r: ff, g: ff, b: 00]

そして最後に...

rgb = rgb | b(値を取得し、それを青の8ビットとOR演算することを意味します。残りは変更されません)

私たちを残して[a: 00, r: ff, g: f, b: ff]

これは32ビット(アルファはこの例とは無関係であるため、実際には24)の色を表します。

于 2012-05-25T14:55:36.060 に答える