在给定背景和叠加背景的情况下,如何计算透明叠加层的颜色和不透明度?

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

我正在尝试对流行游戏中使用的颜色进行逆向工程。

请参阅此低质量屏幕截图作为示例:

左侧是“叠加面”,有背景颜色和叠加层,右侧只是背景。

我的平台在技术上是简单的 HTML 和 CSS,我使用 Firefox,但我希望我能使用的任何技术都能转移到大多数平台。

我在互联网上查找,发现了“颜色混合模式”和“颜色混合模式”,但除了可用的选项之外,我无法找到有关每种模式背后的数学信息。

此外,我简单的测试看看这是否是一个简单的加法问题也不起作用:

Given RGBA values X, Y and Z, mix(X, Y) = Z.

X = rgba(32, 34, 35, 1.0)
Y = rgba(124, 123, 123, 0.65)
Z = rgba(93, 92, 93, 1.0)

Test: (X.r)(X.a) + (Y.r)(Y.a) = Z.r
      32 * 1 + 124 * 0.65 = 156.65

We can also rule out that it isn't multiplication, division or any sort of basic operation here.
There's either a non-simple formula or a coefficient being used here that I'm not aware of.
      

然后我查看了维基百科关于混合模式主题的内容,并找到了一篇关于 Alpha 合成 的文章。它看起来几乎描述了我想要的东西,并且为我提供了方程式。我开发了一个小 python 脚本来看看它是否能工作,但它没有。

from typing import List

class Color(object):
    def __init__(self, r: float, g: float, b: float, a: float = 1.0) -> None:
        self.r, self.g, self.b, self.a = r, g, b, a

    def __str__(self) -> str:
        return f'Color({self.r}, {self.g}, {self.b}, {self.a:.2%})'

    def __repr__(self) -> str:
        return self.__str__()

def mix(a: Color, b: Color) -> Color:
    Ao = a.a + (b.a * (1 - a.a))
    Co: List[float] = []

    for Ca, Cb in zip([a.r, a.g, a.b], [b.r, b.g, b.b]):
        pre = (Ca + a.a) + ((Cb * b.a) * (1 - a.a))
        Co.append(pre  / Ao)
    
    return Color(r=Co[0], g=Co[1], b=Co[2], a=Ao)


bg = Color(32, 34, 35)
overlay = Color(124, 123, 123, 0.65)
c = mix(overlay, bg)

# Color(32, 34, 35, 100.00%) + Color(124, 123, 123, 65.00%) = Color(135.85, 135.55, 135.9, 100.00%)
print(f'{bg} + {overlay} = ')
print(c)

鉴于这两种颜色,我如何确定可以使用什么合适的叠加来达到相同的“叠加”颜色?我假设会有一个非常大的数字(但不是无限的,只要我们使用整数和整数百分比)。

colors overlay reverse-engineering background-color transparent
1个回答
0
投票

简短回答

CSS 规范中列出了执行 alpha 混合的数学原理。

更长的答案

第一:

*Given RGBA values X, Y and Z, mix(X, Y) = Z*

XYZ 是一个颜色空间,理想情况下您不会使用名为 X、Y 或 Z 的变量,除非您实际使用 XYZ 颜色空间,因为,会造成混乱...

然后是这个:

Test: (X.r)(X.a) + (Y.r)(Y.a) = Z.r
      32 * 1 + 124 * 0.65 = 156.65 // ????

曾经如此接近。我将重写它以摆脱 XYZ。另外,您写的答案不是 156.65,而是 112.6 记住 PEMDAS,在加法之前先乘法。 124 * 0.65 = 80.6 但还有更多...

let red = cBG.r * cBG.a + cOver.r * cOver.a;

        32 * 1 + 124 * 0.65 = 112.6

这里的错误是,即使底层颜色的 alpha 为 1,它也没有贡献全部量。

底层颜色

cBG
贡献 1 减去
cOver
的 alpha 的差值。由于
cOver.a
为 0.65,因此
cBG.a
为 0.35。换句话说,如果最大 alpha 为 1(确实如此),那么如果颜色
cOver
贡献 0.77,则颜色
cBG
只能贡献 0.33 — 在进行简单遍历时,alpha 总和必须等于 1(或更少)。

当第一种颜色是 alpha 1 的实心时,正确的数学是:

let red = cBG.r * (1 - cOver.a) + cOver.r * cOver.a;

      32 * 0.35 + 124 * 0.65 = 91.8

如果两种颜色的 alpha 都小于 1,则数学会稍微复杂一些 - 最简单的方法是始终从 alpha 为 1 的颜色开始,然后向上构建。

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