Introducción

Herramientas frente a máquinas, artesanía frente a industria

En su libro The Technological Society (1954), Jacques Ellul presenta la diferencia entre las épocas anterior y posterior a la revolución industrial de la siguiente manera:

La era preindustrial es el reinado de la herramienta y de la artesanía. La propiedad primordial de las herramientas es ser genéricas, versátiles y adaptables. Corresponde al artesano desarrollar sus habilidades para hacer que las herramientas sigan su intención, de modo que la mano supla las limitaciones del instrumento. Este concepto sigue siendo bien conocido hoy por los músicos: tienes que practicar, aprender, intentar, fallar, reintentar… no hay atajos. Ellul insiste en la idea de parsimonia que acompaña a las herramientas: los recursos son limitados, así que tu conjunto de herramientas queda prácticamente definido por lo que puedes permitirte, transportar, dominar y construir localmente. Las modas cambian despacio y son locales, porque usan recursos locales y se adaptan a necesidades locales, y las herramientas siguen el mismo patrón. Las herramientas son legados que pasan de maestro a aprendiz, de padre a hijo. No se vuelven incompatibles ni obsoletas.

La era industrial es el reinado de la máquina. Proviene de una cultura de estandarización y masificación. La máquina es mucho más productiva porque está especializada en una tarea, pero es inútil para todo lo demás y rara vez puede adaptarse a otro uso. Cuando cambian las necesidades de producción, la máquina se reemplaza por otra porque no sirve para nada más. Esto ya no es un esquema parsimonioso, y se permite porque los recursos son mucho más baratos y la producción en masa permite economías de escala. Entonces, los humanos se convierten en sirvientes de la máquina, y la artesanía se vuelve un lujo.

Las producciones que solían hacerse en casa o en pequeños talleres, en un contexto familiar, se trasladan a grandes fábricas, donde hay espacio suficiente para las máquinas. Por cierto, eso tuvo efectos muy concretos en cómo organizamos nuestra vida cotidiana, incluyendo cuándo y cuántas veces comemos1, así como los patrones de sueño2. Así que no es exagerado decir que la revolución industrial también cambió profundamente la forma en que pensamos, lo que consideramos normal o evidente.

Eso me resonó porque es como yo había estado desarrollando herramientas de edición de color, intuitivamente, desde que empecé: intentando construir herramientas genéricas que se apoyaran en la menor cantidad de supuestos para mantenerse versátiles, dando a la vez un control fino sobre los parámetros de la imagen, y confiando en última instancia en las capacidades de los artesanos en lugar de en herramientas semirotas, sin validar y automágicas que solo funcionan en casos ideales.

Fotografía digital: ¿automatizar o disfrutar el proceso?

Nunca he entendido la pasión de muchos fotógrafos, especialmente los más tecnófilos, por los flujos de trabajo de un solo botón y los procedimientos automatizados. He aprendido y enseñado piano, y estoy acostumbrado al paradigma cállate y practica: entrenar para desarrollar y mantener la agilidad, y luego repetir los mismos pocos compases una y otra vez hasta que el sonido sea correcto. Trabajar la calidad, la textura y la expresividad del sonido, mediante la cantidad de peso que pones en las teclas, la velocidad del ataque, el movimiento de la muñeca y del antebrazo. Usar tu cuerpo para el movimiento fino y entrenarlo más allá de sus capacidades actuales, convirtiendo gestos muy poco naturales en reflejos. Y por último, aprender a oír en tu mente el sonido que buscas, antes incluso de mover las manos. Todas esas cosas que nunca serán reducibles a deslizadores y botones de una interfaz gráfica, a métricas, variables o algoritmos.

La forma en que muchos fotógrafos abordan la edición de fotos suena como si hubieran sido castigados por la fotografía digital porque ahora tienen que usar un software para obtener sus fotos. Así que debería reducirse a un procedimiento sin alma en el que todo debería automatizarse si se puede. Intercambiamos presets y recetas, algunos incluso los venden. Y ahora tenemos la IA para emular un estilo u otro. ¿Dónde está la alegría en industrializar la creación artística? ¿Qué sentido tiene tener un pasatiempo que se siente como la carga de tener que revelar tus fotos? El arte es un proceso, no un procedimiento. ¿Qué mente enferma diseñaría un robot que haga cerámica, grabado o arreglos florales en tu lugar? ¿Y si usáramos el software como una oportunidad para terminar el aspecto de tus imágenes según tu gusto y sensibilidad? ¿Hemos perdido el placer puro de hacer las cosas nosotros mismos, aunque sea mal? ¿A qué edad se pierde ese apetito?

De acuerdo, luchar contra un software de edición de fotos es una experiencia frustrante, pero necesitas entender contra qué estás luchando. ¿Es solo la dificultad intrínseca de tu oficio y tu falta de habilidad, o es el mal diseño de la herramienta? Cuando batallas con un piano de 25 k€ que acaba de pasar por el técnico, sabes que el instrumento no es el problema. Pero con el software, ¿cómo lo sabes? Bueno, no puedes hasta que te comprometas por completo con el paradigma cállate y practica. Los buenos retocadores obtendrán buenos resultados con cualquier software; la diferencia está en cuánto tiempo les llevará. Y, bueno, a veces tienes que encubrir mucho los modelos de color rotos de las aplicaciones de edición.

Las herramientas en la interfaz gráfica de edición de fotos

En términos de diseño de interfaz de usuario, la parsimonia de herramientas genéricas y versátiles es la mejor manera de evitar verse abrumado por decenas de funciones que se ocultan entre sí, se solapan en funcionalidad y no hacen más que contaminar tu campo visual. Es el feng shui del software. Pero entonces, la naturaleza de las herramientas cambia un poco.

Hay dos maneras de pensar en los controles de color del procesamiento de imágenes: desde su uso funcional, y desde la forma en que permiten manipular las propiedades del color. Desde su uso funcional:

FunciónMétodos
Reducir ruidoFiltrado por wavelets, medias no locales, filtro bilateral, filtro guiado, difusión,
Desenfocar (corregir)Deconvolución de Richardson-Lucy, pirámide gaussiana/laplaciana, filtro de paso alto, filtrado por wavelets, contradifusión, máscara de desenfoque
DesenfocarFiltrado por wavelets, difusión, filtro bilateral, filtro guiado
AclararCorrección de exposición, curva de tonos, función de transferencia de potencia (“gamma”), mezclador de canales
Balance de blancosNormalización por canal, transformación de adaptación cromática, mezclador de canales
Desplazamiento de colorMezclador de canales, lift-gamma-gain, slope-offset-power, rotación de tono, LUT
Realce de coloridoSaturación, croma, vibración, LUT
Realce de contrasteCurva de tonos, funciones de transferencia sigmoidales, normalización de rango (“niveles”), LUT
Compresión del rango dinámicoIgual que el contraste, pero en modo “reducir” en lugar de modo “aumentar”

Ten en cuenta que el desplazamiento de color podría volver a dividirse en dos modos: correctivo (que requiere modelos de luz) y creativo (que requiere modelos perceptuales). No llegaremos tan lejos.

Si abordamos la misma lista desde el otro punto de entrada, la forma en que permiten manipular las propiedades del color, obtenemos:

MétodoFunciones
Filtrado por waveletsReducir ruido, Desenfocar (corregir), Desenfocar
DifusiónReducir ruido, Desenfocar (corregir), Desenfocar
Mezclador de canalesAclarar, Desplazamiento de color, Balance de blancos
LUTRealce de contraste, Desplazamiento de color, Realce de colorido
Curva de tonosAclarar, Realce de contraste, Compresión del rango dinámico

No rehíce la lista completa pero captas la idea: tanto si quieres clasificar tu lista de herramientas por método como por función, no acabas con una correspondencia 1:1, salvo en unos pocos casos. Así que ninguna de estas asignaciones te permite factorizar sistemáticamente tus herramientas en elementos unitarios de la interfaz gráfica, como para honrar el principio de parsimonia.

Y además, el procesamiento de imágenes no es solo un conjunto de herramientas en una caja, es en realidad un pipeline de filtros de píxeles que deben insertarse como nodos de un grafo en un orden que coincida con los requisitos de entrada de los filtros. Aquí lo tienes (simplificado):

flowchart TD
    r(Raw input) --> d1[Raw denoise]
    d1 --> demosaic[Demosaic]
    demosaic --> d2[RGB denoise]
    d2 --> wb[White balance]
    wb --> bright1["Brightness enhancement (linear)"]
    bright1 --> blur1[Blur / Deblur]
    blur1 --> color_lin["Color shift (linear)"]
    color_lin --> contrast1["Contrast enhancement / Brightness enhancement (non-linear)"]
    contrast1 --> color_nl["Color shift (non-linear) / Colorfulness enhancement"]
    color_nl --> dr[Dynamic range compression]
    dr --> o(Output)

