我目前正在优化我的手动(CPU 驱动)alpha 混合(根据像素 b 的 alpha 值,像素 b 优于像素 a)。
我目前正在使用:
uint8_t invAlpha = !Alpha;
uint8_t R = (Alpha * r_src + invAlpha * r_dst) >> 8;
uint8_t G = (Alpha * g_src + invAlpha * g_dst) >> 8;
uint8_t B = (Alpha * b_src + invAlpha * b_dst) >> 8;
*pDstPix = (255 << 24) | (R << 16) | (G << 8) | B;
现在我从以下位置找到了论文“Alpha Blending with No Division Operations”:https://arxiv.org/pdf/2202.02864
本文中的一段文字解释了您可以在同一个寄存器中并行混合多个 8 位组件 alpha。
不幸的是,在该示例中,仅使用像素自身的 alpha 值进行混合。 (我什至不知道为什么这是有道理的......)
不管怎样,我只是不知道是否,特别是如何,将我的算法(三个单独的 RGB 混合)建立在这个基础上。 如何加速我的算法?
(最低 80386 / ARM Cortex-M3 或更高版本,无汇编器(编译器应针对所有支持的平台进行自身优化。)
您可能无法像现在这样加速您的代码。如果您的目标有向量单元,您的编译器很可能可以对此进行向量化,并且您将使用 SIMD 寄存器并花费大部分时间等待内存。
您的实现使用除以 256 (
>> 8
) 并四舍五入到零的更简单的近似值,而本文是关于加速除以 255 并四舍五入到最接近结果的更精确变体。
假设您的意思是
invAlpha = 255 - Alpha
,当您将全白色与完全不透明度(红色通道为 255)混合时,您的代码将计算 (255 * 255 + 0 * r_dst) >> 8
,即 (255*255)/256 = 254。
您可以像这样实现精确的版本:
uint8_t R = (Alpha * r_src + (255-Alpha) * r_dst + (255/2)) / 255;
这并不像看起来那么糟糕。除法指令非常慢,但现代编译器在除以常量时通常可以避免它们。
不幸的是,在该示例中,仅使用像素自身的 alpha 值进行混合。 (我什至不知道为什么这是有道理的......)
当您在 GIMP 中实现图层(甚至是浏览器渲染引擎)之类的东西时,将两个图层混合在一起,同时输出仍然具有 Alpha 通道,这是有意义的。如果结果没有 Alpha 通道(但源有),那么您可以通过以预乘 Alpha 格式存储数据来稍微加快混合速度。