我使用位字段结构来访问像素中的每个颜色通道,问题是我经常以相同的方式对每个通道应用代码,但因为我不能只迭代结构的成员在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
}
答案 0 :(得分:2)
正如评论中指出的那样,这并没有真正解决OP的问题,因为他的结构上的成员是不能与数组对齐的位域。我会在这里保留答案,希望它对某人有用。
我认为union
就是你想要的。
您可以编写结构,例如
union
{
struct
{
float r;
float g;
float b;
}rgb;
float channel[3];
} color;
这样结构将与float [3]在内存中的相同位置,并且您可以有效地访问与结构成员相同的成员或作为数组中的元素。
您可能需要查找确切的语法,但您明白了。
答案 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;
}
答案 2 :(得分: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
}
另请注意,我的宏将与您的开关案例完全相同。唯一的区别是它是在宏中定义的,我试图做的是切换案例和宏之间的区别纯粹是可视化的。