Y, por último pero no menos importante, el problema que nadie ve: las matemáticas. Por ejemplo, un filtro guiado aplicado a una máscara de opacidad y guiado por la imagen RGB (como en el refinamiento de máscaras de Ansel/Darktable) no tiene las mismas matemáticas que un filtro guiado aplicado a una máscara de luminancia y guiado por sí misma (como en el ecualizador de tonos), o una imagen RGB completa guiada por sí misma (como en el desvelado de neblina). Estos necesitan implementarse varias veces, con distintos tipos de entradas y distintos tipos de optimizaciones. Lo mismo se aplica a los métodos que trabajan sobre imágenes no desmosaicadas: tenemos que tener en cuenta que no disponemos de una señal RGB completa en cada sensel, y las matrices XTrans necesitan matemáticas especiales, distintas de las de Bayer.

Así que, dado que:

  1. las funcionalidades tienen distintos métodos,
  2. los métodos no pueden reducirse a una sola funcionalidad,
  3. todos ellos se insertan como nodos en un pipeline donde el orden importa,
  4. los métodos tienen variaciones de implementación según su señal de entrada, es decir, su posición en el pipeline,
  5. los usuarios quieren divertirse sin tener que aprender nada,
  6. el desorden de la interfaz gráfica no sirve a nadie y cansa a todos,

…tenemos un problema: ¿cómo dividir las funciones y organizarlas como una interfaz gráfica coherente?

En una configuración profesional, donde puedes esperar que los usuarios sepan construir un pipeline por sí mismos y entiendan los pormenores de sus nodos, puedes ir por el camino de DaVinci Resolve y construir un editor nodal. Entonces construyes un nodo por método, y gestionas internamente las variantes de implementación comprobando el tipo de señal de entrada. Esta es la manera más minimalista, porque no hay ninguna duplicación en la interfaz gráfica: solo un banco de nodos, y los nodos pueden colocarse en paralelo en lugar de forzarse secuencialmente. Pero requiere usuarios expertos.

La manera de Lightroom/Capture One es ocultar por completo que siquiera existe un pipeline, y ofrecer una interfaz gráfica plana. Entonces la multiinstanciación de nodos se hace mediante máscaras: añadir nuevas máscaras te permite asignarles un subconjunto de los controles del software para editar selectivamente las regiones enmascaradas. Pero eso también viene acompañado del hecho de que ninguna de estas aplicaciones permite la edición lineal referida a la escena (scene-referred), lo que hace que el desenfoque, la corrección de desenfoque, la reducción de ruido y las verdaderas transiciones de máscara queden defectuosos.

Ansel está en un camino intermedio. Primero, ahora hay un prototipo de editor nodal:

image
image

Esto nos permite mostrar explícitamente el orden del pipeline, reordenarlo manualmente y cambiar los presets de ordenación, de una forma que también muestra las entradas y salidas. Antes solo teníamos la pila de módulos de la interfaz gráfica en la barra lateral derecha, que en cierto modo sugería el orden del pipeline si se leía como una pila de capas, pero los usuarios a menudo la usaban mal como una mera comodidad para reordenar la caja de herramientas de la interfaz gráfica.

Y luego, la división de funciones es híbrida:

  • Los módulos ecualizador de contraste, contraste local y difuminar o enfocar son intrínsecamente duales por naturaleza: pueden aumentar o disminuir el contraste local y el enfoque según sus parámetros. El ecualizador de contraste incluso tiene un método de reducción de ruido, lo cual tiene sentido porque enfocar aumenta el ruido, así que el lugar adecuado para mantenerlo bajo control es donde se genera. Estos son módulos que priorizan el método.
  • El balance de blancos duplica la funcionalidad de la parte de adaptación cromática de la calibración de color. El balance de blancos es una simple normalización por canal que ocurre en el RGB del sensor, y lo necesitan algunos métodos de interpolación cromática (especialmente para los sensores XTrans), mientras que la calibración de color realiza una compensación del iluminante mucho más precisa perceptualmente en el espacio CIE CAT16. Ese espacio se define a partir del espacio CIE XYZ 1931, que solo obtenemos tras el perfilado de color de entrada (y eso requiere una imagen desmosaicada para funcionar). Hay distintas razones y necesidades para ambos, y deben situarse en lugares diferentes del pipeline. Estos son módulos que priorizan el pipeline: aunque parezcan funcionalmente similares, sus razones de existencia y sus requisitos internos (y matemáticas completamente distintas) los hacen mucho más diferentes de lo que podrías pensar. Lo mismo se aplica a los diversos módulos de reducción de ruido: algunos trabajan sobre la entrada RAW, otros no, y algunos funcionan mejor con señales no lineales.
  • El balance de color se diseñó como un módulo de color todo en uno, que aplica un ASC CDL  extendido (slope-offset-power), y luego gestiona la saturación y el croma globales y por luminancia, reemplazando por tanto módulos anteriores de Darktable como contraste-brillo-saturación, vibración y velvia (todos funcionando en CIE Lab 1976). Tomado por sí solo, es un módulo que prioriza la funcionalidad, pero no es el único módulo de desplazamiento de color. Los demás módulos de desplazamiento de color usan métodos muy diferentes (matrices, LUT o controles por tono), que son de 3 a 9 veces menos costosos computacionalmente de ejecutar, y operan en distintos espacios de color.

Ansel hereda su concepto de módulos de Darktable: los módulos son al mismo tiempo un widget de la caja de herramientas de la interfaz gráfica y un filtro de píxeles insertado en algún punto del pipeline. Así, diseñar módulos muy pequeños (en cuanto a funciones) generará muchos widgets de alto nivel en la barra lateral derecha, mientras que diseñar módulos muy grandes producirá menos widgets de alto nivel, pero serán más altos o usarán más pestañas internas. La segunda opción podría seguir siendo preferible porque los módulos de alto nivel de la interfaz gráfica actúan como bandejas, así que menos bandejas que sean funcionalmente consistentes ayudan a comprender mejor la división de funciones de alto nivel (como una tabla de contenidos).

Pero no acaba ahí, porque de nuevo… los nodos. Un módulo debería ser un conjunto de controles de color que sean consistentes como un nodo enmascarado y multiinstanciado en el pipeline. No es bueno llenar un módulo con decenas de funciones donde la mitad de ellas tienen sentido como ajustes globales, y el resto solo en la localidad de la máscara; una vez instanciadas, solo consumirán ciclos de CPU para nada.

Y por último, está el rendimiento. Los controles de color que necesitan trabajar en algún espacio de color particular necesitarán una conversión de color de ida y vuelta, que consumirá ciclos de CPU, así que es mejor que todos se ejecuten en el mismo módulo si tienen sentido juntos desde el punto de vista funcional. Además, cualquier módulo nuevo ejecutará un nuevo bucle sobre los píxeles, lo que significa que moverá la imagen una vez más a la caché de memoria de la CPU desde/hacia la RAM. Así que agrupar funciones en el mismo bucle evita un abuso adicional del ancho de banda de E/S y ayuda con el rendimiento.

Así que, si recapitulamos toda la lista de restricciones, aquí tenemos un reto realmente difícil de resolver:

  1. siempre deberíamos esforzarnos por construir la menor cantidad de elementos de interfaz gráfica porque una interfaz desordenada hace que todo sea difícil de encontrar (y cognitivamente abrumador): el mejor lugar para esconder un árbol es en el bosque,
  2. el desorden que construyamos debería organizarse de lo global a lo local, de lo genérico a lo específico, de lo frecuentemente usado a lo especializado, porque es la manera más fácil de razonar sobre ello: pensar en la estructura de la interfaz gráfica como una “tabla de contenidos” es lo mejor que se me ha ocurrido hasta ahora,
  3. pero hacer una regla de dividir sistemáticamente las funciones según la funcionalidad o según el método aún acaba con duplicaciones en ambos casos, a menos que vayamos en la dirección del editor totalmente nodal, hagamos todo basado en el método, y difiramos la responsabilidad de construir pipelines al usuario experto,
  4. los módulos deberían diseñarse de manera que prioricen la funcionalidad siempre que sea posible, pero se aplican muchas limitaciones:
    1. el tipo de señal de entrada, que determina la posición en el pipeline, y puede obligarnos a priorizar el pipeline y a duplicar herramientas,
    2. la relevancia y consistencia del conjunto de controles del módulo cuando está multiinstanciado y enmascarado: un módulo debería ser una unidad consistente del flujo de trabajo de edición, no un cajón de sastre para embutir todo. En particular, si tiene sentido (en cuanto al flujo de trabajo) aplicar una máscara solo a un subconjunto de las funciones del módulo, entonces ese subconjunto debería ser su propio módulo,
    3. problemas de rendimiento (viaje de ida y vuelta entre espacios de color, mapeo de gama de la salida, ancho de banda de E/S): no podemos pensar en la ergonomía del usuario únicamente desde el lado de la interfaz; la velocidad de ejecución también forma parte de la ergonomía,
    4. la naturaleza matemática de las operaciones realizadas: algunos métodos (especialmente el enfoque/contraste local) pueden tener efectos opuestos según el signo de sus parámetros, algunos métodos son poco adecuados para agruparse juntos en el mismo filtro de píxeles,
  5. por último, hay que considerar la cantidad de clics/pasos de desplazamiento necesarios para llegar a una función de uso frecuente, porque el eje genérico -> específico no siempre es paralelo al eje frecuentemente usado -> especializado. Así que, aunque la organización de alto nivel genérico -> específico tiene sentido cognitivamente, no siempre es la más ergonómica.

