2017-10-18 65 views
2

负载32位图像转换为缓冲和我然后预乘与相应的α颜色值以用于混合。左乘阿尔法图像有效

下面的作品,但我想知道是否有这样做的更有效的方法,即使它只导致足够好的近似?

图像数据是这种类型的指针:

typedef struct rgba_pixel 
{ 
    uint8_t r; 
    uint8_t g; 
    uint8_t b; 
    uint8_t a; 
} rgba_pixel; 

rgba_pixel * image_data; 

for (i = 0; i < length; i++) 
{ 
    if (image_data[i].a == 0) 
     image_data[i].r = image_data[i].g = image_data[i].b = 0; 
    else if (image_data[i].a < 255) 
    { 
     alpha_factor = image_data[i].a/255.0; 
     image_data[i].r = image_data[i].r * alpha_factor; 
     image_data[i].g = image_data[i].g * alpha_factor; 
     image_data[i].b = image_data[i].b * alpha_factor; 
    } 
} 
+1

能告诉你IMAGE_DATA的和alpha_factor的类型的定义是什么? –

+0

已添加到定义中,alpha_factor是双精度型。 – phenompbg

回答

3

鉴于你argb组件unsigned char,则可以通过打开浮点乘法整数乘法和使用shr 8(提高性能除以256)而不是255除:

for (i = 0; i < length; i++) 
{ 
    if (image_data[i].a == 0) 
     image_data[i].r = image_data[i].g = image_data[i].b = 0; 
    else if (image_data[i].a < 255) 
    { 
     image_data[i].r = (unsigned short)image_data[i].r * image_data[i].a >> 8; 
     image_data[i].g = (unsigned short)image_data[i].g * image_data[i].a >> 8; 
     image_data[i].b = (unsigned short)image_data[i].b * image_data[i].a >> 8; 
    } 
} 

这将转换1 fp除法和3 fp multipli阳离子分成3个整数乘法和3个位移。

另一个改进可以通过使用联合结构的像素数据来完成:

typedef union rgba_pixel 
{ 
    struct { 
     uint8_t r; 
     uint8_t g; 
     uint8_t b; 
     uint8_t a; 
    }; 

    uint32_t u32; 
} rgba_pixel; 

然后在一次分配零到R,G和B:

//image_data[i].r = image_data[i].g = image_data[i].b = 0; 
image_data[i].u32 = 0; //use this instead 

根据https://godbolt.org/x86-64 gcc 7.2,后者在-O3处生成较少的指令。在实践中哪一种可能会或可能不会更快。

要考虑的另一件事是局部循环展开,即处理多个(例如4)每循环迭代的像素。如果你保证你的行是4的倍数,你甚至不需要额外的检查。

+0

非常感谢,我给这个一杆 – phenompbg

+0

的其他人,如果是为了避免做任何事情如果alpha为255,即。 alpha_factor将为1.0 – phenompbg

+0

噢,是的,我的错误。另外我还增加了一些其他想法。 –