整个库:221 个色彩空间,gzip 后 71 kB——任意空间之间,双向转换。
npm install color-space
import space from 'color-space' space.rgb.oklch(255, 128, 0) // → [0.732, 0.186, 53] space.oklch.rgb(0.65, 0.1, 180) // → [56.14, 162.97, 145.41] space.oklch.range // [[0,1], [0,0.4], [0,360]]
或者只要一个色彩空间——打包结果里不含其他任何东西。
import oklch from 'color-space/oklch.js' oklch.rgb(0.65, 0.1, 180) // → [56.14, 162.97, 145.41]
带类型:TypeScript 声明随包提供,覆盖整个库,也覆盖单独导入的每个色彩空间。
适用于整幅图像和长缓冲区:54 个空间,gzip 后 53 kB,在实测的 26 个转换上比 JS 批处理快 1.4–4.8 倍。
import space, { alloc } from 'color-space/wasm'
space.oklch.rgb(0.72, 0.16, 41) // → [246, 125, 79]
const buf = alloc(n) // n×3 Float64Array
space.rgb.oklch(buf) // in place
该模块不导入任何东西,因此凡是能运行 WebAssembly 的地方都能运行:浏览器、Node、Deno、Bun,以及通过 wasmtime 或 wasmer 从 Python、Rust、Go 调用。
import struct
from wasmtime import Store, Module, Instance # pip install wasmtime
store = Store() # color-space.wasm: the npm package's dist/
cs = Instance(store, Module.from_file(store.engine, 'color-space.wasm'), []).exports(store)
at = cs['alloc'](store, 1.0) & 0xFFFFFFFF # the buffer: n×3 float64 in the kernel's memory
cs['memory'].write(store, struct.pack('3d', 255, 128, 0), at)
cs['rgb_lrgb_n'](store, 1.0) # in place, edge by edge: rgb → linear rgb → oklab
cs['lrgb_oklab_n'](store, 1.0)
struct.unpack('3d', cs['memory'].read(store, at, at + 24)) # (0.732, 0.112, 0.148)
色彩空间 rgb, lrgb, xyz, xyz-d50, xyy, lms, p3, p3-linear, rec2020, rec2020-linear, a98rgb, a98rgb-linear, prophoto, prophoto-linear, rec709, hsl, hsv, hwb, oklab, oklrab, oklch, oklrch, lab, lchab, lab-d65, lch-d65, din99o-lab, din99o-lch, luv, lchuv, hsluv, hpluv, cam16, hct, ycbcr-bt709, ycbcr-bt2020, jzazbz, jzczhz, ictcp, ictcp-hlg, ipt, din99d, acescg, acescct, acescc, awg3, logc3, logc4, slog3, vlog, log3g10, clog2, ryb, munsell
全部 221 个空间都提供着色器函数。转换到 rgb 返回 0–255,与 JavaScript 一致:片元颜色需除以 255。
WebGL 和 OpenGL:GLSL。
import { glsl } from 'color-space/gl'
import oklch from 'color-space/gl/oklch'
const frag = `#version 300 es
precision highp float;
${glsl(oklch, 'rgb')}
out vec4 color;
void main() { color = vec4(oklch_rgb(vec3(0.7, 0.15, gl_FragCoord.x)) / 255.0, 1.0); }`
WebGPU:WGSL。
import { wgsl } from 'color-space/gl'
const code = wgsl(oklch, 'rgb') + `
@fragment fn main(@builtin(position) p: vec4f) -> @location(0) vec4f {
return vec4f(oklch_rgb(vec3f(0.7, 0.15, p.x)) / 255.0, 1.0);
}`
DirectX、Unity 和 Unreal:HLSL。Metal:MSL。两者都由 naga 从 WGSL 生成,naga 是可选依赖。
import { hlsl } from 'color-space/gl/hlsl' // npm i naga-wasm
import { msl } from 'color-space/gl/msl'
await hlsl('oklch', 'rgb') // float3 oklch_rgb(float3)
await msl('oklch', 'rgb') // metal::float3 oklch_rgb(metal::float3)在剪辑软件里转换素材:选两个色彩空间,下载一个 .cube,可用于 Resolve、Premiere、Final Cut、OBS 或 ffmpeg。摄影机 Log 的转换与美国电影艺术与科学学院(Academy)官方的 ACES 变换一致。
要在 Photoshop、系统色彩管理、lcms 或 ImageMagick 中使用某个色彩空间,下载它的 .icc 配置文件即可。RGB 色彩空间可作为 Photoshop 的工作空间,其余的通过查找表转换。
面向 AI 智能体:调用经过验证的转换,而不是靠猜。
npx -y color-space mcp
// Claude Code
claude mcp add color-space -- npx -y color-space mcp
// VS Code
code --add-mcp '{"name":"color-space","command":"npx","args":["-y","color-space","mcp"]}'
// Claude Desktop · Cursor · .mcp.json
{ "mcpServers": { "color-space": { "command": "npx", "args": ["-y", "color-space", "mcp"] } } }选区的填充和描边,可用 221 个空间中的任意一个——每个通道一个平面和一条色条,按文件的色域裁切;可将颜色复制为 CSS。
文件中的所有颜色——CSS、Swift、Flutter、Compose、Unity、设计令牌——可用 221 个空间中的任意一个呈现,每个通道一个平面和一条色条;编辑后按颜色原有的写法写回。
颜色的坐标系:坐标轴、取值范围,以及把数值与可测量的光对应起来的规则。人的色觉是三色视觉,有三种视锥细胞(S、M、L),因此要描述人眼能看到的任意颜色,至少需要三个坐标。同一个橙色可以写作 rgb(255 128 0)、oklch(0.732 0.186 53) 或 XYZ [49, 36.7, 4.5]。调色板是挑选出的几种颜色;色彩空间则是记录任何颜色的通用方式。
色彩模型规定用哪些分量描述颜色:RGB 使用三原色,HSL 使用色相、饱和度和明度,CMYK 使用四种油墨。色彩空间进一步确定原色、白点和编码曲线,使每组数值对应一个可测量的颜色。因此,rgb(255 0 0) 在 sRGB、Display P3 和 Adobe RGB 中表示不同的红色:模型相同,空间不同。
日常使用中,两者通常都称为色彩空间,CSS 的 color-mix(in hsl, …) 和本目录也沿用这一叫法。没有独立参照基准的模型,可以基于已有的色彩空间定义:这里的 HSL 和 HSV 均以 sRGB 为基础,与 CSS 一致。
取决于任务:
要按任务查看所有空间,请按 用途 给目录分组。
OKLCH。它同样用三个参数调色——色相、彩度、明度——但明度名副其实:在 HSL 中,L=50 的黄色发出的光约是 L=50 的蓝色的 13 倍,L 相同并不意味着明亮度相同。OKLCH 则不然:L 相同,明亮度也相同。CSS 原生支持 oklch()。
在顶部的颜色输入框中输入或粘贴它,比如 #ff8000。页面上的每个空间都会立即显示这个颜色;在 OKLCH 中它是 0.732、0.186、53,CSS 写作 oklch(0.732 0.186 53)。每个空间详情中的 css 标签页给出可复制的写法,在代码中则是 space.rgb.oklch(255, 128, 0)。
因为它们是在伽马编码的 sRGB 中计算的:在那里对两种颜色的数值取平均,得到的光比真实混合两束光更暗、更浊。在 OKLab 中插值就能避免;在 CSS 中写作 linear-gradient(in oklab, red, blue)。每个空间详情中的 插值 一行都会把同一段混合在两个空间中并排画出,让你在选择前看清差别。
指一个空间能描述、而另一个空间(或你的屏幕)无法显示的颜色。鲜艳的 Display P3 绿色在 sRGB 中不存在:一经转换,数值就会超出有效范围。图谱让这一点始终可见:当前颜色旁的 ⚠ 表示它超出了你在“色域”中选定的范围;在平面或色带上按住 Alt,会显示该处颜色需要哪个更宽的色域(P3、Rec. 2020);超出范围的区段则以半透明叠在棋盘格上。
屏幕发光;纸张反射油墨没有吸收的光。纸上油墨能达到的鲜艳颜色更少——饱和的 RGB 蓝、绿、红都落在其外——所以印出来更暗淡。印前处理会经由为该印刷机和纸张制作的 ICC 配置文件转换,例如欧洲铜版纸用 FOGRA39,美国用 GRACoL。本目录的 CMYK 是 CSS 在无配置文件时用于 device-cmyk() 的简单公式——数值正确,但不能当作印刷打样。
用于网页和分享,选 sRGB:文件不带配置文件时,浏览器和手机都默认按它处理。只要配置文件保持嵌入,Display P3 就能在 Apple 和许多 Android 屏幕上保留更多鲜艳场景的色彩。冲印店要求时,交付 Adobe RGB。ProPhoto RGB 留给 16 位编辑:它的色域非常宽,8 位文件会出现色带。
转换使用闭式公式,而非查找表近似,往返转换的误差在浮点噪声以内。少数例外都在相应位置注明:OSA-UCS 没有闭式逆变换,Munsell 等图册系统在已发布的级差之间插值。rgb 输出从不裁切:sRGB 之外的颜色会以低于 0 或高于 255 的值返回,因此只在显示时裁切。
这些转换也经过核验:每个空间都链接到它所实现的论文或规范;凡与 colorjs.io 重叠之处,数值都与之对照测试;摄影机 Log 则与美国电影艺术与科学学院(Academy)官方的 ACES 变换对照。formula-verification.md 记录了每项核对的依据——包括已发表论文本身出错的几处。
如果数值与其他库不同,请先比较取值范围:本库保留每个空间的惯用范围——RGB 0–255、Lab 明度 0–100、色相 0–360——而许多库一律压缩到 0–1。每张卡片都标出了范围;在代码中是 space.oklch.range。
原生支持 rgb()、hsl()、hwb()、lab()、lch()、oklab()、oklch(),另有 color() 用于 Display P3、Adobe RGB、ProPhoto、线性 sRGB 和 XYZ(D65 与 D50)。CSS 的 rec2020 是纯 2.4 伽马,而不是本目录中 Rec. 2020 所用的 BT.2020 曲线——同样的数值会指向不同的颜色。每个空间详情中的 css 标签页都会以可复制的形式写出当前颜色;CSS 不支持的空间则改以 ICC 配置文件或 LUT 提供。
打开 视图,在 色觉 中选择红色盲、绿色盲或蓝色盲。目录会模拟这种色觉重新绘制,方便你检查调色板中的颜色是否仍然可以区分。据 NEI 统计,约每 12 名男性中就有 1 人有色觉缺陷。
它们是授权产品:颜色由所有者出售的数据定义,而不是由公开公式定义——因此没有公开的算法可供实现,再分发其色表也不合法。公式公开的同类体系则收录在此:Munsell(其 1943 年的重新标定数据已公开)和 RAL Design(直接在 CIELAB 中定义)。凡是公式公开发表过的体系都可以收录;推荐尚未收录的体系。
| 工具 | 色彩空间 | 摄影机 Log | 亮度–色度 | sRGB | 工具集 | 大小 | 速度 | 目标平台 |
|---|---|---|---|---|---|---|---|---|
| 205 | 31 | 16 | 0–255 | parse mix ΔE contrast CVD | 62 kB | JS, WASM, GL, LUT, ICC, OCIO, MCP, Figma, VS Code, CLI, web | ||
| 30 | – | 1 | 0–1 | parse mix gamut ΔE contrast CVD | 23 kB | JS | ||
| 51 | – | – | 0–1 | parse mix gamut ΔE contrast | 34 kB | JS, web | ||
| chroma-js | 11 | – | – | 0–255 | parse mix ΔE contrast palettes | 17 kB | JS | |
| @texel/color | 16 | – | – | 0–1 | parse gamut ΔE | 9 kB | JS | |
| 128 | 24 | 6 | 0–1 | ΔE CVD | – | – | Python, LUT | |
| 77 | – | – | 0–1 | parse mix gamut ΔE contrast CVD palettes | – | – | Python | |
| 9 | – | – | 0–1 | mix contrast CVD palettes | – | – | R, web | |
| 57 | 11 | – | 0–1 | gamut | – | – | C++, Python, GL, LUT, ICC | |
| 22 | – | – | 0–1, 0–255 | ΔE | – | – | web | |
| 9 | – | – | 0–255 | parse gamut | – | – | web |
数据来自各项目自己的源码、软件包或页面,截至 2026-10-18。
@software{Ivanov_color-space_2026,
author = {Ivanov, Dmitry},
license = {CC0-1.0},
month = oct,
title = {{color-space}},
url = {https://github.com/colorjs/color-space},
version = {3.4.0},
year = {2026}
}Ivanov, D. (2026). color-space (Version 3.4.0) [Computer software]. https://github.com/colorjs/color-space
感知空间
J 为明度,M 为视彩度,h 为色相——色貌模型的字母;2 指 ACES 2.0
ACES 2.0 JMh → ACES2065-1 → ACEScg → CIE XYZ → sRGB
为显示器对 ACES 图像做色调映射和色域映射,同时保持每种颜色的色相。
ACES 2.0 输出变换的工作空间,色调曲线、彩度压缩和色域压缩都在其中进行;OpenColorIO 以固定函数 ACES_RGB_TO_JMh_20 的形式提供它。
并非通用的色貌模型:观察条件是固定的,视彩度也去掉了 Hellwig 模型中的偏心率因子。
// one space, tree-shaken (0.4-1.5 kB) — its own edge: import aces2Jmh from 'color-space/aces2-jmh.js' aces2Jmh['aces2065-1'](48.9, 0, 92) // → [0.2159, 0.2159, 0.2159] // any-to-any, both ways — the wired hub: import space from 'color-space' space['aces2-jmh'].rgb(48.9, 0, 92) // → [128, 128, 128] space.rgb['aces2-jmh'](128, 128, 128) // → [48.9, 0, 92] // route: aces2-jmh → aces2065-1 → acescg → xyz → rgb