Todos estos requisitos contrapuestos deben arbitrarse caso por caso, mirando la totalidad del pipeline, de lo contrario no construimos una aplicación de flujo de trabajo sino un registro de plugins. Viven en la encrucijada entre la programación de bajo nivel, las matemáticas, el flujo de trabajo de retoque y la ergonomía de la interfaz, y ninguno de estos conceptos es en general más importante que los demás. Sin embargo, algunas de estas restricciones se entienden más fácilmente que otras, lo que hará que reciban mucha más atención, en un típico efecto de la farola : seguir persiguiendo problemas en la capa que entiendes mientras descartas por completo su verdadero origen porque toca una capa que no entiendes/de la que no sabes nada. Por eso es un auténtico incordio trabajar con “diseñadores de UX”, porque normalmente no tienen la base para mirar más allá de la interfaz gráfica y a menudo no les importa que haya un motor que controlar debajo de la interfaz. No puedes simplemente decidir cancelar la gravedad porque te gustaría eliminar el controlador de cabeceo  para simplificar la interfaz.

El diseño es un proceso de refinamientos iterativos guiados por los comentarios de los usuarios. Algunas de estas iteraciones rediseñarán de lo macro a lo micro (de la arquitectura global de la aplicación a los controles internos de los módulos), y otras rediseñarán de lo micro a lo macro, hasta que converja hacia una semántica unificada y una división de funciones coherente. Es una insensatez pensar que alguien lo hará bien en una sola pasada, o pensar que solo uno de los niveles micro/macro necesita arreglos. Es un puente que hay que construir desde ambos extremos a la vez, y encontrar la forma de que se encuentren en el medio.

Las propiedades de unos buenos controles de color

Por mis 17 años de experiencia editando fotos, y 8 años de experiencia estudiando y experimentando con las matemáticas del procesamiento de imágenes, hay un par de cosas que he aprendido sobre lo que es un buen o un mal control de color. Por “control de color” me refiero a alguna forma de transmitir la intención del usuario a un algoritmo de píxeles que editará una propiedad visual de una imagen. Unos buenos controles de color:

  1. son ortogonales entre sí, lo que significa que un control cambia una dimensión del color en un momento dado y no te obliga a compensar en otro control,
  2. están escalados de manera uniforme desde una perspectiva perceptual, lo que significa que ir de “0” a “1” cambiará el resultado visual en la misma medida que ir de “1” a “2”. Por desgracia, esto no siempre es posible, porque las matemáticas y la física te odian.
  3. escalan con elegancia a medida que aumenta el rango dinámico, lo que descarta prácticamente todos los modelos de apariencia del color (CIE Lab 1976, CIECAM 16, dt UCS 22), construidos para SDR sobre conjuntos de datos registrados con parches de color pintados.
  4. se degradan con elegancia a medida que aumentamos la magnitud de los cambios, lo que significa que pueden sobrecocinarse pero no pueden cambiar el contenido de la imagen ni crear artefactos,
  5. preservan los gradientes de la imagen, lo que significa que mantienen las variaciones locales tonales y cromáticas como variaciones, en lugar de aplanarlas, hacerlas sobrepasar (creando halos, franjas, ruido, etc.) o invertirlas.
  6. permiten a los artistas acercarse lo máximo posible a su intención en la menor cantidad de tiempo.
  7. no están duplicados.

Del punto 1, deducimos por ejemplo que cualquier tipo de curva de tonos RGB es mala, porque desaturará las luces y saturará las sombras como subproducto de la cantidad de contraste (de luminancia) que añadiste, y no puedes controlar (ni descorrelacionar) la cantidad de cambio de saturación que obtendrás por la cantidad de cambio de contraste que pediste, salvo mediante trucos como la preservación de ratios RGB o manipulando manualmente la saturación/desaturación a través de la aplicación de la curva de tonos. Esta es la razón de existir del ecualizador de tonos, que corrige el contraste usando un ajuste de exposición selectivo en lugar de una curva de tonos.

Del punto 2, deducimos que los controles de la interfaz gráfica deberían usar modelos de apariencia del color siempre que sea posible.

Del punto 3, deducimos que los modelos de apariencia del color usados en la interfaz gráfica no deberían usarse sobre los píxeles, sino que deberían convertirse para que los píxeles se manejen en RGB. Este es un paradigma típico modelo-vista-controlador  que se ignora sistemáticamente en todas las aplicaciones de procesamiento de imágenes. Aparentemente, hay una creencia entre los desarrolladores de que el modelo de color de los píxeles debería coincidir 1:1 con el espacio de color del controlador de la interfaz gráfica.

Del punto 4, deducimos que los controles que en la práctica solo son utilizables en un pequeño subconjunto de su rango de valores están usando malas matemáticas, malos modelos de color, malas suposiciones previas. Los modos de fallo son tan importantes como lo que ocurre al usar los controles en su punto óptimo.

Del punto 5, simplemente confirmamos el punto 3.

Del punto 6, planteamos un nuevo problema: muchos fotógrafos no tienen una intención de retoque/edición (es decir: un objetivo visual final), sino que solo empujan y tiran de los deslizadores en la dirección que parece hacer que la imagen se vea mejor, y acaban con un accidente afortunado que serían incapaces de reproducir (o descartan la imagen por ser incapaces de trabajarla). En este caso, no hay ninguna métrica de éxito para los controles porque no hay ninguna diferencia que calcular entre intención y resultado, ya que la intención no está definida. Por eso, al trabajar con los comentarios de los usuarios, necesitamos ser críticos e investigar quién habla y desde dónde. Es decir: no todo comentario de usuario es un buen comentario de usuario (y los años de experiencia no son prueba de nada por sí mismos).

Y el punto 7 no es más que un recordatorio de la sección anterior: tener que duplicar un ajuste suele ser indicativo de una mala división de funciones, o necesitas tener una buena razón para hacerlo.

Todos estos son obviamente los casos ideales a los que aspirar. En la práctica, tienes que evaluar distintos candidatos y elegir el mejor, que rara vez cumplirá todos los requisitos. Pero para evaluar candidatos que compiten, primero necesitas puntos de referencia y escalas objetivas. Esos son los puntos de referencia que se me han hecho evidentes con los años.

Las propiedades de unos buenos flujos de trabajo de edición

Recuerdo interminables cadenas de correos, hace 9 años en la lista de correo de Darktable (ahora desaparecida), sobre cuál era la mejor manera de reorganizar la interfaz gráfica, en las que me decían: “no hay flujo de trabajo correcto ni incorrecto, solo preferencias personales”. El relativismo absoluto siempre es más estúpido de lo que suena. Esa estupidez continúa ahora en discuss.pixls.us. Son realmente las mismas discusiones, diciendo las mismas cosas sobre los mismos problemas, dando vueltas en bucle durante más de 9 años, y todavía sin ninguna solución tangible.

Primero está el caso obvio en el que defines una máscara paramétrica en, digamos, balance de color RGB, y la configuras para enmascarar los valores RGB entre lo que sea y lo que sea + épsilon. Entonces, estás contento con los colores, pero tu imagen se ve un poco oscura, así que vas y subes la exposición. Ahora tu máscara paramétrica es inválida y tienes que rehacerla de nuevo, porque la exposición se sitúa antes en el pipeline que el balance de color RGB, así que has desplazado todo tu rango de valores de código RGB. Esto es edición circular, es la pérdida de tiempo más evitable, y si quieres prevenirla, no hay mucha elección: tienes que cuidar el orden de tu pipeline. La edición circular es un flujo de trabajo objetivamente malo. ¿Necesito justificarlo?

No se detiene en las máscaras, porque muchos módulos de color necesitan normalizar el blanco HDR para poder usar modelos de color que solo pueden funcionar bajo el supuesto de que blanco = {1, 1, 1}. Por eso pongo esos más adelante en el pipeline, después de los ajustes globales de brillo y contraste.

