WezTerm Lua API 详解:`color:complement_ryb()` 与基于 RYB 色彩模型的补色计算
在 WezTerm 中通过 Lua 配置生成配色方案时,常常需要根据一个基色自动推导出与之协调的对比色。color:complement_ryb() 正是为此提供的核心方法:它返回指定颜色的补色(complement),但与常规的 RGB 色环计算不同,它走的是RYB(红-黄-蓝)色彩模型——也就是画家口中"艺术家色轮"(artist's color wheel)的补色逻辑。读完本文,你将掌握该方法的用法、它与 color:complement() 的差异、背后的色相换算算法,以及如何把它用于程序化配色。
方法签名与基本行为
color:complement_ryb()
- 返回值:一个新的
Color对象,即当前颜色的 RYB 补色; - 可用版本:自 WezTerm
20220807-113146-c2fee766版本起引入; - 输入输出:接受任意
Color对象(内部以 SRGBA 存储),返回同样是 SRGBA 表示的Color对象。
调用方必须是 Color 对象。Color 对象可以通过 wezterm.color.parse() 解析字符串得到,也可能由 WezTerm 的各类函数与方法返回(参见 Color 对象总览)。
local wezterm = require("wezterm")
local base = wezterm.color.parse("red") -- 基色:纯红
local comp = base:complement_ryb() -- 基于 RYB 模型计算补色
wezterm.log_info(tostring(comp)) -- 输出补色的字符串表示
从 Lua 绑定层面看,该方法注册于 lua-api-crates/color-funcs/src/lib.rs 的 ColorWrap 用户数据类型中,底层通过 RgbaColor::complement_ryb() 实现:
methods.add_method("complement_ryb", |_, this, _: ()| Ok(this.complement_ryb()));
什么是 RYB 色彩模型
RYB(Red-Yellow-Blue,红黄蓝)是一种减色色彩模型,历史上由画家在混合颜料时总结而成。它的三个原色是红、黄、蓝,两两相混得到橙、绿、紫这三个二次色,六者共同构成"艺术家色轮"。由于颜料混色的感知特性,RYB 色环上相距 180° 的颜色,在画家眼中往往比基于 RGB(加法色)色环的补色关系更自然、更协调。
补充:
color:complement_ryb()使用 RYB 色彩模型,其补色比 RGB 模型的补色更贴近艺术家对"混合颜色"的直觉。
算法原理:HSL 色相角度在 RGB 与 RYB 之间的双向映射
原文档说明了整体流程:转换为 HSL → 将色相角换算为对应的 RYB 角度 → 旋转 180° → 再换算回 RGB → 转回 RGBA。我们可以在 color-types/src/lib.rs 中找到完整的实现来印证这一过程。
核心入口是 SrgbaTuple::complement_ryb(),它直接复用了 adjust_hue_fixed_ryb(180.):
pub fn complement_ryb(&self) -> Self {
self.adjust_hue_fixed_ryb(180.)
}
而 adjust_hue_fixed_ryb 完整呈现了文档描述的四个步骤(color-types/src/lib.rs#L608-L617):
pub fn adjust_hue_fixed_ryb(&self, amount: f64) -> Self {
let (h, s, l, a) = self.to_hsla(); // 1. 转 HSL
let h = rgb_hue_to_ryb_hue(h); // 2. RGB 色相角 → RYB 色相角
let h = normalize_angle(h + amount); // 3. 旋转 180°,并归一化到 [0, 360)
let h = ryb_huge_to_rgb_hue(h); // 4. RYB 色相角 → RGB 色相角
Self::from_hsla(h, s, l, a) // 5. 用原饱和度/亮度重建 RGBA
}
注意:旋转只改变色相,饱和度(S)与明度(L)原样保留,因此补色的明暗、鲜艳程度与基色保持一致,只在对立的色相位置上。
色相映射表:分段线性换算
RGB 与 RYB 的色相角并非简单线性对应,WezTerm 采用分段线性映射。正方向 rgb_hue_to_ryb_hue(color-types/src/lib.rs#L659-L675)按 7 个区间换算:
| RGB 色相区间(°) | RYB 色相区间(°) |
|---|---|
| 0 – 35 | 0 – 60 |
| 35 – 60 | 60 – 122 |
| 60 – 120 | 122 – 165 |
| 120 – 180 | 165 – 218 |
| 180 – 240 | 218 – 275 |
| 240 – 300 | 275 – 330 |
| 300 – 360 | 330 – 360 |
例如,RGB 色环中红在 0°、黄在 60°,而 RYB 色环中红被压缩到 0°、黄被推至 60°、绿大致对应 122° 附近……这套表在视觉上把"画家直觉"量化进了程序。
逆变换 ryb_huge_to_rgb_hue(color-types/src/lib.rs#L679-L695)则执行完全相反的分段映射,保证"转过去再转回来"不会破坏色相。每个区间内通过 map_range 做线性插值,normalize_angle(color-types/src/lib.rs#L705-L711)负责把旋转后的角度收拢到 [0°, 360°),从而支持负角度与超过 360° 的角度自动回绕。
complement_ryb() 与 complement() 的区别
原文档特意指出它与 color:complement() 互为参考。两者的差异就在于旋转所基于的色环模型:
| 方法 | 色相换算 | 计算结果特点 |
|---|---|---|
complement() |
直接在 HSL 色相角上加 180°(color-types/src/lib.rs#L585-L587) | RGB 模型补色,如红的补色偏向青色系 |
complement_ryb() |
先换算到 RYB 角度,旋转 180° 后再换回 RGB | RYB 模型补色,更贴近艺术家直觉,如红的补色是绿色系 |
以纯红(#ff0000)为例:RGB 补色约为青色 #00ffff(色相 180°),而 RYB 补色经映射后更接近绿色系。这正体现了两种色彩模型对"补色"的认知差异。
实战:把补色用于程序化配色
complement_ryb() 最常见的场景是在 wezterm Lua 配置中程序化生成配色方案,例如以主色调为基准自动推导前景色、强调色或分隔色:
local wezterm = require("wezterm")
-- 用主色调的 RYB 补色作为强调色,保证视觉协调
local accent = wezterm.color.from_hsla(210, 0.8, 0.6, 1.0)
local accent_complement = accent:complement_ryb()
return {
colors = {
accent = tostring(accent_complement),
},
}
配合 wezterm.color.from_hsla()、color:adjust_hue_fixed_ryb() 等方法,可以在不硬编码任何色值的前提下,让整套配色随一个基准色自动衍生:
adjust_hue_fixed_ryb(180)得到补色,与complement_ryb()等价;triad()三个色相各隔 120°;square()四个色相各隔 90°;- 再用 color:saturate()、color:lighten() 等微调明度与饱和度,即可生成完整的色板。
小结
color:complement_ryb()返回基于 RYB 艺术家色轮的补色,由 color-types/src/lib.rs 中adjust_hue_fixed_ryb(180.)实现;- 算法本质是:HSL 化 → RGB/RYB 色相分段线性互转 → 旋转 180° → 重建 RGBA;
- 需要严格"颜色科学"意义的补色时用 color:complement(),需要画家直觉的协调色时用
complement_ryb(); - 它是 WezTerm 程序化生成配色方案(Color 对象方法集)中的重要一环,适合在 Lua 配置中动态推导协调色。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K637- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python310
cherry-studio🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端TypeScript2 K146
hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程Python46467
new-apiAI模型聚合管理中转分发系统,一个应用管理您的所有AI模型,支持将多种大模型转为统一格式调用,支持OpenAI、Claude、Gemini等格式,可供个人或者企业内部管理与分发渠道使用。🍥 A Unified AI Model Management & Distribution System. Aggregate all your LLMs into one app and access them via an OpenAI-compatible API, with native support for Claude (Messages) and Gemini formats.Go20043
JeecgBoot🔥企业级低代码平台集成了AI应用平台,帮助企业快速实现低代码开发和构建AI应用!前后端分离架构 SpringBoot,SpringCloud、Mybatis,Ant Design4、 Vue3.0、TS+vite!强大的代码生成器让前后端代码一键生成,无需写任何代码! 引领AI低代码开发模式: AI生成->OnlineCoding-> 代码生成-> 手工MERGE,显著的提高效率,又不失灵活~Java33951