跳到主要内容

混合与合成

三个函数都是源在前、目标在后 —— 与 palette 的 source.multiply(destination) 是同一顺序。第二个 颜色若在不同的 space,会先转换到第一个颜色的 space,结果也带着那个 space。

由于这些模式是逐分量定义的,它们需要一个类似 RGB 的刺激空间。各函数接受的 space 并不相同:

函数第一个参数接受的 space
plt_blend15 个 RGB space、xyz、xyz_d50、luma、luma_linear、luma_gamma、lms、lms_von_kries
plt_compose同上,外加 lab、luv、yxy、oklab、cam16_ucs_jab
plt_blend_equations与 plt_compose 相同

带色相的 space(hsl、lch、oklch、CAM16 JCH/QCH/…)会被拒绝 —— 逐分量混合一个色相角没有意义。 先转换:

SELECT plt_blend(plt_hsl(0, 1, 0.5), plt_hsl(120, 1, 0.5), 'multiply');
SELECT plt_to_hex(plt_blend(plt_convert(plt_hsl(0, 1, 0.5), 'srgb'),
plt_convert(plt_hsl(120, 1, 0.5), 'srgb'),
'multiply')) AS multiplied;

plt_blend(source, destination, mode)​

签名:plt_blend(source plt_color, destination plt_color, mode VARCHAR) -> plt_color

11 种可分离模式,与 CSS/PDF 的合成模型一致:

模式一句话结果
multiply更暗:source × destination
screen更亮:两个补值相乘,再取补
overlay视目标而定,用 multiply 或 screen
darken逐分量取两者中更暗的
lighten逐分量取两者中更亮的
dodge把目标朝白色提亮
burn把目标朝黑色压暗
hard_light交换 source 与 destination 的 overlay
soft_light更柔和的 hard light
difference绝对差值
exclusion对比度更低的 difference
SELECT plt_blend_modes() AS modes;
SELECT plt_to_hex(plt_blend(plt_srgb(0.5, 0.2, 0.1), plt_srgb(0.4, 0.6, 0.8), 'multiply')) AS multiply,
plt_to_hex(plt_blend(plt_srgb(0.5, 0.2, 0.1), plt_srgb(0.4, 0.6, 0.8), 'screen')) AS screen,
plt_to_hex(plt_blend(plt_srgb(0.5, 0.2, 0.1), plt_srgb(0.4, 0.6, 0.8), 'overlay')) AS overlay;

结果的 alpha 由混合本身决定:源与目标都不透明时结果也不透明,源半透明时目标会透出来:

SELECT plt_blend(plt_with_alpha(plt_srgb(0.5, 0.2, 0.1), 0.5),
plt_with_alpha(plt_srgb(0.4, 0.6, 0.8), 0.5),
'hard-light') AS result;

模式名会规范化:大小写不敏感,- 或空格视作 _,所以 'Hard Light' 等同于 'hard_light'。未知的 名字会让语句失败:

SELECT plt_blend(plt_srgb(1, 0, 0), plt_srgb(0, 0, 1), 'glow');

plt_compose(source, destination, operator)​

签名:plt_compose(source plt_color, destination plt_color, operator VARCHAR) -> plt_color

六种 Porter-Duff 算子:

算子保留
over源覆盖目标(通常的 alpha 合成)
inside源落在目标内部的部分
outside源落在目标外部的部分
atop源覆盖目标,但限于目标的区域
xor两者互不重叠的部分
plus两者之和,alpha 也算在内
SELECT plt_compose_modes() AS operators;
SELECT plt_to_hex(plt_compose(plt_with_alpha(plt_srgb(1, 0, 0), 0.5),
plt_with_alpha(plt_srgb(0, 0, 1), 0.5), 'over')) AS over,
plt_to_hex(plt_compose(plt_with_alpha(plt_srgb(1, 0, 0), 0.5),
plt_with_alpha(plt_srgb(0, 0, 1), 0.5), 'xor')) AS xor_,
plt_compose(plt_with_alpha(plt_srgb(1, 0, 0), 0.5),
plt_with_alpha(plt_srgb(0, 0, 1), 0.5), 'plus') AS plus_alpha;

plt_compose 还能用在 lab、luv、yxy、oklab 与 cam16_ucs_jab 里,plt_blend 则不行:

SELECT plt_compose(plt_with_alpha(plt_oklab(0.5, 0.1, 0.1), 0.5),
plt_with_alpha(plt_oklab(0.7, -0.1, 0.1), 0.5), 'over') AS in_oklab;

plt_blend_equations(source, destination, source_factor, destination_factor)​

签名:plt_blend_equations(source plt_color, destination plt_color, source_factor VARCHAR, destination_factor VARCHAR) -> plt_color

OpenGL 风格的形式:由你决定源与目标各有多少进入结果。十个因子中任意两两组合都接受:

SELECT plt_blend_parameters() AS factors;
SELECT plt_to_hex(plt_blend_equations(plt_with_alpha(plt_srgb(1, 0, 0), 0.5),
plt_with_alpha(plt_srgb(0, 0, 1), 0.5),
'source_alpha', 'one_minus_source_alpha')) AS blended;

'source_alpha' / 'one_minus_source_alpha' 复现了普通的 over 合成,用它来检验一对因子的行为是否 符合预期是个好办法:

SELECT plt_to_hex(plt_compose(src, dst, 'over')) AS compose_over,
plt_to_hex(plt_blend_equations(src, dst, 'source_alpha', 'one_minus_source_alpha')) AS equations
FROM (SELECT plt_with_alpha(plt_srgb(1, 0, 0), 0.5) AS src,
plt_with_alpha(plt_srgb(0, 0, 1), 0.5) AS dst);

未知的因子或算子会报错:

SELECT plt_blend_equations(plt_srgb(1, 0, 0), plt_srgb(0, 0, 1), 'half', 'one');
SELECT plt_compose(plt_srgb(1, 0, 0), plt_srgb(0, 0, 1), 'around');

列出支持的名字​

plt_blend_modes()​

签名:plt_blend_modes() -> VARCHAR[]

plt_blend 接受的 11 个模式名,顺序固定。可以用它驱动对一张颜色表的 list_transform,而不必把列表 写死在查询里。

plt_compose_modes()​

签名:plt_compose_modes() -> VARCHAR[]

plt_compose 接受的六个算子名。

plt_blend_parameters()​

签名:plt_blend_parameters() -> VARCHAR[]

plt_blend_equations 接受的十个因子名:zero、one、source_color、 one_minus_source_color、destination_color、one_minus_destination_color、source_alpha、 one_minus_source_alpha、destination_alpha、one_minus_destination_alpha。

SELECT unnest(plt_blend_modes()) AS mode, 'blend' AS used_by
FROM (SELECT 1)
UNION ALL
SELECT unnest(plt_compose_modes()), 'compose'
UNION ALL
SELECT unnest(plt_blend_parameters()), 'equations';