展示HN:Ember – Redshift兼容调色板

Hacker News Top 工具

摘要

Ember提供针对Redshift等暖屏过滤器优化的调色板,旨在提升可用性,并支持导出终端主题、图表、热图和UI元素。

大多数调色板在启用强烈的Redshift或夜间模式过滤器时,由于主动抑制绿色和蓝色通道,会出现崩溃。我制作了一个不会崩溃的调色板。<p>Ember的终端、图表、热图和UI调色板经过设计和测试,在Redshift和非Redshift条件下尽可能保持可区分性...因此不再出现重复颜色(更糟糕的是颜色消失)!
查看原文
查看缓存全文

缓存时间: 2026/08/14 21:30

carpdiem/ember 项目来源:https://github.com/carpdiem/ember

Ember:适用于夜班模式/红移的色彩调色板

专为终端、图表、热力图和UI界面设计的色彩方案,在开启或关闭高强度暖屏过滤后均能保持可用性。

CI(持续集成)状态:CI
许可证:MIT
Python 3.10+

Ember 旨在解决传统色彩方案在开启红移模式后颜色难以区分的问题。Ember 的核心目标是在各类色温过滤器下保持颜色辨识度。仅在满足此目标后,才会进一步调整因红移而衰减的色彩通道,以提升日间(即未应用红移时)的视觉区分度。

Ember 提供四种色彩方案:

3400K 方案适用于通用场景,大致针对 MacBook 最大夜班模式效果优化。2000K 和 1200K 方案则专为“深度红移“爱好者(及天文学家)设计。

一个有趣的现象是:2000K 和 1200K 的极端红移方案比 3400K 方案的颜色类别更少。这是因为极端红移大幅压缩了可感知的色彩空间!下文将详细说明…

每种方案均基于命令式 sRGB 色值构建,在对应色温的模拟通道 RGB 增益下验证,并导出为终端主题(Alacritty、iTerm2、Windows Terminal)、UI 界面角色色、分类图表色彩、256级渐进映射表,以及 Matplotlib/CSS/JSON/Python 格式文件。

Ember 本身不实施过滤器,请继续使用您现有的过滤工具。


四种色彩方案

3400K 暗色

3400K 暗色主题——包含六种背景色阶、三种前景文字角色、六种分类色彩、六种终端 ANSI 强调色,以及 256级渐进映射表

3400K 亮色

3400K 亮色主题——包含六种背景色阶、三种前景文字角色、六种分类色彩、六种终端 ANSI 强调色,以及 256级渐进映射表

2000K 暗色

2000K 暗色主题——包含六种背景色阶、三种前景文字角色、四种分类色彩、四种终端强调色(品红=红,青色=绿),以及 256级渐进映射表

1200K 暗色

1200K 暗色主题——包含六种背景色阶、三种前景文字角色、三种分类色彩、三种终端强调色(蓝色=黄,品红=红,青色=绿),以及 256级渐进映射表

以上均为实际导出的命令式 sRGB 色值。目标过滤强度越深,方案中的颜色类别就越少;别名化的终端槽位标记为“别名“而非伪装成额外颜色。


应用红移过滤前后的对比

所有四种方案的分类色彩与渐进映射表,分别展示命令色值与对应配置文件的模拟暖色变换效果

终端效果

相同代码在四种方案下的渲染效果,分别展示未过滤与模拟过滤后的输出

图表与热力图

相同热力图、柱状图与折线图在四种方案下的渲染效果,分别展示未过滤与模拟过滤后的输出

颜色类别消失的原因

3400K、2000K 和 1200K 暖过滤模型下 RGB 通道的存活率

暖色过滤并非叠加色调图层,而是通过不同增益系数乘以红、绿、蓝三通道。在 Ember 的 1200K 模型中,蓝色增益为零,因此仅在蓝色通道有差异的颜色会产生相同输出。故较深的方案会减少颜色类别数量,而非假装别名化颜色仍保持区分度。

