1

ビット フィールドの構造体を使用して、ピクセル内の各カラー チャネルにアクセスします。問題は、各チャネルに同じ方法で適用されるコードが非常に頻繁にあることですが、CI エンドで構造体のメンバーを反復処理できないためです。メンバーごとに同じコードのコピーを 3 つ持つか、さらに不便なことに、switch-case ステートメントを使用する必要があります。

数値を指定してメンバーにアクセスできるようにマクロを使用できれば、よりエレガントになると考えました。理想的には、.CHAN(i) が、整数変数 i には、0、1、または 2 が含まれます。ただし、そのようなマクロを作成する方法や、それが可能かどうかさえわかりません。

詳細ですが、各メンバーは12ビットのようなもので、予想される8ビットではありません。そのため、配列に変換したり、ポインターとの共用体を作成したりすることはできません。また、別のチャネルに同じことを行う前に、各チャネルに多くのことを行う必要があることが多いため、X-Macros は機能しません。つまり、各メンバーを通過するための for ループには、1 行以上のものが含まれる可能性があります。

編集:ここにいくつかのコードがあります。最初に構造体です:

typedef struct
{
    uint32_t b:12;
    uint32_t g:12;
    uint32_t r:12;
    uint32_t a:12;
} lrgb_t;

コードで私の問題がどのように見えるかの例:

for (ic=0; ic<3; ic++)
{
    for (i=0; i<curvecount; i++)
    {
        curve[i].p0.x = (double) i;
        curve[i].p3.x = (double) i+1.;

        switch (ic)     // this is what I'm trying to eliminate
        {
            case 0:
                curve[i].p0.y = pancol[i].r / 4095.;
                curve[i].p3.y = pancol[i+1].r / 4095.;
                break;
            case 1:
                curve[i].p0.y = pancol[i].g / 4095.;
                curve[i].p3.y = pancol[i+1].g / 4095.;
                break;
            case 2:
                curve[i].p0.y = pancol[i].b / 4095.;
                curve[i].p3.y = pancol[i+1].b / 4095.;
                break;
        }
        // Ideally this would be replaced by something like this, CHAN() being an hypothetical macro
        // curve[i].p0.y = pancol[i].CHAN(ic) / 4095.;
        // curve[i].p3.y = pancol[i+1].CHAN(ic) / 4095.;
    }

    ... // more stuff that ultimately results in a bunch of pixels being written, channel after channel
}
4

3 に答える 3

2

コメントで指摘されているように、構造体のメンバーは配列と整列しないビットフィールドであるため、これは実際には OP の問題に対処しません。ただし、誰かにとってまだ役立つことを願って、ここで答えを保持します。

unionはあなたが望むものだと思います。次のような構造体を書くことができます

union
{
   struct
   {
       float r;
       float g;
       float b;
   }rgb;
   float channel[3];
} color;

このようにして、構造体はメモリ内の float[3] と同じ場所に配置され、同じメンバーに構造体メンバーまたは配列内の要素として効果的にアクセスできます。

正確な構文を調べる必要があるかもしれませんが、アイデアは得られます。

于 2013-03-27T12:36:40.910 に答える
1

1 つの可能性として、繰り返されるコードを関数にラップし、それをチャネルごとに呼び出すことが考えられます。

typedef struct {
  int r:12;
  int g:12;
  int b:12;
} Pixel;

int inc(int val) {
  return val + 1;
}

int main(void) {
  Pixel p = {0, 0, 0};
  p.r = inc(p.r);
  p.g = inc(p.g);
  p.b = inc(p.b);
  return 0;
}
于 2013-03-27T12:41:17.487 に答える
0

あなたが追加したコードを読んだ後、提案されたマクロにいくつかの変更を加えました

#define CHAN(ic) \
(ic == 1) ? curve[i].p0.y = pancol[i].r / 4095; curve[i].p3.y = pancol[i+1].r / 4095; : \
(ic == 2) ? curve[i].p0.y = pancol[i].g / 4095; curve[i].p3.y = pancol[i+1].g / 4095; : \
curve[i].p0.y = pancol[i].b / 4095; curve[i].p3.y = pancol[i+1].b / 4095;

マクロ CHAN(ic) は、操作するメンバーを決定するために「ic」を評価します。'ic' が 1 の場合、メンバー '.r' が操作されます。'ic' が 2 の場合、'.g' が操作されます。この仮定の 'ic' が適切に設定されていることを確認する必要があります。そうしないと、 panco[i].b および pancol[i+1].b の値を台無しにする可能性があります。コードは次のようになりますが、マクロを少し調整する必要がある可能性が高いですが、質問があればお知らせください。

//#define CHAN(ic) here

for (ic=0; ic<3; ic++)
{
  for (i=0; i<curvecount; i++)
  {
     curve[i].p0.x = (double) i;
     curve[i].p3.x = (double) i+1.;
     CHAN(ic)
  }
  ... // more stuff that ultimately results in a bunch of pixels being written, channel after channel
}

また、私のマクロは、switch ケースとまったく同じことを行うことに注意してください。唯一の違いは、マクロで定義されていることです。私が言おうとしている点は、スイッチ ケースとマクロの違いは純粋に視覚的なものであるということです。

于 2013-03-27T13:56:13.983 に答える