Y luego, está el caso de la edición por lotes: tienes una serie de imágenes que editar, quieres que se vean consistentes a lo largo de toda la serie, pero tienen variaciones menores en iluminación, contraste y temperatura de color. La única manera de que eso funcione es tener un primer paso de normalización de la imagen, para manejar las variaciones individuales de cada imagen y convertirlas a un estado constante. Una vez hecho esto, puedes aplicar por lotes el mismo estilo o copiar y pegar el historial de los módulos posteriores encima, porque ese siguiente paso recibirá entradas “constantes” normalizadas y por tanto debería producir salidas consistentes (si no constantes). No lograr ese primer paso de normalización hará que el siguiente sea completamente poco fiable e impredecible, lo que frustrará el propósito de la edición por lotes. E incluso con ese flujo de trabajo aparentemente rígido, todavía acabarás teniendo que hacer un ajuste fino individual si de verdad quieres resultados consistentes. Esto no es mi opinión, es un simple hecho: si quieres salidas consistentes para un conjunto de modificaciones de imagen con ajustes rígidos, necesitas entradas consistentes.

Pero hay una limitación a eso, porque cuando trabajas con señal HDR, necesitas configurar tu mapeo tonal HDR -> SDR pronto, para poder ver realmente lo que estás haciendo en tu imagen, sin recorte de las luces. Así que hay un primer paso de tomar una vista general de tu contenido, y luego un paso de finalizar los límites del rango dinámico. Lo que significa que siempre deberías configurar primero la exposición global, mirando los tonos medios (y nada más), y luego configurar tu mapeador tonal de trabajo por ahora. Así que esa regla de intentar anclar tu flujo de trabajo 1:1 al orden del pipeline (a su vez anclado en los requisitos de entrada de los módulos) tiene algunas excepciones y no puede aplicarse sin discernimiento.

Lo que significa que deberías haber aprendido todo eso. Los buenos flujos de trabajo provienen de personas que pensaron en cómo adaptarse a las herramientas que usaban, mirándolas tanto desde el punto de vista práctico como teórico, y no de los despreocupados que confundieron con un flujo de trabajo todos los hábitos malformados que adquirieron con los años. Una vez más, hay cosas que suceden por debajo de la superficie de la interfaz gráfica, no estamos escribiendo cartas en un procesador de textos. Durante más de 9 años he estado gritando en bucle en los foros: ES UN PIPELINE, NO UN CONJUNTO DESCONECTADO DE CONTROLES DE IMAGEN ALEATORIOS. El orden importa. Si hay una sola cosa que entiendas de toda esta perorata, debería ser esta.

Y creo que Lightroom ha hecho mucho daño a las expectativas y a la comprensión de los usuarios al ocultar su pipeline interno. Pero le funciona a Lightroom porque quita muchos grados de libertad a los usuarios. Darktable ha reutilizado mucha de la semántica de la interfaz de Lightroom a la vez que proponía gradualmente más libertad y control directo sobre los nodos del pipeline (introduciendo a lo largo de los años el enmascarado por módulo, luego la multiinstanciación de módulos y el reordenamiento de instancias relativas, luego las máscaras rasterizadas reutilizables entre módulos no consecutivos, y finalmente el reordenamiento completo de los módulos), lo que ha confundido tanto a los veteranos como a los recién llegados por igual.

La idea de un pipeline no es siquiera específica de la fotografía digital. La pintura al óleo también tiene un pipeline de algún tipo, en el que empiezas preparando tu soporte, lo recubres con imprimación para hacerlo menos absorbente, luego pones los contornos, luego preparas el fondo, luego aplicas tu veladura  y por último pones la capa de barniz. Nadie en su sano juicio empezaría con el barniz y terminaría con la imprimación. La fotografía analógica tiene obviamente un pipeline de baños químicos, temporizadores y demás. Y las aplicaciones de pintura como Photoshop, Gimp o Krita tienen un pipeline explícito, materializado por capas que se ocluyen entre sí, de abajo hacia arriba, con capas de efecto que no son más que filtros de píxeles paramétricos que producen salidas dinámicas.

Pero de algún modo, como el software de edición de fotos raw hace que parezca desconectado de las realidades materiales, parece aceptable en lo digital trabajar sin estructura ni método. El flujo de trabajo de edición “no destructiva” también podría haberse interpretado libremente como YOLO  aquí, lo cual tampoco ayuda. Que tengas Ctrl+Z no significa que de repente todo sea perdonable.

Para resumir, los buenos flujos de trabajo de edición son los que te dan resultados predecibles en cada paso a la vez que evitan la edición circular. Deben estar informados por el orden del pipeline, pero no pueden ceñirse 1:1 a él todo el tiempo, y tienes que usar tu criterio para distinguir cuándo ceñirte al pipeline y cuándo desviarte. Eso deja muy poco margen para las preferencias personales.

La ética del procesamiento digital de imágenes

En los tiempos analógicos, los artistas trabajaban con medios físicos, y podían realizar toda clase de trucos y encontrar nuevas técnicas para lograr resultados a medida. Era accesible porque podías tocar físicamente el medio con el que trabajabas. Los artistas eran libres.

El arte digital es inherentemente violento, en la medida en que ha quitado libertad a los artistas: ahora no pueden encontrar nuevas técnicas por sí mismos, porque su arte existe como pura información en alguna memoria de ordenador, así que están limitados a lo que proponen las aplicaciones, y pueden o bien suplicar a los editores/desarrolladores de software que consideren sus necesidades, o bien aprender a programar y programarlas ellos mismos (lo cual es una cuota de entrada considerable si no tienes formación técnica en ciencias aplicadas o informática). La pérdida de libertad puede quedar oculta por el hecho de que cualquier cosa hecha en software es reversible, así que los fotógrafos no dañan permanentemente los negativos, por ejemplo. Peor aún, el software puede hacerte más productivo, así que es una ganancia neta desde el punto de vista del negocio. Pero eso no debería ocultar el hecho de que a los artistas se les coloca en una posición de consumidor más pasiva que antes, y dominada por quienes saben cómo y quieren programar por ellos, que son quienes deciden cómo harán arte a partir de ahora.

“Violencia”, “supresión de la libertad”, “dominación”… Ya sabes hacia dónde va esto: se llama opresión. Una opresión sexy que te promete lograr resultados profesionales en solo unos clics sin tener que ir a la escuela de fotografía. O, en el contexto del software libre, una opresión que parece benévola e inofensiva porque no hay nada que pagar y la privacidad de los datos viene integrada. Pero nada de eso es incompatible con el hecho de que, nosotros, los desarrolladores, controlamos lo que tienes derecho a hacer en/a tus imágenes, o no, porque controlamos el código. No porque hayamos sido elegidos por los usuarios, no porque seamos competentes para la tarea en cuestión (a estas alturas, he demostrado muchas veces aquí que el “equipo” de Darktable no era más que un puñado de idiotas sin idea y con demasiado tiempo libre), simplemente porque tenemos derechos de administrador sobre algún repositorio de Github. Eso nos da poder, y el poder viene con responsabilidad.

Esto ha estado rondándome la cabeza desde hace varios años, porque se convierte también en un dilema ético (además de todos los técnicos mencionados anteriormente) decidir qué funciones añadir, o eliminar, o refactorizar. Al mismo tiempo, intentar complacer a todo el mundo no es posible y acabaría abrumando a todos con montones de herramientas especializadas que nunca usarán (de nuevo: esconder un árbol en el bosque). Además, también es más código que mantener, así que más trabajo y una carga para los mantenedores en el futuro, con más amenazas a la estabilidad del software. Construir una navaja suiza que está constantemente medio rota no va a ayudar a nadie.

Pero sigue siendo cierto que eliminar controles por el bien de simplificar la interfaz gráfica podría no ser más que eliminar libertad, si no estamos seguros de que una funcionalidad similar siga existiendo, de una forma u otra, en el software. La libertad artística no es un bien de consumo, es una necesaria bocanada de aire fresco en sociedades que se derivan cada vez más hacia el (tecno)fascismo, una vez más.

De nuevo, todo eso tiene que arbitrarse caso por caso. Dejar que las aplicaciones de procesamiento de imágenes vayan en todas las direcciones a la vez, intentando acomodar todas las necesidades en una sola aplicación, incluso las más peculiares, va a construir ovejas de 5 patas que son poco prácticas de usar para cualquiera. Lo cual nos remite de nuevo a mi primera sección: construir herramientas genéricas, versátiles y libres de supuestos que puedan adaptarse a muchas necesidades diferentes de forma factorizada. Industria frente a artesanía.

