2

私のAVRには、{R、G、B、x、R、G、B、x、...}(xは未使用のバイト)の形式で色の強度情報を保持する文字の配列があります。char myArray[4*LIGHTS]0x00BBGGRR番号を簡単に書き込めるようにlongint (32ビット)を書き込む簡単な方法はありますか?

私の型キャストはラフで、書き方がわかりません。long int型へのポインタを作成し、それをmyArrayと等しく設定するだけだと思いますが、グループxをmyColorに設定するように任意に指示する方法がわかりません。

uint8_t myLights[4*LIGHTS];
uint32_t *myRGBGroups = myLights; // ?

*myRGBGroups = WHITE; // sets the first 4 bytes to WHITE
                      // ...but how to set the 10th group?

編集:型キャストが適切な用語であるかどうかはわかりません。32ビットの数値を8ビットに切り捨てただけの場合はそうなると思いますか?

4

7 に答える 7

5
typedef union {
    struct {
         uint8_t    red;
         uint8_t    green;
         uint8_t    blue;
         uint8_t    alpha;
    }          rgba;
    uint32_t   single;
} Color;

Color    colors[LIGHTS];

colors[0].single = WHITE;
colors[0].rgba.red -= 5;

注: リトルエンディアン システムでは、4 バイト値の下位バイトがアルファ値になります。一方、ビッグエンディアン システムでは赤の値になります。

于 2010-01-14T19:57:48.043 に答える
2

あなたのコードは完全に有効です。myRGBGroups を通常の配列として使用できるため、10 番目のピクセルにアクセスするには使用できます

myRGBGroups[9]
于 2010-01-14T20:01:55.947 に答える
1

ユニオンの最初のフィールドがint32で、2番目のフィールドが4 * charsのベクトルである、Cユニオンの使用を考えてみてください。しかし、これがあなたにとって最良の方法であるかどうかはわかりません。

于 2010-01-14T19:51:13.377 に答える
1

これを行う場合は、AVR のエンディアンを考慮してuint32_t、コンポーネントが正しい順序で格納されていることを確認する必要があります (後でmyLights配列を介して逆参照するため)。簡単なGoogleは、AVRがデータをメモリのリトルエンディアンに格納することを示しているようですが、他のレジスタはエンディアンが異なります。

とにかく、それを行ったと仮定すると、myRGBGroups配列インデックスを使用して逆参照できます (各インデックスは 4 バイトのブロックを参照します)。したがって、10 番目のグループを設定するには、次のようにしますmyRGBGroups[ 9 ] = COLOR

于 2010-01-14T19:53:29.533 に答える
0

構造体とuint32_tを結合することは、サイズ4*LIGHTSのuint8_tを作成するよりもはるかに優れたアイデアです。これを行うもう1つのかなり一般的な方法は、正しいuint32_tを作成するために必要なビット単位の演算を実行するマクロまたはインライン関数を使用することです。

#define MAKE_RGBA32(r,g,b,a) (uint32_t)(((r)<<24)|((g)<<16)|((b)<<8)|(a))
uint32_t colors[NUM_COLORS];
colors[i] = MAKE_RGBA32(255,255,255,255);

エンディアンによっては、値を異なる順序でintに配置する必要がある場合があります。RGBA5551やRGB565などの古い16bppカラー形式の場合、バイト単位よりもビット単位の演算の観点から色を考える方が理にかなっているため、この手法は一般的です。

于 2010-01-14T21:11:03.807 に答える
0

myRGBgroup で算術演算を使用できる場合、たとえば、myRGBgroups ++ は次のグループを返します。同様に、プラス、マイナスなどを使用できます。これらの演算子は、1 バイトではなく型サイズを使用して動作します。

myRGBgroups[10] // access group as int
((uint8_t*)(myRGBgroups + 10)) // access group as uint8 array
于 2010-01-14T19:55:07.583 に答える
0

構造体の割り当てを使用して同様のことを実行できます-これにより、エンディアンの問題が回避されます。

typedef struct Color {
    unsigned char r, g, b, a;
} Color;

const Color WHITE   = {0xff, 0xff, 0xff, 0};
const Color RED     = {0xff, 0, 0, 0};
const Color GREEN   = {0, 0xff, 0, 0};

Color colors[] = {WHITE, RED};
Color c;

colors[1] = GREEN;
c = colors[1];

ただし、使用できない標準では比較が定義されておらず、割り当てc == GREENでショートカットを使用できないため(初期化のみ)、失敗します。{}c = {0, 0, 0, 0}

また、8 ビット AVR の場合 (AVR32 とは対照的に)、どちらの手法を使用してもパフォーマンスが向上しない可能性が高いことに注意してください。

于 2010-02-21T10:35:45.660 に答える