1

我使用位字段的结构来访问像素中的每个颜色通道,问题是我经常有代码以相同的方式应用于每个通道,但是因为我不能只在 CI 端迭代结构的成员每个成员最多有 3 个相同代码的副本,或者更不方便的是必须使用 switch-case 语句。

我认为如果我可以使用宏以便我可以通过提供一个数字来访问成员会更优雅,理想情况下是一个可以使 .CHAN(i) 变为 .r、.g 或 .b 的宏,具体取决于整数变量 i 包含 0、1 或 2。除了我不知道如何制作这样的宏,或者即使这可能。

一个细节,但每个成员都是 12 位,而不是预期的 8 位,所以我不能只是将它变成一个数组或有一个带有指针的联合。X-Macros 也不会这样做,因为我经常需要对每个通道做很多事情,然后再对另一个通道做同样的事情,换句话说,用于遍历每个成员的 for 循环可以包含更多的内容,而不仅仅是一行。

编辑:这是一些代码,首先是结构:

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 的问题,因为他的结构上的成员是不与数组对齐的位域。不过,我会在这里保留答案,希望它仍然对某人有用。

我认为aunion是你想要的。您可以编写结构,例如

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

这样,结构将与 float[3] 在内存中的相同位置,并且您可以有效地访问相同的成员作为结构成员或数组中的元素。

您可能需要查找确切的语法,但您明白了。

于 2013-03-27T12:36:40.910 回答
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' 既不是 1 也不是 2,则将操纵 '.b' 因为在这个假设中,您必须确保正确设置了“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
}

另请注意,我的宏将与您的开关盒完全一样。唯一的区别是它是在宏中定义的,我试图说明的是开关盒和宏之间的区别纯粹是视觉上的。

于 2013-03-27T13:56:13.983 回答