La productividad se logra mediante la especialización (que, combinada con la estandarización, desbloquea la automatización), la especialización se logra mediante la duplicación, la duplicación crea sobrecarga y desorden en la interfaz gráfica, la sobrecarga y el desorden son los enemigos de la UX y la creatividad. La conclusión de todo eso es: elijamos qué merece la pena especializar, y así obstaculicemos la libertad de los usuarios. Por lo tanto, la productividad es el paradigma equivocado: su conclusión natural es la opresión.

Lo opuesto a la productividad es la robustez y la versatilidad. Puede que sea más lento (¿lo es de verdad?), pero podemos manejar una mayor variedad de casos con el mismo número de herramientas, sin eliminar arbitrariamente opciones, y por tanto la libertad del usuario. El concepto de robustez ya ha sido desarrollado en el contexto de la inestabilidad social y climática por Olivier Hamant, en su libro Antidote to the cult of performance. Robustness from nature (2024). Una de sus principales conclusiones es que el culto al rendimiento (o a la eficiencia) solo conduce a la competencia, que promueve la violencia, y en los tiempos inestables que se avecinan, necesitamos cooperación. En una sociedad que produce más que suficiente para cubrir las necesidades de todos (pero lo distribuye mal), el rendimiento no nos hace ganar nada salvo más beneficios (de nuevo, mal distribuidos). Pero lo que sí produce con seguridad es el agotamiento (burn-out), tanto en las personas como en los ecosistemas.

En el software, el agotamiento puede provenir de varias cosas:

  1. el tecnoestrés  vinculado a demasiadas aplicaciones, herramientas, estándares y paradigmas a los que adaptarse,
  2. la sobrecarga de información , vinculada a un exceso de widgets y herramientas de interfaz gráfica por los que navegar,
  3. la fatiga del cambio  vinculada a actualizaciones demasiado frecuentes que cambian los flujos de trabajo.

En resumen, perseguir el rendimiento cae en cascada en una serie de inconvenientes:

  1. desde un punto de vista técnico, significa tener que construir herramientas más especializadas que sobrecargan la interfaz gráfica, lo que produce sobrecarga de información,
  2. desde un punto de vista de UX, mantener el desorden y la sobrecarga razonables implica elegir arbitrariamente qué necesidades se cubrirán (probablemente las de la mayoría) y qué necesidades se ignorarán, lo que es eliminar libertad artística a cualquiera que se desvíe demasiado de lo mayoritario: esto es una primicia en la historia del arte, y ninguna cantidad de libertad del software lo hace menos violento,
  3. desde un punto de vista de marketing, solo los profesionales necesitan productividad, y ahora mismo parecen preferir el software comercial en gran mayoría. No hay ningún beneficio para el código abierto en ir a “ganar nuevos mercados”, más bien debería esforzarse por cubrir los nichos desatendidos. Y además, la fotografía profesional está muriendo lentamente desde los años 1980, así que no estoy seguro de que siga siendo un mercado sustancial por mucho más tiempo.

Esa fue una larga introducción, pero en un mundo donde todos creen que pueden ser diseñadores, es necesario exponer por completo la lista entera de requisitos de diseño antagónicos para calmar a quienes creen que son el próximo Leonardo Da Vinci, y darles una noción de que la simple idea que se les ocurrió solo parece brillante porque no tienen la nota de especificación completa. He tenido demasiados de ellos en mi buzón y en mis rastreadores de incidencias.


Cómo se maneja en Ansel

Todas las capturas de pantalla se han hecho en un portátil de 15,6’’.

Presentación de los módulos globales

Antes que nada, recordemos cómo se rehízo la presentación general del cuarto oscuro:

image
  • las pestañas de los módulos recibieron nombres explícitos en lugar de iconos crípticos,
  • las pestañas están ordenadas (externamente) en el orden de flujo de trabajo sugerido, de izquierda a derecha, así que los usuarios solo tienen que seguir la interfaz como una guía,
  • dentro de las pestañas, los módulos están ordenados en orden de pipeline (con una lógica de capa “encima”, de abajo hacia arriba), que también es el orden de flujo de trabajo generalmente aconsejado. La nueva pestaña “básica” es una excepción, al tener secciones de módulos: dentro de las secciones, los módulos están ordenados según el pipeline, pero las propias secciones están ordenadas según el flujo de trabajo (de nuevo, lógica de capa “encima”, así que de abajo hacia arriba),
  • la pestaña “pipeline” o el grafo nodal de orden de los módulos desambiguan todo y muestran una vista directa de los nodos del pipeline sin ningún reordenamiento intermedio,
  • las pestañas de “favoritos” se han eliminado por completo, ya que solo pretenden resolver la sobrecarga añadiendo más de ella.

Mientras tanto, las barras de herramientas centrales se han eliminado por completo, liberando la máxima cantidad de espacio para las imágenes en formato retrato, en pantallas 16:9 y 16:10 donde el espacio vertical es realmente más valioso que el horizontal. El uso de un menú global ha permitido de nuevo eliminar muchos botones de icono extraños de las barras de herramientas, y reemplazarlos por elementos de menú textuales y explícitos. Así, en modo pantalla completa, ahora solo pierdes la altura de la barra de menú global:

image

Las opciones de fusión y enmascarado, al estar unificadas entre módulos, se han trasladado a la barra lateral izquierda. Esto libera mucho espacio vertical para los módulos, reduciendo la necesidad de pestañas internas y evitando muchos clics de un lado a otro. Ten en cuenta que las opciones de fusión se están reescribiendo actualmente, después de que la API de máscaras haya sido completamente refactorizada, simplificada y ampliada, así que esta es solo una vista temporal.

Las vistas de Ansel son bastante verbosas, así que para ayudar a distinguir entre el texto constante (etiquetas) y las variables (valores), se ha introducido un coloreado de sintaxis:

  • las etiquetas constantes son blancas,
  • los valores variables son naranjas.

Calibración de color

En calibración de color, las 3 pestañas R, G y B se han fusionado en la misma pestaña mezclador, que ahora cabe por completo en vertical. Lo mismo ocurre con brillo, colorido y B&N, que ahora se fusionan en salidas.

La pestaña mezclador tiene ahora 2 modos de interfaz alternativos, además del habitual (ahora denominado completo) ;

La vista primarios se llevó al Darktable original, salvo que ellos la convirtieron en un módulo independiente, lo cual es estúpido : las matemáticas internas de píxel son exactamente una multiplicación por una matriz 3×3, que es lo que también es calibración de color, así que no hacía falta un módulo adicional. Este es de nuevo un problema resuelto en la capa equivocada : necesitaba una capa de interfaz adicional en un módulo existente, y ellos lo convirtieron en un módulo duplicado.

En cambio, Ansel lo implementa como una capa de interfaz, lo que significa que los parámetros habituales del mezclador de canales se convierten de ida y vuelta a los parámetros de la vista de primarios, y las matemáticas de píxel del módulo no han cambiado desde 2021. En aras de una transformación totalmente invertible de la matriz 3×3 a la vista de primarios, hubo que añadir un parámetro adicional de ganancia para cerrar matemáticamente la transformación.

La vista simple es algo que tenía en el cajón desde hace varios años : reexpresar los parámetros poco intuitivos del mezclador en términos de rotación de tono, estiramiento del plano de croma (contraste de color) y redimensionado acromático. El estiramiento U/V reemplaza el módulo heredado de Darktable color contrast, que trabaja en CIE Lab 1976 y empujaba o tiraba de las cromaticidades a y b. Las vistas simples van más allá y te permiten definir tu propio espacio de cromaticidad uv mediante la rotación de los ejes de croma (uv) : cuando se fija en 0°, u es un eje verde-magenta y v es un eje azul-amarillo (similar a color contrast). Pero luego puedes girarlo hacia lo que necesites; por ejemplo, alrededor de -20°, el eje v se vuelve bastante cercano a un eje de temperatura de color, y el eje u al eje de tinte ortogonal. Te dejo con la documentación.

Este modo es especialmente adecuado para recuperar luces de escenario azules abrumadoras, mucho más fácilmente que con la interfaz habitual del mezclador de canales :

After After
Before Before
Foto © Reinout Nonhebel, 2018
  1. al comprimir el eje V, comprimimos fuertemente la gama en el eje azul-amarillo, lo cual es mucho más suave con el resto de la gama que usar una compresión global de croma,
  2. al comprimir el eje U, también comprimimos la gama en el eje magenta-verde, pero de forma mucho más suave,
  3. el tono de acoplamiento acromático se fija en azul profundo. Al aumentar la cantidad de acoplamiento, remapeamos una parte del azul hacia el eje acromático, es decir, lo desaturamos y lo aclaramos a la vez, lo que ayuda mucho a recuperarlo dentro de la gama, preservando al mismo tiempo la sensación general de azul. A la inversa, el color complementario se oscurece y se resatura, pero como ese color opuesto es el amarillo, y comprimimos el eje amarillo-azul mediante V, acabamos aproximadamente en el mismo sitio.

