快速 Alpha 混合(仅限 CPU)

问题描述 投票:0回答:1

我目前正在优化我的手动(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 或更高版本,无汇编器(编译器应针对所有支持的平台进行自身优化。)

c performance alphablending
1个回答
0
投票

您可能无法像现在这样加速您的代码。如果您的目标有向量单元,您的编译器很可能可以对此进行向量化,并且您将使用 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 格式存储数据来稍微加快混合速度。

© www.soinside.com 2019 - 2024. All rights reserved.