我有一个名为blend_pixels()
的函数,其任务是根据指定的混合模式将单个像素混合到另一个像素上。几乎所有想要绘制任何东西的函数都会调用该函数。
问题是每个像素调用函数,这意味着它每秒被调用数千万次,它包含一个switch-case语句,通过所有可能的混合模式,直到找到正确的之一。
显然,这比调用直接执行所需操作的函数要慢一些,这就是我试图解决的问题。调用blend_pixels()
的父函数通常只调用它们自己作为参数调用的混合模式,因此我不能将它们称为只能执行一种混合模式的小函数。但是对于父函数的每次调用只需要做一次选择(父函数在每次调用时对很多像素进行操作,而对于每个像素调用blend_pixels()
,在循环中遍历所有必需的像素)。
该功能如下所示:
void blend_pixels(lrgb_t *bg, lrgb_t fg, int32_t p, const int mode)
{
int32_t r, g, b;
switch (mode)
{
case SOLID:
*bg = fg;
break;
case ADD:
r = (fg.r * p >> 15) + bg->r; if (r>ONE) bg->r = ONE; else bg->r = r;
g = (fg.g * p >> 15) + bg->g; if (g>ONE) bg->g = ONE; else bg->g = g;
b = (fg.b * p >> 15) + bg->b; if (b>ONE) bg->b = ONE; else bg->b = b;
break;
case SUB:
r = -(fg.r * p >> 15) + bg->r; if (r<0) bg->r = 0; else bg->r = r;
g = -(fg.g * p >> 15) + bg->g; if (g<0) bg->g = 0; else bg->g = g;
b = -(fg.b * p >> 15) + bg->b; if (b<0) bg->b = 0; else bg->b = b;
break;
case MUL:
... // you get the idea
}
}
以这种方式调用:
void parent_function(lrgb_t *fb, int w, int h, lrgb_t colour, ... int blendingmode)
{
...
for (iy=y0; iy<y1; iy++)
for (ix=x0; ix<x1; ix++)
{
p = some_weighting_formula();
blend_pixels(&fb[iy*w+ix], colour, p, blendingmode);
}
}
本身可能被称为:
parent_function(fb, w, h, orange, ... /*whatever*/, ADD);
&#34; ADD&#34;是枚举的整数
很明显,选择混合算法的任何开关案例都应该在parent_function
的循环之外完成。但是如何?
答案 0 :(得分:3)
您可以使用函数指针执行此操作。
首先为函数指针定义一个typedef:
typedef void (*blend_function)(lrgb_t *, lrgb_t, int32_t);
然后将blend_pixels
的每个部分分解为它自己的函数,每个函数都具有相同的参数并返回类型为typedef:
void blend_pixels_add(lrgb_t *bg, lrgb_t fg, int32_t p)
...
void blend_pixels_sub(lrgb_t *bg, lrgb_t fg, int32_t p)
...
void blend_pixels_mult(lrgb_t *bg, lrgb_t fg, int32_t p)
...
然后在父函数中,您可以指定函数指针类型的变量,并为其指定要使用的函数的地址:
void parent_function(lrgb_t *fb, int w, int h, lrgb_t colour, ... int blendingmode)
{
...
blend_function blend;
switch (blendingmode)
{
case ADD:
blend = blend_pixels_add;
break;
case SUB:
blend = blend_pixels_sub;
break;
...
}
for (iy=y0; iy<y1; iy++)
for (ix=x0; ix<x1; ix++)
{
p = some_weighting_formula();
blend(&fb[iy*w+ix], colour, p);
}
}
答案 1 :(得分:0)
解决您的问题&#34;并且它包含一个切换案例语句,通过所有可能的混合模式,直到找到正确的混合模式。&#34;,这可能不是真正发生的事情。
Switch语句通常被编译成所谓的跳转表。在跳转表中,代码不会遍历所有寻找正确的情况的情况,而是将switch()语句的参数用作地址数组中的索引。类似的东西:
jump_table[SOLID] -> case SOLID address
jump_table[ADD] -> case ADD address
...
因此,在这种实现中,一个正在考虑很多很多值的switch语句应该和手工编码的函数指针解决方案一样快,因为这基本上就是编译器构建的。