【问题标题】:Premultiplying image alpha efficiently有效地预乘图像 alpha
【发布时间】:2018-03-30 00:10:38
【问题描述】:

将 32 位图像加载到缓冲区中,然后我将颜色值与相应的 alpha 进行预乘以用于混合。

以下工作,但我想知道是否有更有效的方法来做到这一点,即使它只会产生足够好的近似值?

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

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;
    }
}

【问题讨论】:

  • 能否给出image_data和alpha_factor类型的定义?
  • 添加到定义中,alpha_factor 是双精度值。

标签: c image-processing optimization graphics cairo


【解决方案1】:

鉴于您的 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 乘法转换为 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 的倍数,即使没有额外的检查,你也可以这样做。

【讨论】:

  • 非常感谢,我会试一试
  • else if 是为了避免在 alpha 为 255 时执行任何操作,即。 alpha_factor 将为 1.0
  • 哦,是的,我的错。我还添加了一些额外的想法。
猜你喜欢
  • 2011-06-30
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 2016-04-28
相关资源
最近更新 更多