过滤行的显示是确定性信号模拟——即命令式 sRGB 色值乘以各配置文件的公开增益系数。它们并非摄影作品、校准物理色温或对所有显示管线的预测。判断效果前请关闭所有活跃的暖色过滤器,否则屏幕会对结果进行二次变换。


如何选择配置文件

色彩方案适用场景分类色数量
3400k-dark近黑色通用暖色主题6
3400k-light浅色界面搭配中等暖色偏移6
2000k-darkRedshift 设置在 2000K 附近4
1200k-dark极端 1200K 压力测试场景3

除非您刻意使用深度过滤,否则请从 3400k-dark 开始。2000K 和 1200K 方案仅提供暗色版本,因为过滤后的浅色画布会变成大面积橙红色区块。


配置 Ember

1. 获取文件

终端主题、CSS 及 JSON 清单:

git clone https://github.com/carpdiem/ember.git
cd ember

Python 用户可跳过克隆,直接从 GitHub 安装:

python -m pip install "ember-palettes @ git+https://github.com/carpdiem/ember.git"

2. 导入终端主题

  • Alacritty:themes/terminal/alacritty/ 复制文件到配置目录,然后在 alacritty.toml 中导入:

    mkdir -p ~/.config/alacritty/themes
    cp themes/terminal/alacritty/2000k-dark.toml ~/.config/alacritty/themes/
    
    [general]
    import = ["~/.config/alacritty/themes/2000k-dark.toml"]
    
  • iTerm2: 打开 设置 → 配置文件 → 颜色 → 颜色预设 → 导入,选择 themes/terminal/iterm2/ 中的文件。

  • Windows Terminal: 打开 设置 → 打开 JSON 文件,将 themes/terminal/windows-terminal/ 中的对象复制到根目录 schemes 数组,然后将配置文件的 colorScheme 设置为其精确 name

终端指南 包含完整导入步骤,并解释深度配置下精简 ANSI 色槽的行为。

3. 使用 UI 界面角色色

每种方案在 JSON、CSS 和 Python surfaces() API 中提供相同的有序角色色:

角色用途
bg_0应用程序基础画布
bg_1低强调邻接区域或侧边栏
bg_2普通面板或卡片
bg_3嵌套面板、活动控件或悬停状态
bg_4浮动面板、菜单或弹出层
bg_5选中行、选区或焦点区域
fg_0主要文字和核心标签
fg_1大型辅助文字或图形(非正文字号)
fg_2柔和的非必要元数据或装饰

六种背景色构成单调递进色阶。bg_0 始终为画布基色,bg_5 为最强背景状态:暗色方案向 bg_5 逐渐变亮,亮色方案向 bg_5 逐渐变暗。

Matplotlib

import matplotlib.pyplot as plt
from ember import categorical, categorical_norm, encode_categories, sequential, surfaces

palette = "2000k-dark"
ui = surfaces(palette)
labels = ["control", "alpha", "beta", "gamma"]
order = ["control", "alpha", "beta", "gamma"]
category_ids = encode_categories(labels, order, slug=palette)

fig, (points, image) = plt.subplots(1, 2)
fig.patch.set_facecolor(ui["bg_0"])
points.set_facecolor(ui["bg_2"])
image.set_facecolor(ui["bg_3"])

points.scatter(
    [1, 2, 3, 4],
    [1.2, 2.4, 1.8, 3.1],
    c=category_ids,
    cmap=categorical(palette),
    norm=categorical_norm(palette),
)
image.imshow([[0.0, 0.4], [0.7, 1.0]], cmap=sequential(palette))
plt.show()

categorical_norm()encode_categories() 传递方案标识符,确保容量检查匹配所选方案。渐进映射始终提供 256 个标准浮点采样点,与分类色彩数量无关。

CSS

加载 ember.css,然后选择方案:

