假设我有两种颜色,一种是src,另一种是dst。它们都有 4 个 channel (RGBA)。每个 channel 都是 8 位大小 (0x00 - 0xFF)。
如果 src 在 dst 之上,根据 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
所以,如果我有合成颜色 out 和 src,我可以获得 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,但具有 composed 和 src 来计算 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/