Así que esta reescritura de coordenadas simple de los parámetros del mezclador de canales produce 6 controles en lugar de 9, y son mucho más significativos y fáciles de controlar. Se trata de un problema de UX que se abordó puramente desde el lado matemático, porque esto no es más que reexpresar una matriz 3×3 en una nueva base de vectores propios ortogonal, rotada sobre el eje RGB acromático, es decir, partió puramente de una intuición de álgebra lineal. Debido a las propiedades de esta nueva base de vectores propios (que se imponen por diseño), pude eliminar dimensiones y convertir las restantes en controles más significativos. Que es lo que quiero decir cuando repito que no puedes resolver problemas de UX simplemente mirando la interfaz.

Virado dividido RGB

El módulo heredado de Darktable split-toning trabajaba en el espacio HSL, que no admite valores de código RGB mayores que 1 (por tanto, nada referido a la escena). Además, mezclar colores en HSL es raro y da la sensación de filtros de juguete cuando empiezas a subir los ajustes.

Al mismo tiempo, el esquema actual de adaptación cromática en Ansel asume un único iluminante. Sin embargo, las escenas reales siempre tienen al menos dos iluminantes :

  1. la fuente de luz principal, que es el iluminante primario, y pesará sobre todo en las luces y los tonos medios,
  2. superficies coloreadas que rebotan la luz de la fuente principal y la tiñen, que actúan como iluminantes secundarios, y pesarán sobre todo en las sombras hasta los tonos medios.

Hasta ahora, para manejar esta situación de iluminantes mixtos, tenías que duplicar instancias de calibración de color y enmascararlas dentro y fuera. Pero intentar recortar una máscara binaria (una región atribuida a un iluminante y el resto al otro iluminante) es frágil porque no tiene en cuenta la mezcla de luz que ocurre alrededor de los tonos medios.

Así que el nuevo módulo virado dividido en Ansel propone dos mezcladores de canales y dos correcciones de temperatura de color, y duplica los nuevos modos de interfaz de calibración de color. Te permite definir el brillo de cada iluminante, asocia una matriz de color a cada uno y calcula una mezcla de ambas matrices que se aplica a cada píxel en función de su luminancia.

After After
Before Before
© Luc Viatour, 2016

Llegados a este punto, quizá pienses que estoy obsesionado con la fotografía de conciertos, pero es solo porque las luces de escenario son la configuración más exigente y no perdonan ningún error en el pipeline de color. Estos han sido problemas sin resolver durante décadas; se sabe que las luces azules se convierten en magenta, y son el referente definitivo del color.

Aquí, ajustamos la temperatura de las luces para lograr tonos de piel más naturales, preservando al mismo tiempo el entorno azul general en las sombras. En una escena así, no hay ningún blanco que puedas muestrear, por lo que apuntar a tonos de piel naturales es la única guía. Luego, haces lo posible por preservar el espíritu de la iluminación de escenario (mantener el azul azul), teniendo en cuenta los límites de tu gama RGB. Para más detalles, consulta la documentación.

Primarios de color

Como mencioné antes, el módulo primaries de Darktable es un mero duplicado del mezclador de canales con una interfaz diferente. Pero hay casos en los que manipular todo el espacio de color a través de sus primarios daña demasiado el rango de baja saturación, que era perfectamente válido. Así pues, había necesidad de afectar a los colores primarios y secundarios (en los vértices del cubo de gama) de una manera que excluyera el centro de la gama, pero que aun así fusionara los efectos de forma suave entre ambas regiones y preservara los gradientes de la imagen.

Esto se logró construyendo una LUT RGB en un nuevo módulo : primarios de color.

After After
Before Before
© Andrea (fuente )

Este ejemplo se diseñó para hacer el rojo y el naranja menos abrumadores, pero profundizar drásticamente los azules, con el fin de mostrar lo estable que es la transformación de color a lo largo de los bordes entre superficies de distinto color.

Dado que, internamente, el módulo construye dinámicamente una LUT desplazando el color de los nodos de control, los usuarios obtienen la posibilidad de decidir a qué distancia de los vértices del cubo RGB se sitúan los nodos de control, mediante el deslizador de cobertura de gama. Luego, 3 parámetros de suavizado permiten fusionar con mayor o menor intensidad los desplazamientos de color en RGB, y proteger en mayor o menor medida los colores neutros del desplazamiento. Por último, el módulo dispone de un visor de LUT en 3D:

image

El visor de LUT muestra los desplazamientos de color a lo largo de todo el cubo RGB, desde el origen hasta el destino. Se puede rotar alrededor del eje acromático (azimut), o ponerse en una vista de plano de cromaticidad (inclinación del eje = 90°). Se puede hacer zoom, desplazar y rotar en 3D mediante eventos del ratón, y cortar en secciones para obtener una mejor vista a cierta profundidad. Por último, la LUT 3D generada se puede exportar como un archivo cLUT .cube para reutilizarla en cualquier software que los admita. Para más detalles, consulta la documentación.

Ecualizador de color

El “equipo” de Darktable tomó mi segundo prototipo (que no funcionaba)  del ecualizador de color, no entendió por qué no funcionaba, añadió pasos de posfiltrado para ocultar los problemas, y lo lanzó como si fuera obra suya, sin siquiera acreditarme. Que se lo queden : es una mierda. Y de todos modos yo no firmo con mi nombre una mierda.

Verás, el problema de ese prototipo es que aplicaba el desplazamiento de saturación en el espacio de color dt UCS 22 HSB, que diseñé en 2021 . Este espacio de color ya se usa en color balance RGB para la saturación, y buscaba encontrar la cantidad correcta de oscurecimiento que debería aplicarse a un color al aumentar su “saturación” (en realidad, su croma, en términos rigurosos de ciencia del color), a fin de evitar que degenere en colores fluorescentes y neón poco naturales, que son los escollos típicos al añadir mucha “saturación”. Así, en lugar del ajuste de croma habitual que reduce el colorido a luminancia o claridad constante, esta fórmula de saturación también oscurece. Y aunque eso funciona muy bien en parches de color planos, el problema es que las imágenes no son superficies de color planas, sino que tienen gradientes.

Se me informó hacia 2022 de que la saturación dt UCS HSB de color balance RGB creaba una extraña franja acromática brillante entre las hojas de otoño amarillas, brillantes y saturadas, y el cielo azul profundo detrás de ellas. El problema era que, en el borde, la luz amarilla de las hojas y la luz azul del cielo se mezclaban en acromático (como deben, al ser colores complementarios) debido a un objetivo ligeramente blando o a la neblina atmosférica. El algoritmo de saturación oscurecía el amarillo y el azul a cada lado de la franja acromática, pero no la franja en sí, que ahora resaltaba más brillante. Y no hay solución para eso; no es un error algorítmico: el problema es el modelo de color, que da cuenta de la percepción pero no de la mezcla de luz. Así que fui, una vez más, otro autor de otro espacio de color roto que me llevó meses desarrollar y 20 horas de cálculo para ajustar numéricamente los parámetros del modelo.

Intentar implementar un ecualizador de color reutilizando ese mismo espacio de color empeoró aún más estos problemas, porque ahora el efecto se controlaba en función del tono, lo que significaba problemas en dos dimensiones en lugar de una. Para paliar el problema, intenté suavizar las cosas usando filtros guiados RGB. Pero no llegué a encontrar la fórmula mágica para tener una fusión adecuada y robusta. Fue entonces cuando el equipo de Darktable decidió rebuscar la reluciente novedad de la estantería, y cuando comprendí que esto solo podía ocurrir en RGB si se quería que fusionara correctamente y preservara los gradientes.

After After
Before Before
© baongoc124 (fuente )

El ecualizador de color hereda el mismo cursor interactivo que el ecualizador de tonos, para editar directamente sobre la imagen muestreando el tono del píxel bajo el cursor, y desplazar la rueda actualizará automáticamente el gráfico. Los nodos se pueden añadir libremente en cualquier lugar, y desde el cursor interactivo, añadir un nodo en el tono actual se hace con clic derecho.

El ecualizador de color permite definir un desplazamiento de color en función del tono para sombras, tonos medios y luces. El selector de color permite ver dónde se sitúa una región entre los controles tonales. Esto permite un control muy fino que, junto con el mismo suavizado 3D que primarios de color, proporciona una manera muy robusta de fusionar desplazamientos de color. El ruido de croma que era el principal problema, al definir desplazamientos de color drásticos, con el módulo heredado de Darktable color zones (que trabaja en CIE Lab 1976) o con el prototipo anterior del ecualizador de color, ya no aparece.