<html data-ember-palette="2000k-dark">
...
</html>
[data-ember-palette] {
  color: var(--ember-fg-0);
  background: var(--ember-bg-0);
}
.panel { background: var(--ember-bg-2); }
.panel:hover { background: var(--ember-bg-3); }
.popover { background: var(--ember-bg-4); }
.selected { background: var(--ember-bg-5); }
.series-a { color: var(--ember-category-one); }
.heatmap-key { background: var(--ember-sequential); }

CSS 提供 11 个代表性的 8位梯度节点。JSON 清单 和 Python 包保留完整的 256 个标准浮点采样点,以及界面角色色、分类色彩、ANSI 色槽、增益配置和测量结果。


背后的科学原理

1. 建模传输到显示器的信号

Ember 将暖色显示变换近似为 sRGB 通道的独立增益调整:

显示 RGB ≈ 命令 RGB × [红增益, 绿增益, 蓝增益]
配置RGB 增益基础
3400k[1.00, 0.74, 0.53]暖白色工程替代值
2000k[1.0000, 0.5436, 0.0868]固定 Redshift 2000K 信号查找表
1200k[1.0000, 0.3094, 0.0000]固定 Redshift 1200K 信号查找表

在 1200K 时,蓝色对模拟输出无贡献;2000K 时仅保留 9%。因此常规 sRGB 色差并非夜间辨识度的可靠指标——两种颜色在日间可能差异显著,过滤后却趋于一致。

这些是软件信号模型,并非校准的物理色温。实际效果还取决于显示器、操作系统、校准设置、亮度及环境光。JSON 清单还在四个 ±5% 绿/蓝增益拐角处报告分类色彩、终端组、前景/背景对比度及渐进间距的敏感度诊断。这些采样点揭示邻近模型敏感度,并非连续增益盒内的全局极值,也非显示校准测量。

2. 优先解决约束状态

Ember 将日间和夜间视为同一命令色彩的两种视图。不将两者质量平均为单一评分,因为优秀的日间间距无法补偿夜间颜色碰撞。

  1. 为 Oklab 色彩空间中的对比度、明度/色度几何及最小感知分离度设定严格的变换目标。
  2. 在满足变换目标的命令色彩中,选择日间分离度强的中等色度集合。

这颠倒了常规工作流程。在 1200K 时,仅调整蓝色不会影响变换后的色彩,因此 Ember 可利用这个原本会丢失的通道提升日间辨识度。在 2000K 时,由于存在微弱蓝色残余,这种自由度较小。

生成发布检查确保每个序列化强调色与其命令变换目标的 ΔEOK 差值在 0.15 以内。分类色彩还必须同时通过 fg_0/fg_1/fg_2 完整色阶验证,而非仅彼此区分。2000K 和 1200K 色组在所有四个采样增益拐角处重复执行分类间距、前景清晰度和背景对比度检查。

3. 保持高频像素中性,将色彩用于语义表达

人类视觉通过明度通道传递空间细节的能力强于色彩通道。因此密集饱和的字形与对比色相不适合消耗有限的夜间色域。

下方对比展示了实际效果:纯白经变换后变为比 Ember 米色正文更亮的橙色,而日间深灰则变为比 Ember 近黑画布更显著的铁锈色信号。

错误方案与 Ember 在精确暖色变换下的对比

Ember 将大多数像素置于暖中性界面色,使用米色而非纯白作为正文色彩,并将更高色度保留给语义强调色。每个可作为前景的终端强调色在目标变换后仍保持与终端基底背景 (bg_0) 的 4.5:1 对比度。fg_1fg_2 仍可用于大型辅助文字和非必要元数据。

4. 通过色彩与结构保护辨识度

在当前发布门控下,Ember 在 3400K 支持六种分类辨识度,2000K 支持四种,1200K 支持三种。深度终端主题在十六个 ANSI 色槽中复用这些支持容量;不支持的名称刻意设为别名,而非伪装成新增颜色。

强调色可能在不同状态间呈现不同色相,但必须在两种状态下均保持可区分。每个终端色组均通过全部三种前景角色验证,确保强调色不会与普通文字、辅助文字或柔和文字碰撞。每组前景三元组必须保持为有序的暖中性色阶,而非三种无关颜色。

