feColorMatrix y la manipulación del color
La matriz de 4 por 5 explicada término a término, los modos abreviados, feComponentTransfer, y tres efectos completos: duotono, umbral de alfa y el filtro gooey.
La matriz
feColorMatrix type="matrix" toma 20 valores que forman una matriz de 4 filas por 5 columnas. Cada fila calcula un canal de salida:
R' = a00*R + a01*G + a02*B + a03*A + a04G' = a10*R + a11*G + a12*B + a13*A + a14B' = a20*R + a21*G + a22*B + a23*A + a24A' = a30*R + a31*G + a32*B + a33*A + a34Los valores de entrada y salida están en el rango 0 a 1. La quinta columna es un término independiente, un desplazamiento constante.
La identidad, que no cambia nada:
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" />Con esa plantilla en la cabeza, las manipulaciones se leen solas.
Escala de grises por luminancia. Cada canal de salida es la misma combinación ponderada de los tres de entrada:
<feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0" />Esos coeficientes son los de la luminancia relativa de la recomendación BT.709, los mismos que usan las máscaras en modo luminancia y los mismos del cálculo de contraste de las pautas de accesibilidad. No son arbitrarios: reflejan la sensibilidad del ojo, que es máxima al verde y mínima al azul.
Invertir. Multiplicar por menos uno y desplazar uno:
<feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />Extraer el canal rojo como escala de grises. Copiar R a los tres canales:
<feColorMatrix type="matrix" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0" />Es lo que se usa para convertir un mapa de altura de un canal en algo visible.
Los tres modos abreviados
type="saturate" toma un valor de 0 a 1 (y admite mayores que 1 para sobresaturar). Es una interpolación entre la matriz de luminancia y la identidad.
<feColorMatrix type="saturate" values="0" /> <!-- gris total --><feColorMatrix type="saturate" values="1.6" /> <!-- sobresaturado -->type="hueRotate" toma grados y rota el matiz. Por debajo es una matriz construida con senos y cosenos del ángulo, y es una aproximación lineal: no es una rotación en un espacio de matiz perceptual, así que a ángulos grandes la luminosidad se desvía.
type="luminanceToAlpha" descarta el color y pone la luminancia en el canal alfa. Es la primitiva que convierte una imagen en una máscara.
<!-- Una imagen convertida en mascara de transparencia --><feColorMatrix type="luminanceToAlpha" />feComponentTransfer
Donde feColorMatrix hace combinaciones lineales entre canales, feComponentTransfer aplica una función arbitraria a cada canal por separado. Cuatro hijos posibles: feFuncR, feFuncG, feFuncB, feFuncA, cada uno con un type:
type |
Qué hace | Atributos |
|---|---|---|
identity |
Nada | ninguno |
linear |
slope * c + intercept |
slope, intercept |
gamma |
amplitude * c^exponent + offset |
amplitude, exponent, offset |
table |
Interpolación lineal en una tabla | tableValues |
discrete |
Escalones a partir de una tabla | tableValues |
table es el más útil: reparte los valores de la tabla uniformemente entre 0 y 1 e interpola. Con dos valores define un mapeo lineal entre dos extremos; con cinco, una curva.
discrete produce escalones sin interpolar, que es exactamente la posterización.
Efecto: duotono
Un duotono es una imagen en escala de grises remapeada a dos colores. Dos primitivas:
<filter id="duotono" color-interpolation-filters="sRGB"> <!-- 1. A luminancia --> <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0" /> <!-- 2. Remapear cada canal entre el color oscuro y el claro --> <feComponentTransfer> <feFuncR type="table" tableValues="0.11 0.65" /> <feFuncG type="table" tableValues="0.09 0.86" /> <feFuncB type="table" tableValues="0.18 0.98" /> </feComponentTransfer></filter>Los dos valores de cada tabla son los componentes del color de sombra y del color de luz, en el rango 0 a 1. En el ejemplo, sombras en un azul muy oscuro y luces en un cian claro. Cambiar la paleta es cambiar seis números.
Con tres valores por tabla se controla también el tono medio, lo que permite duotonos con un tercer color en la zona intermedia.
El color-interpolation-filters="sRGB" es obligatorio aquí: en linearRGB los colores que salen no son los que has escrito, y ajustar la paleta se convierte en adivinanza.
Efecto: el filtro gooey
Este es el que hay que entender de verdad. La idea: si desenfocas varias formas, sus bordes se solapan en una zona de alfa intermedio; si después amplificas brutalmente el alfa, esa zona intermedia salta a opaco y las formas parecen fundirse como gotas de mercurio.
<filter id="gooey" color-interpolation-filters="sRGB" x="-30%" y="-30%" width="160%" height="160%"> <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="difuso" /> <feColorMatrix in="difuso" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" /> <feComposite in="SourceGraphic" in2="goo" operator="atop" /></filter>La fila del alfa es 0 0 0 19 -9, es decir:
A' = 19 * A - 9Una función lineal con pendiente muy alta. Con A = 0.47 da A' = -0.07, que se recorta a 0. Con A = 0.53 da A' = 1.07, que se recorta a 1. Es decir, todo lo que esté por debajo de 0,474 se vuelve transparente y todo lo que esté por encima de 0,526 se vuelve opaco: un umbral duro con una transición de 0,05 de ancho, que es lo que da el borde suave pero definido.
Las dos constantes se ajustan así: la pendiente controla la dureza del borde (más alta, más duro) y el término independiente controla dónde está el umbral. El punto medio es -intercept / slope: con 19 y -9 sale 0,474. Si quieres que las formas se fundan antes, baja el umbral a 0,3 usando values="... 19 -5.7".
El feComposite operator="atop" final vuelve a poner el gráfico original encima del resultado gooey, recortado a él. Sin ese paso las formas quedarían de un color plano y sin sus detalles interiores.