Al igual que primarios de color, este módulo crea dinámicamente una LUT RGB 3D que se puede visualizar y guardar en archivos .cube exactamente igual. Para más detalles, consulta la documentación.

Dibujo

image

¿Necesito decir algo más ?

Ansel implementa ahora un prototipo de módulo de dibujo que te permite dibujar imágenes rasterizadas en un pipeline referido a la escena a partir de pinceles de 32 bits que admiten colores HDR (>100%). Los pinceles admiten opacidad y flujo (igual que Photoshop), salpicaduras aleatorias, suavizado de trazado, difuminado de bordes, y se pueden usar en modos de pintado, borrado, difuminado y desenfoque. El tamaño, la opacidad, el flujo y la dureza del pincel se pueden asignar a la presión y la inclinación del lápiz Wacom, o a la aceleración genérica del cursor. Usan alfa premultiplicado adecuado y guardan las capas en archivos adjuntos TIFF de coma flotante de 16 bits que se pueden editar en la mayoría de las aplicaciones de dibujo principales.

Se pueden usar varias capas instanciando múltiples instancias del módulo dibujo y componiéndolas sobre la imagen mediante las opciones genéricas de fusión y enmascarado de Ansel. También se puede usar para componer cualquier tipo de capa arbitraria procedente de cualquier software, siempre que se guarde en coma flotante de 16 bits como una capa en el archivo adjunto TIFF de Ansel. La imagen de fondo (anterior al módulo) se puede exportar como capa de fondo si necesitas una imagen de referencia para dibujar en otro software e importar el resultado de vuelta.

Esto fue posible gracias a la nueva arquitectura del pipeline que habilitó un modo en tiempo real. Cierto es que aún no es tan rápido como Photoshop porque, en cada refresco de la pincelada, hay otros módulos ejecutándose después de dibujo en el pipeline.

Esa es la libertad definitiva de lograr todo lo que los botones y los deslizadores nunca te darán, ya sea aclarar y oscurecer, reparar partes dañadas (luces recortadas, áreas faltantes) o simplemente mezclar fotografía y pintura. Para más detalles, consulta la documentación.

Grano fotográfico

El módulo heredado grain de Darktable era realmente insatisfactorio, ya que solo permitía grano de luminancia y se aplicaba sobre el canal de claridad del espacio de color CIE Lab 1976. Los resultados eran extraños, sin parecerse en nada al haluro de plata. Finalmente implementé la síntesis estocástica de grano  que desarrollé en 2023 en un nuevo módulo: grano fotográfico. Este divide el campo de luz en cristales virtuales de haluro de plata y simula sensores de grano apilados en capas. Funciona tanto para grano en B&N como en color, aunque tuve que tomar cierta distancia con mi artículo inicial para manejar el color.

After After
Before Before
© Alessandro Amato del Monte (fuente )
After After
Before Before
© Alessandro Amato del Monte (fuente )

Filmic

Durante varios años, la gente me ha estado diciendo que los estúpidos módulos de Darktable sigmoid y el más reciente AgX les daban un poco más de control. Y ninguno de ellos ha sido capaz de decirme exactamente control sobre qué. Así que me llevó mucho tiempo averiguarlo.

Sigmoid y AgX no son revoluciones, son otros filmic :

  1. conviertes colores usando un logaritmo o un modelador de potencia,
  2. le encajas encima alguna curva en forma de S,
  3. luego haces lo posible por deshacer lo que la curva de tonos le ha estado haciendo al croma durante todo el proceso,
  4. y finalmente deshaces el modelador.

Sigmoid y AgX podrían haber sido modos alternativos dentro de filmic : todos pasan por los mismos pasos con prioridades y estrategias ligeramente distintas. Hacerlo así habría proporcionado un único módulo para la compresión del rango dinámico, con distintos modos según cuánto control fino quisieran los usuarios. En lugar de eso, duplicaron funcionalidad y añadieron sobrecarga de interfaz, de modo que ahora los usuarios tienen que elegir entre base curve (que ya era una variante duplicada y especializada de la propia tone curve), filmic, sigmoid y AgX para lograr la misma tarea, mientras que ninguno de ellos declara realmente la funcionalidad que proporciona.

Lo único que filmic hace mejor es manejar explícitamente los límites del rango dinámico, lo que permite usarlo para la compensación de punto negro al imprimir. Los otros dos los manejan como un subproducto del ajuste de contraste. Dado que a los desarrolladores de los otros dos no les importan las impresiones, ya te imaginas que eso alivia algunas restricciones en el diseño y elimina algunos deslizadores en la interfaz. Lo único que los otros dos hacen mejor es proporcionar controles manuales de color para deshacer los problemas de saturación y desplazamiento de tono a través del mapeo de tonos, pero realmente no creo que ese nivel de granularidad de color pertenezca a una función de mapeo de tonos : es un flujo de trabajo y una división de funciones completamente defectuosos.

En cualquier caso, finalmente averigüé que el control de contraste más fino provenía del hecho de que sigmoid proporciona directamente un control de nodos de talón y hombro, mientras que filmic usa una latitud y un desplazamiento globales que resultan engorrosos de usar, ya que los vincula ambos. Esto se diseñó originalmente para asignarlo a las hojas de datos reales de las emulsiones fotográficas, porque la latitud es algo real de las películas, con el fin de quizá emular algún día películas reales. Ese día nunca llegó.

Así que resolví el problema en la capa de interfaz añadiendo una conversión entre los ajustes de latitud/desplazamiento y luces/sombras, y ahora filmic RGB te permite manipular directamente la posición de los nodos de talón/hombro :

image

No se cambió ninguna matemática de píxel en el proceso, los parámetros del módulo siguen siendo los mismos que antes, no se creó ningún módulo nuevo, es solo un paso intermedio de conversión en la interfaz.

Conclusión

Todos los nuevos módulos admiten descarga de trabajo a la GPU mediante OpenCL. Se han diseñado para ser robustos, y creo que ese objetivo se ha alcanzado. Han reemplazado a módulos anteriores peores, que trabajaban en CIE Lab 1976, y que han mostrado sus límites y defectos durante mucho tiempo. Ahora ejecutas un pipeline RGB completo en Ansel. Los módulos heredados siguen en el programa y seguirán ejecutándose para ediciones antiguas. Además, los deslizadores coloreados y los gráficos de tono están gestionados por color usando el perfil de color de la pantalla.

Los módulos que he introducido recientemente no son juguetes relucientes nuevos con los que entusiasmarse. Son la conclusión de años de reflexión sobre una división de funciones consistente y coherente que ayuda al flujo de trabajo referido a la escena. Ese flujo de trabajo referido a la escena es más complejo que el anterior referido a la pantalla, aunque solo sea porque necesitamos normalizar el “blanco” antes de entrar en cualquier LUT o espacio de color perceptual, pero es la única manera de abordar las imágenes HDR, la fusión alfa adecuada para las máscaras, y los filtros de píxel físicamente precisos que simulan la mezcla de luz. Los filtros físicamente precisos son robustos y producen resultados orgánicos, incluso llevados a ajustes drásticos. Pero a menudo son menos accesibles para los recién llegados y desconcertantes para los retocadores experimentados acostumbrados a Lightroom y similares.

Esta será mi última publicación en este sitio web porque me retiro del desarrollo. Me ha costado demasiado : demasiado estrés, demasiados episodios de burn-out, demasiados años arreglando la mierda de otros y sufriendo sus malas decisiones. Estoy cansado más allá de lo que puedas imaginar. Odio programar y odio a los programadores. Conozco muy pocos que programen para construir cosas o para resolver problemas; la mayoría simplemente disfruta demasiado pasando un buen rato con un ordenador, y se convierten en bomberos pirómanos en los que no puedes confiar para diseñar cosas. Odio la tecnología y la llamada “innovación”: todo esto no es más que una estafa capitalista diseñada para el crecimiento infinito en un mundo donde los recursos son limitados, y pretendemos resolver problemas creados por la tecnología con aún más tecnología. Eso es una locura. El mundo del código abierto hereda la misma mentalidad, incluido el tecnosolucionismo , porque ese es el tipo de putrefacción cerebral que producen 350 años de capitalismo, aunque el FLOSS no tenga los beneficios que lo justifiquen. Está lleno de mentiras y lleno de mierda, porque libre significa libertad solo para los ingenieros, y los usuarios que se vayan al infierno. El problema es que yo solía creer en esas mentiras, en esos valores : eran (y siguen siendo) los míos. Pero darme cuenta de que no son más que palabras vacías repetidas en “comunidades” tóxicas de hombres blancos de mediana edad con títulos de ingeniería, máster y doctorado fue un despertar brutal. ¿Qué hacemos de verdad para empoderar a los usuarios que de verdad lo necesitan ? ¿En qué punto exigir a la ligera el uso de la CLI empodera a alguien que no sabe leer código ? Solo estamos contribuyendo a ahondar la brecha entre las élites alfabetizadas informáticamente y los campesinos. Recuerda, aquí estamos haciendo software de fotografía, no una biblioteca de backend, no una infraestructura de servidor, sino una aplicación de escritorio para el usuario final.