色彩仍不足以确保关键辨识度。图表应结合直接标签、位置、虚线样式、标记形状或纹理:仅用色彩的序列与冗余编码的对比

5. 在变换视图中构建连续映射

每个渐进映射始于人工选择的大地色路径。生成器在 Oklab 空间平滑该路径,在目标变换后测量累计距离,并按等变换距离间隔重采样。

2000K 和 1200K 映射使用克制的内部蓝色通道调整来优化命令间距,同时不放弃变换等距性、端点或明度单调性。最终得到 256 级采样映射,具有严格单调的变换明度与近乎等距的模拟变换 Oklab 步长。

发布检查还要求日间明度单调性和日间步长变化有界。CSS 提供 11 个便捷的 8位预览节点;JSON 和 Python 包含完整浮点采样点。


测量属性与发布门控

测量属性

下表中的 ΔEOK 是乘以 100 的欧几里得 Oklab 距离。这是生成器与测试一致使用的工程指标,并非标准化 CIE ΔE 公式。

方案分类色数日间最小 ΔEOK变换后最小 ΔEOK原始色度 平均/最大变换后明度范围最小 ANSI 对比度
3400K 暗色615.0011.450.0971 / 0.10450.22065.29:1
3400K 亮色616.7312.410.0988 / 0.10370.30684.65:1
2000K 暗色417.0012.910.0956 / 0.10820.15384.52:1
1200K 暗色320.7210.250.1047 / 0.11070.12684.55:1

日间色相跨度与变换后分类/背景对比度是独立的发布门控。此对比度用于图形分类标记,而非小字号文字。

方案日间最小色相差目标变换后分类色/bg_0 对比度目标
3400K 暗色20.23°≥ 20°3.01:1≥ 3:1
3400K 亮色31.75°≥ 30°3.03:1≥ 3:1
2000K 暗色27.76°≥ 20°3.05:1≥ 3:1
1200K 暗色65.03°≥ 45°3.12:1≥ 3:1

终端色组分离度包含完整前景色阶及强调色间对比:

方案日间强调色最小差日间→fg_0日间→fg_1日间→fg_2变换后强调色最小差变换后→fg_0变换后→fg_1变换后→fg_2
3400K 暗色10.768.678.1311.727.316.585.1610.18
3400K 亮色15.649.259.479.2211.076.476.707.13
2000K 暗色12.6213.7310.868.257.757.645.034.75
1200K 暗色12.359.698.9614.684.134.494.1311.29

前景协调性通过独立门控验证:

方案fg_0 / fg_1 / fg_2日间相邻步差变换后相邻步差日间/变换后间隔比日间/变换后色相跨度最大日间色度
3400K 暗色#DDD0B2 / #BDAE93 / #90847210.41 / 13.798.70 / 11.880.7568 / 0.73729.32° / 2.63°0.0426
3400K 亮色#342F2C / #4D4540 / #665C548.75 / 8.527.55 / 7.320.9734 / 0.97070.00° / 1.12°0.0181
2000K 暗色#EED5AE / #D3BB99 / #AA9D8B8.04 / 10.446.20 / 9.040.7886 / 0.70082.74° / 2.51°0.0584
1200K 暗色#FFE5BD / #CBAF89 / #A18C7316.43 / 11.7911.07 / 9.160.7099 / 0.81776.73° / 0.71°0.0607

暗色界面测量使用 WCAG 的 sRGB 相对亮度计算(基于精确序列化十六进制值)。对比度范围涵盖变换后 fg_0 与全部六种背景角色的组合。

相似文章

Rechroma

Product Hunt

Rechroma 是一款帮助设计师构建更优配色方案并交付完整色彩系统的工具。

使用Web标准实现深色模式

Lobsters Hottest

一篇关于使用Web标准(如color-scheme元标签和prefers-color-scheme媒体查询)在网站上实现深色模式的指南,并包含一个JavaScript切换开关,可尊重用户偏好并将其存储在localStorage中。