Saltar al contenido

Los modos de fusión

Usar los dieciséis modos de mezcla separables y no separables que el canvas comparte con CSS y con los programas de diseño, y saber qué hace cada familia.

Las cuatro familias

Los que oscurecen: multiply, darken, color-burn. El resultado nunca es más claro que ninguna de las dos capas. El blanco es neutro: mezclar con blanco no cambia nada.

Los que aclaran: screen, lighten, color-dodge. El resultado nunca es más oscuro. El negro es neutro.

Los de contraste: overlay, hard-light, soft-light. Combinan los dos anteriores según el valor del píxel base: oscurecen las zonas oscuras y aclaran las claras. El gris medio es neutro.

Los de comparación y componentes: difference, exclusion, hue, saturation, color, luminosity.

Los doce primeros son separables: operan canal a canal, de forma independiente. Los cuatro últimos son no separables: descomponen el color en tono, saturación y luminosidad, y toman unos componentes de una capa y otros de la otra.

Los que se usan

multiply multiplica los valores normalizados. El resultado es como superponer dos transparencias. Es el modo de las sombras y del papel: cualquier zona blanca desaparece y las oscuras se refuerzan.

JS
// Sombra proyectada realista sobre un fondo con texturactx.globalCompositeOperation = 'multiply';ctx.fillStyle = 'rgba(0,0,0,0.35)';ctx.beginPath();ctx.ellipse(cx, cy + 60, 70, 18, 0, 0, Math.PI * 2);ctx.fill();ctx.globalCompositeOperation = 'source-over';

Frente a dibujar la sombra con source-over y alfa, multiply conserva la textura del fondo debajo, que es lo que hace que una sombra se vea integrada y no pegada.

screen es el inverso: multiplica los complementarios. Es el modo de la luz añadida y de los reflejos, y a diferencia de lighter no satura tan rápido, con lo que da un resultado más suave.

overlay y soft-light son los modos de gradación de color. Aplicar una capa de color con soft-light sobre una fotografía es la forma estándar de virar una imagen sin destruir su rango tonal.

JS
// Virado calido sobre una fotoctx.drawImage(foto, 0, 0);ctx.globalCompositeOperation = 'soft-light';const g = ctx.createLinearGradient(0, 0, 0, alto);g.addColorStop(0, '#f9e2af');g.addColorStop(1, '#89b4fa');ctx.fillStyle = g;ctx.fillRect(0, 0, ancho, alto);ctx.globalCompositeOperation = 'source-over';

difference da el valor absoluto de la diferencia entre ambos. Su uso más interesante no es estético sino de diagnóstico: comparar dos imágenes. Las zonas idénticas quedan negras y las distintas se iluminan.

JS
// Diff visual entre dos renderizadosctx.drawImage(referencia, 0, 0);ctx.globalCompositeOperation = 'difference';ctx.drawImage(actual, 0, 0);ctx.globalCompositeOperation = 'source-over';// Todo lo que no sea negro es una diferencia

Es la técnica que está detrás de las herramientas de regresión visual, y en canvas cuesta tres líneas.

luminosity y color son la pareja no separable más útil. luminosity toma la luminosidad del origen y el tono y la saturación del destino; color hace lo contrario. Juntos permiten recolorear una imagen conservando su modelado de luz:

JS
// Recolorear conservando el detalle de luzctx.drawImage(objeto, 0, 0);ctx.globalCompositeOperation = 'color';ctx.fillStyle = '#cba6f7';ctx.fillRect(0, 0, ancho, alto);ctx.globalCompositeOperation = 'source-over';

Tabla de referencia

Modo Familia Neutro Uso típico
multiply Oscurece Blanco Sombras, tinta, papel
darken Oscurece Blanco Quedarse con el más oscuro por canal
color-burn Oscurece Blanco Oscurecer con más contraste
screen Aclara Negro Luces, reflejos, brillos
lighten Aclara Negro Quedarse con el más claro por canal
color-dodge Aclara Negro Destellos intensos
overlay Contraste Gris medio Aumentar contraste general
hard-light Contraste Gris medio Como overlay con las capas invertidas
soft-light Contraste Gris medio Virado suave, gradación de color
difference Comparación Negro Comparar imágenes, inversión
exclusion Comparación Negro Como difference con menos contraste
hue Componentes — Cambiar el tono conservando el resto
saturation Componentes — Ajustar saturación desde una capa
color Componentes — Recolorear conservando la luz
luminosity Componentes — Aplicar el modelado de luz de otra capa

Combinar modos y capas

Los efectos interesantes casi nunca son un modo suelto: son varias capas con modos distintos. Y como cada modo afecta a todo el canvas, la composición por capas es obligatoria.

JS
/** Devuelve un canvas con la foto virada y con un brillo superpuesto. */function componer(foto, ancho, alto) {  const base = document.createElement('canvas');  base.width = ancho; base.height = alto;  const c = base.getContext('2d');  // Capa 1: la foto  c.drawImage(foto, 0, 0, ancho, alto);  // Capa 2: virado con soft-light  c.globalCompositeOperation = 'soft-light';  const virado = c.createLinearGradient(0, 0, ancho, alto);  virado.addColorStop(0, '#f9e2af');  virado.addColorStop(1, '#585b70');  c.fillStyle = virado;  c.fillRect(0, 0, ancho, alto);  // Capa 3: vinetado con multiply  c.globalCompositeOperation = 'multiply';  const vineta = c.createRadialGradient(    ancho / 2, alto / 2, Math.min(ancho, alto) * 0.3,    ancho / 2, alto / 2, Math.max(ancho, alto) * 0.75);  vineta.addColorStop(0, '#ffffff');  vineta.addColorStop(1, '#6c6f85');  c.fillStyle = vineta;  c.fillRect(0, 0, ancho, alto);  // Capa 4: destello con screen  c.globalCompositeOperation = 'screen';  const destello = c.createRadialGradient(    ancho * 0.25, alto * 0.2, 0, ancho * 0.25, alto * 0.2, ancho * 0.5);  destello.addColorStop(0, 'rgba(249,226,175,0.5)');  destello.addColorStop(1, 'rgba(249,226,175,0)');  c.fillStyle = destello;  c.fillRect(0, 0, ancho, alto);  c.globalCompositeOperation = 'source-over';  return base;}

Ese es el aspecto real de un filtro fotográfico: cuatro capas, cuatro modos, cero manipulación de píxeles. Todo lo hace el compositor, que además puede acelerarlo por hardware, y el coste es de cuatro rellenos en lugar de millones de iteraciones en JavaScript.