He vaciado mi cerebro aquí, para registrar todo lo que he aprendido sobre el diseño de procesamiento de imágenes, cómo lo hice y por qué. Es importante entender que los usuarios, y la mayoría de los desarrolladores, solo saben cómo se comporta una aplicación con sus propias imágenes. Durante 8 años, he recibido muchas imágenes patológicas que la gente me enviaba, mostrando los defectos y limitaciones de las herramientas. Tengo alrededor de 45 GB de esas imágenes en mi disco duro, ahora mismo. Eso da una perspectiva completamente distinta sobre los problemas reales de la que puedan tener todos los campistas felices : yo soy el tipo que sabe qué se rompe y cuándo. Yo soy el tipo al que los problemas encuentran. Yo soy la Casandra  del proyecto. Y es molesto tener que justificar todo el tiempo, ante gente que no ve los problemas, por qué esa cosa que podría ser mucho más simple no puede ser mucho más simple porque hay casos patológicos en los que necesitamos adaptarnos a la variabilidad de la entrada. Para adaptarse a la variabilidad de la entrada, necesitas parámetros de usuario en lugar de constantes codificadas de forma fija. De ahí la sobrecarga de interfaz. El tipo de sobrecarga de interfaz que no puedes evitar sin perjudicar la usabilidad.

No puedes evaluar la calidad de un diseño si no conoces sus requisitos. “Me gusta” o “no me gusta” es irrelevante. A nadie le gusta llevar el cinturón de seguridad, y sigue siendo un buen diseño si consideras cuántas vidas ha salvado. Cualquier crítica real solo puede versar sobre cómo la solución propuesta alcanzó el objetivo, lo cual solo puede ocurrir si conoces el objetivo. En el procesamiento de imágenes, la naturaleza mixta de los requisitos hace difícil evitar sumergirse en las matemáticas y sus jeroglíficos en algún momento, que es donde pierdes a la gente. Pero eso tampoco les impide dar su opinión inútil, empezando por “no soy programador”/“no soy matemático”/“no soy científico del color”… “PERO”… [entra aquí algún ruido cerebral aleatorio]. Hacer código abierto, donde todo es público, permite ese tipo de ruido por todas partes : es realmente agotador, y hay muchas veces en que deseé que el código fuente fuera cerrado, solo para poder trabajar en paz. La mayoría de esos tipos tienen buenas intenciones y solo quieren formar parte de algo, pero contribuir a la sobrecarga de información no ayuda y solo contribuye a crear fatiga. La comunicación es donde todo trabajo en equipo pierde productividad

El diseño no consiste en escuchar lo que a la gente le gusta. Si al 65% de tu panel de pruebas le gusta el texto escrito en rojo, y al 72% le gusta el texto escrito sobre fondo rojo, ¿escribes texto rojo sobre fondo rojo ? No tiene ningún sentido. No estamos haciendo política ni intentando complacer a los votantes durante una campaña, buscamos soluciones a largo plazo y a prueba de futuro para los problemas. El diseño consiste en escuchar lo que la gente necesita, que rara vez puede expresar con claridad, y encontrar maneras de factorizar esas necesidades. Así que las únicas estadísticas que vale la pena calcular son las de los casos de uso : cómo se usa el software, cuáles son los puntos de dolor más comunes, y cuál es su causa raíz. Luego arregla la causa raíz, que puede estar muy lejos de la manifestación real del problema. Eso también es una habilidad real y preciosa : seguir el hilo de la incidencia, a través de pistas e indicios, para descubrir el origen real, y no solo parchear la incidencia final o sortearla. “Escuchar a los usuarios” no significa escuchar a cada individuo y darle lo que quiere individualmente : no estamos ofreciendo terapia. Significa escuchar a toda la base de usuarios, e identificar las necesidades y los puntos de dolor comúnmente compartidos para idear una solución factorizada que cubra el mayor número de necesidades con la menor cantidad de tecnología. Esto no implica descartar a nadie que se desvíe de la media más de una desviación estándar, pero esas personas quizá tengan que recurrir a métodos que no están hechos a medida ni optimizados para sus necesidades.

El diseño no existe en una isla : hay otras aplicaciones de edición de imágenes alrededor. De nuevo, es difícil evaluar cuándo tu diseño debería copiar a otros porque los usuarios estarán acostumbrados a su semántica de interfaz, y cuándo deberías apartarte porque el problema que intentas resolver es demasiado distinto de lo que hace la competencia, o tu usuario típico es demasiado distinto. El código abierto está constantemente desgarrado entre la tentación de copiar 1:1 a los líderes comerciales que tanto odia (pero a los que en silencio aspira a ser), y el ansia de superar a todos en ingenio mientras reinventa la rueda (a menudo de peor manera). En todo eso, tu Estrella Polar es preguntarte, cada hora de cada día : ¿cuál es el problema que intentamos resolver, y quiénes son las personas que lo enfrentan ? Así es como puedes adaptar las cosas a tu audiencia, en lugar de caer en cultos cargo  y adoptar soluciones porque han tenido éxito en un contexto que no entiendes realmente y que no es necesariamente el tuyo.

Mi principal conclusión de todos estos años es que aplicar transformaciones de color a los píxeles en cualquier otro espacio que no sea RGB está condenado al fracaso, como muestra el ejemplo de colorbalance RGB : aunque pueda sonar como una gran idea decorrelacionar el trabajo de “color” (como en tono/croma) del trabajo tonal, nunca será más que una cuestión de elegir tu dolor. Aumentar el croma a claridad constante degrada los colores hacia el fluorescente, aumentar la saturación a brillo constante (oscureciendo por tanto en conjunto) no respeta la teoría de la mezcla de luz, y ambos producen ruido de croma debido a la naturaleza inestable de los ángulos de tono. Pero, por otra parte, RGB no es perceptualmente uniforme, y el rango verdoso de cualquier escala de tono HSL/HSV ocupa aproximadamente el 30 % del espacio, mientras que el verde es solo 1/6 del anillo de tono perceptual. La única solución es manejar la interfaz en modelos de color perceptuales, y convertir, de un modo u otro, a RGB antes de aplicarla a los píxeles. Lo que requiere gimnasia de abstracción adicional para los desarrolladores. Y eso claramente no es su punto fuerte, ya que el nivel matemático es bastante bajo.

Ya tengo un sucesor, pero el futuro de Ansel tendrá que ser una cooperativa donde los usuarios garanticen a los desarrolladores condiciones de trabajo justas, y los desarrolladores garanticen a los usuarios que sus necesidades serán cubiertas, correspondiéndose responsabilidades mutuas. No podemos continuar así, no es sano. Y, por “así”, me refiero, por un lado, al “desarrollador aficionado” con cero responsabilidad, y por el otro, al desarrollador único quemándose y viviendo por debajo del umbral de pobreza para más o menos hacer que las cosas ocurran. Ese paradigma ha dado todo lo que podía, no se puede ajustar. Las mismas causas solo conducirán a las consecuencias que ya conocemos : el código abierto es una porquería. Si quieres más, ese paradigma tendrá que cambiar. El código abierto, por un lado, es una dictadura de los desarrolladores (los que saben y pueden) sobre los usuarios (los que necesitan), pero por el otro, es la explotación de los que trabajan por parte de los que toman. Eso solo alimenta el resentimiento mutuo, el desprecio disimulado y la condescendencia. Todos pierden.

La alternativa es la actual mierdificación de las plataformas corporativas y el tecnofascismo que está habilitando actualmente. Quedas advertido.


Translated from English by : ChatGPT, Claude. In case of conflict, inconsistency or error, the English version shall prevail.

  1. Grignon, Claude. La règle, la mode et le travail : la genèse sociale du modèle des repas français contemporain. In Le temps de manger, édité par Maurice Aymard, Claude Grignon, et Françoise Sabban. Paris: Éditions de la Maison des sciences de l’homme, 1993. doi:10.4000/books.editionsmsh.8155. URL  ↩︎

  2. Ekirch AR. Segmented Sleep in Preindustrial Societies. Sleep. 2016 Mar 1;39(3):715-6. doi: 10.5665/sleep.5558. PMID: 26888454; PMCID: PMC4763365. URL  ↩︎