Mira un color, una paleta, un degradado o una imagen en todos los espacios de color. De las pantallas a la impresión, de los selectores de color a la investigación, de 1860 a 2026.
La biblioteca completa: 221 espacios, 71 kB con gzip. De cualquier espacio a cualquier otro, en ambos sentidos.
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]]
O un solo espacio: el paquete no lleva nada más.
import oklch from 'color-space/oklch.js' oklch.rgb(0.65, 0.1, 180) // → [56.14, 162.97, 145.41]
Con tipos: las declaraciones de TypeScript vienen en el paquete, para toda la biblioteca y para cada espacio por separado.
Para imágenes completas y búferes largos: 54 espacios, 53 kB con gzip, de 1.4 a 4.8× más rápido que el lote de JS en las 26 conversiones medidas.
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
El módulo no importa nada, así que funciona dondequiera que funcione WebAssembly: navegadores, Node, Deno, Bun —y Python, Rust o Go con wasmtime o wasmer—.
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)
Espacios 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
Los 221 espacios como funciones de sombreador. Una conversión a rgb devuelve 0–255, como en JavaScript: divide entre 255 para un color de fragmento.
WebGL y 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 y Unreal: HLSL. Metal: MSL. Ambos se generan a partir del WGSL con naga, una dependencia opcional.
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)Convierte el material grabado en tu editor: elige dos espacios y descarga un .cube para Resolve, Premiere, Final Cut, OBS o ffmpeg. Las conversiones de logs de cámara coinciden con las transformaciones ACES oficiales de la Academia.
Lleva un espacio a Photoshop, a la gestión de color de tu sistema, a lcms o a ImageMagick: descárgalo como perfil .icc. Los espacios RGB sirven como espacios de trabajo de Photoshop; los demás convierten mediante una tabla de consulta.
Para agentes de IA: llaman a conversiones verificadas en lugar de adivinarlas.
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"] } } }Los rellenos y trazos de la selección en cualquiera de los 221 espacios: un plano y una barra por canal, recortados a la gama del archivo; copia el color como CSS.
Todos los colores del archivo —CSS, Swift, Flutter, Compose, Unity, tokens de diseño— en cualquiera de los 221 espacios, con un plano y una barra por canal; al editar, cada color se reescribe en su propia notación.
Un sistema de coordenadas para el color: ejes, rangos y una regla que vincula los números con luz medible. La visión humana es tricromática, con tres tipos de conos (S, M, L), por lo que tres coordenadas son el mínimo para describir cualquier color que el ojo pueda ver. El mismo naranja es rgb(255 128 0), oklch(0.732 0.186 53) y XYZ [49, 36.7, 4.5]. Una paleta es una selección de colores; un espacio es una forma de registrar cualquier color.
Un modelo de color define las componentes con las que se describe un color: tres primarios en RGB, matiz, saturación y claridad en HSL, y cuatro tintas en CMYK. Un espacio de color especifica además los primarios, el punto blanco y la curva de codificación, de modo que cada conjunto de valores corresponda a un color medible. Por eso rgb(255 0 0) describe rojos distintos en sRGB, Display P3 y Adobe RGB: un modelo, tres espacios.
En el uso habitual, ambos se llaman espacios, también en color-mix(in hsl, …) de CSS y en este catálogo. Un modelo puede tomar como referencia un espacio ya definido: aquí HSL y HSV se basan en sRGB, como en CSS.
Depende de la tarea:
Para ver todos los espacios ordenados por tarea, agrupa el catálogo por uso.
OKLCH. Mantiene los mismos tres parámetros —matiz, croma, claridad—, pero su claridad es fiable: en HSL, el amarillo a L=50 emite unas 13 veces más luz que el azul a L=50, así que la misma L no significa el mismo brillo. En OKLCH, sí. CSS admite oklch() de forma nativa.
Escríbelo o pégalo en el campo de color de arriba, por ejemplo #ff8000. Todos los espacios de la página muestran ese color a la vez; en OKLCH sus valores son 0.732, 0.186, 53, que en CSS se escriben oklch(0.732 0.186 53). La pestaña css de cada dosier da la forma lista para copiar, y en código es space.rgb.oklch(255, 128, 0).
Porque se calculan en sRGB codificado con gamma, donde promediar los números de dos colores produce una luz más oscura y apagada que la que daría mezclar realmente su luz. Interpolar en OKLab lo evita; en CSS se escribe linear-gradient(in oklab, red, blue). La fila interpolar de cada dosier traza la misma mezcla en dos espacios, uno junto al otro, para ver la diferencia antes de elegir.
Abre el espacio log de tu cámara, como S-Log3, LogC4 o Apple Log. En su bloque LUT, elige Rec. 709 y tu editor: DaVinci Resolve, Premiere Pro, Final Cut Pro, OBS, ffmpeg y otros. Tu navegador genera el archivo .cube. Es una conversión técnica sin mapeo de tonos: las altas luces por encima del blanco difuso se recortan, y el look lo pones tú.
Un color que un espacio puede describir pero que otro —o la pantalla— no puede mostrar. Un verde intenso de Display P3 no existe en sRGB: al convertirlo, los números quedan fuera del rango válido. El atlas lo mantiene a la vista: un ⚠ junto al color actual indica que queda fuera del Límite elegido; al mantener Alt sobre un plano o una franja, se indica qué gama más amplia necesita el color de ese punto (P3, Rec. 2020), y los tramos fuera de rango se ven atenuados sobre un damero.
Una pantalla emite luz; el papel refleja lo que sus tintas no absorben. La tinta sobre papel alcanza menos colores vivos —los azules, verdes y rojos RGB saturados quedan fuera de su gama—, así que se imprimen más apagados. La preimpresión convierte mediante un perfil ICC específico de la máquina de impresión y el papel, como FOGRA39 para papel estucado en Europa o GRACoL en EE. UU. El CMYK de este catálogo es la fórmula simple que CSS usa para device-cmyk() sin perfil: válida para los valores, no una prueba de impresión.
Para la web y para compartir, sRGB: navegadores y teléfonos lo dan por hecho cuando un archivo no lleva perfil. Display P3 reproduce más colores intensos de la escena en las pantallas de Apple y de muchos Android, siempre que el perfil siga incrustado. Envía Adobe RGB cuando un laboratorio de impresión lo pida. Reserva ProPhoto RGB para editar a 16 bits: su gama es tan amplia que los archivos de 8 bits muestran bandas.
Las conversiones son fórmulas cerradas, no aproximaciones por tabla, y una conversión de ida y vuelta devuelve los valores originales con diferencias del orden de la precisión de coma flotante. Las pocas excepciones están documentadas donde ocurren: OSA-UCS no tiene inversa cerrada, y los sistemas de atlas como Munsell interpolan entre los valores publicados. La salida en rgb nunca se limita: un color fuera de sRGB da valores por debajo de 0 o por encima de 255, así que conviene limitarlo solo al mostrarlo.
Además están verificadas: cada espacio enlaza el artículo o la especificación que implementa, los valores se contrastan con colorjs.io en todos los espacios que ambos cubren, y los logs de cámara, con las transformaciones ACES oficiales de la Academia. formula-verification.md registra qué se contrastó con qué, incluidos algunos casos en que los propios artículos publicados tenían errores.
Si los números difieren de los de otra biblioteca, compara los rangos: esta conserva los rangos convencionales de cada espacio —RGB 0–255, claridad Lab 0–100, matiz 0–360—, mientras que muchas lo normalizan todo a 0–1. Cada tarjeta muestra sus rangos; en código son space.oklch.range.
De forma nativa, rgb(), hsl(), hwb(), lab(), lch(), oklab() y oklch(), más color() para Display P3, Adobe RGB, ProPhoto, sRGB lineal y XYZ (D65 y D50). El rec2020 de CSS es una gamma 2.4 pura, no la curva BT.2020 del Rec. 2020 de este catálogo: los mismos números corresponderían a otro color. La pestaña css de cada dosier muestra el color actual listo para copiar; los espacios que CSS no tiene se ofrecen en su lugar como perfiles ICC o LUT.
Abre Vista y elige una opción de Visión: ceguera al rojo (protanopia), ceguera al verde (deuteranopia) o ceguera al azul (tritanopia). El catálogo se redibuja como lo ve ese ojo, para que compruebes que los colores de una paleta siguen distinguiéndose. Alrededor de 1 de cada 12 hombres tiene una deficiencia en la visión del color, según datos del NEI.
Son productos con licencia: sus colores se definen mediante datos que venden sus propietarios, no mediante fórmulas publicadas; así que no hay un modelo matemático público que implementar, y redistribuir sus tablas no sería legal. Sí están aquí sistemas afines de definición pública: Munsell (su renotación de 1943 es de acceso público) y RAL Design (definido directamente en CIELAB). Tiene cabida aquí cualquier sistema cuyas fórmulas se hayan publicado alguna vez; sugiere uno que falte.
| Herramienta | Espacios | Logs de cámara | Luma–croma | sRGB | Utilidades | Tamaño | Velocidad | Destinos |
|---|---|---|---|---|---|---|---|---|
| 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 |
Según el código fuente, el paquete o la página de cada proyecto, a 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
Colorimetría
Yy: Y escalada como L*; Cx y Cz: las diferencias X − Y, Y − Z, escaladas como a* y b* sin la raíz cúbica
1993, Flohr, Kolpatzik, Balasubramanian, Carrara, Bouman & Allebach
Filtrar imágenes en color en luz lineal a lo largo de ejes alineados con CIELAB: diseño de tramas de semitonos y métricas de diferencia basadas en desenfoque, como FLIP de NVIDIA.
Diseño de tramas de semitonos y métricas espaciales de diferencia entre imágenes (FLIP): se filtra aquí y luego se pasa a CIELAB.
Lineal en XYZ y, por tanto, no perceptualmente uniforme: las diferencias deben medirse solo después de convertir a CIELAB.
// one space, tree-shaken (0.4-1.5 kB) — its own edge: import ycxcz from 'color-space/ycxcz.js' ycxcz.xyz(9, 0, 0) // → [20.5166, 21.5861, 23.5085] // any-to-any, both ways — the wired hub: import space from 'color-space' space.ycxcz.rgb(9, 0, 0) // → [128, 128, 128] space.rgb.ycxcz(128, 128, 128) // → [9, 0, 0] // route: ycxcz → xyz → rgb