c - RGBA,每个 channel 8 位大小的 alpha 反转合成,在 C 中

标签 c colors int precision alphablending

假设我有两种颜色,一种是src,另一种是dst。它们都有 4 个 channel (RGBA)。每个 channel 都是 8 位大小 (0x00 - 0xFF)。

如果 srcdst 之上,根据 Alpha compositing ,我得到了out颜色:

  • out_A = src_A + dst_A * (1 - src_A)
  • out_RGB = (src_RGB * src_A + dst_RGB * dst_A * (1 - src_A))/out_A

所以,如果我有合成颜色 outsrc,我可以获得 dst 颜色:

  • dst_A = (out_A - src_A)/(1 - src_A)<
  • dst_RGB = (out_RGB * out_A - src_RGB * src_A)/((1 - src_A) * dst_A)

在 C 中,如果必须为每个 channel 使用 8 位。我得到了 alpha 合成代码:

/*
 * [0] - R
 * [1] - G
 * [2] - B
 * [3] - A
 */
uint8_t src_raw[4], dst_raw[4], composed[4];
float src[4], dst[4], out[4];

/*
 * We get the src_raw and dst_raw color,
 * now calculate the composed color.
 */

for (int i = 0; i < 4; ++i) {
    src[i] = src_raw[i] / 255.0f;
    dst[i] = dst_raw[i] / 255.0f;
}

out[3] = src[3] + dst[3] * (1 - src[3]);
for (int i = 0; i < 3; ++i) {
    out[i] = (src[i] * src[3] + dst[i] * dst[3] * (1 - src[3])) / out[3];
}

for (int i = 0; i < 4; ++i) {
    composed[i] = out[i] * 0xFF;
}

反合成 是 smae,但具有 composedsrc 来计算 dst

问题是当从 uint8_t 转换为 float,计算并从 float 转换为 uint8_t 时,我失去了精度。

例如,如果 dst_raw = {0, 0, 255, 128}src_raw = {128, 0, 0, 64},我得到 合成颜色{51, 0, 152, 159}。但是当 composed = {51, 0, 152, 159}src_raw = {128, 0, 0, 64} 时,我得到了 dst_raw 颜色 {0 , 0, 254, 126}.

我的问题是:在使用 8 位大小来表示一个 channel 来反转 alpha 合成时,如何获得正确的 dst_raw 颜色?

最佳答案

恐怕一般来说您想要的是不可能的,因为会损失精度。

假设您的 dstAlpha 是 0x0F,那么任何目标颜色值(从 0x00 到 0xFF)的范围在输出中最多会压缩到 0x00 到 0x0F。那么根本没有足够的信息来恢复原始值。

如果从 8 位中您只保留 4 位,那么您将无法凭空恢复其他 4 位。 alpha 越低,精度损失越严重。

关于c - RGBA,每个 channel 8 位大小的 alpha 反转合成,在 C 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20043751/

相关文章:

java - 计算十六进制颜色相反的公式 ("Difference")

c - 是否有办法查看用户使用 Scanf 输入的第一个值是什么?

将十进制转换为具有长整数值的二进制 C

c - 如何启用 clang 静态分析器的 "alpha.security.taint check"检查器

c - 重新排列风格糟糕的 C 代码

python - “is”运算符对非缓存整数的行为异常

Android:如何将位图数组转换为 Int 数组?

c - 程序不断返回段错误

java - java 中十六进制数字的 extratinf RGB 分量

javascript - 通过单选按钮更改图像,用户可以选择