Introduction

Outils vs. machines, artisanat vs. industrie

Dans son livre La Technique ou l’enjeu du siècle (1954), Jacques Ellul présente ainsi la différence entre l’avant et l’après révolution industrielle :

L’ère préindustrielle est le règne de l’outil et de l’artisanat. La propriété première des outils est d’être génériques, polyvalents et adaptables. Il revient à l’artisan de développer ses compétences pour faire suivre son intention aux outils, de sorte que la main compense les limitations de l’instrument. Ce concept est encore bien connu des musiciens aujourd’hui : il faut s’entraîner, apprendre, essayer, échouer, réessayer… il n’y a pas de raccourcis. Ellul insiste sur l’idée de parcimonie qui accompagne les outils : les ressources sont limitées, si bien que votre outillage est à peu près défini par ce que vous pouvez vous offrir, transporter, maîtriser et fabriquer localement. Les tendances changent lentement et sont locales, parce qu’elles utilisent des ressources locales et s’adaptent à des besoins locaux, et les outils suivent le même schéma. Les outils sont des héritages transmis du maître à l’apprenti, du parent à l’enfant. Ils ne deviennent ni incompatibles ni obsolètes.

L’ère industrielle est le règne de la machine. Elle procède d’une culture de la standardisation et de la massification. La machine est beaucoup plus productive parce qu’elle est spécialisée pour une seule tâche, mais elle est inutile pour tout le reste et peut rarement être adaptée à un autre usage. Lorsque les besoins de production changent, la machine est remplacée par une autre parce qu’elle n’est bonne à rien. Ce n’est plus un schéma parcimonieux, et cela est permis parce que les ressources sont bien moins chères et que la production de masse permet des économies d’échelle. Alors, les humains deviennent les serviteurs de la machine, et l’artisanat devient un luxe.

Des productions qui se faisaient autrefois à la maison ou dans de petits ateliers, dans un cadre familial, sont déplacées vers de grandes usines, où il y a assez de place pour les machines. Cela a d’ailleurs eu des effets très concrets sur la manière dont nous organisons notre vie quotidienne, y compris quand et combien de fois nous mangeons1, ainsi que sur nos habitudes de sommeil2. Il n’est donc pas exagéré de dire que la révolution industrielle a aussi profondément changé notre façon de penser, ce que nous considérons comme normal ou évident.

Cela m’a parlé parce que c’est ainsi que j’avais développé mes outils d’édition de couleur, intuitivement, depuis mes débuts : essayer de construire des outils génériques reposant sur le moins d’hypothèses possible pour rester polyvalents, tout en offrant un contrôle fin sur les paramètres de l’image, et en m’appuyant en définitive sur les capacités de l’artisan plutôt que sur des outils à moitié cassés, non validés, auto-magiques qui ne fonctionnent que dans les cas idéaux.

Photographie numérique : automatiser ou savourer le processus ?

Je n’ai jamais compris la passion de beaucoup de photographes, en particulier les plus technophiles, pour les workflows presse-bouton et les procédures automatisées. J’ai appris et enseigné le piano, et je suis habitué au paradigme shut up and practice (« tais-toi et travaille ») : s’entraîner pour développer et maintenir l’agilité, puis répéter les mêmes quelques mesures encore et encore jusqu’à ce que le son soit juste. Travailler la qualité, la texture et l’expressivité du son, à travers le poids que vous mettez sur les touches, la vitesse de l’attaque, le mouvement du poignet et de l’avant-bras. Utiliser son corps pour des mouvements fins et l’entraîner au-delà de ses capacités actuelles, transformer des gestes très peu naturels en réflexes. Et enfin, apprendre à entendre dans son esprit le son que l’on vise, avant même de bouger les mains. Toutes ces choses ne seront jamais réductibles à des curseurs et des boutons d’interface, à des métriques, des variables ou des algorithmes.

La manière dont beaucoup de photographes abordent l’édition de photos donne l’impression qu’ils ont été punis par la photographie numérique parce qu’ils doivent désormais utiliser un logiciel pour obtenir leurs photos. Cela devrait donc se réduire à une procédure sans âme où tout devrait être automatisé si cela peut l’être. On échange des préréglages et des recettes, certains les vendent même. Et maintenant nous avons l’IA pour imiter tel ou tel style. Où est la joie à industrialiser la création artistique ? Quel est l’intérêt d’avoir un loisir qui ressemble au fardeau de devoir développer ses photos ? L’art est un processus, pas une procédure. Quel esprit malade concevrait un robot qui fait de la poterie, de la gravure ou des compositions florales à votre place ? Et si l’on utilisait le logiciel comme une occasion de peaufiner le rendu de ses images selon son goût et sa sensibilité ? Avons-nous perdu le plaisir brut de faire les choses nous-mêmes, même mal ? À quel âge cet appétit se perd-il ?

Certes, se battre contre un logiciel d’édition de photos est une expérience frustrante, mais il faut comprendre contre quoi vous vous battez. S’agit-il simplement de la difficulté intrinsèque de votre métier et de votre manque de compétences, ou est-ce la mauvaise conception de l’outil ? Quand vous peinez sur un piano à 25 k€ qui vient de voir le technicien piano, vous savez que l’instrument n’est pas le problème. Mais avec un logiciel, comment le savoir ? Eh bien, vous ne le pouvez pas tant que vous ne vous engagez pas pleinement dans le paradigme shut up and practice. Les bons retoucheurs obtiendront de bons résultats avec n’importe quel logiciel, la différence est dans le temps que cela leur prendra. Et, bon, parfois vous devez faire beaucoup de rattrapage pour les modèles de couleur cassés des applications d’édition.

Les outils dans l’interface d’édition de photos

En termes de conception d’interface, la parcimonie d’outils génériques et polyvalents est le meilleur moyen d’éviter d’être submergé par des dizaines de fonctionnalités qui se cachent les unes les autres, se recoupent en fonctionnalité et ne font que polluer votre champ visuel. C’est du feng shui logiciel. Mais alors, la nature des outils se déplace un peu.

Il y a deux façons de penser les contrôles de couleur du traitement d’image : à partir de leur usage fonctionnel, et à partir de la manière dont ils permettent de manipuler les propriétés de la couleur. À partir de leur usage fonctionnel :

FonctionMéthodes
DébruiterFiltrage par ondelettes, moyennes non locales, filtre bilatéral, filtre guidé, diffusion,
DéfloueurDéconvolution de Richardson-Lucy, pyramide gaussienne/laplacienne, filtre passe-haut, filtrage par ondelettes, contre-diffusion, masque flou
FlouterFiltrage par ondelettes, diffusion, filtre bilatéral, filtre guidé
ÉclaircirCorrection d’exposition, courbe de tonalité, fonction de transfert puissance (« gamma »), mélangeur de canaux
Balance des blancsNormalisation canal par canal, transformation d’adaptation chromatique, mélangeur de canaux
Décalage de couleurMélangeur de canaux, lift-gamma-gain, slope-offset-power, rotation de teinte, LUT
Rehaussement de la colorationSaturation, chroma, vibrance, LUT
Rehaussement du contrasteCourbe de tonalité, fonctions de transfert sigmoïdales, normalisation de plage (« niveaux »), LUT
Compression de la plage dynamiqueComme le contraste, mais en mode « réduction » au lieu du mode « augmentation »

Notez que le décalage de couleur pourrait être redécoupé en deux modes : correctif (qui appelle des modèles de lumière) et créatif (qui appelle des modèles perceptuels). Nous n’irons pas jusque-là.

Si l’on aborde la même liste par l’autre point d’entrée, la manière dont ils permettent de manipuler les propriétés de la couleur, on obtient :

MéthodeFonctions
Filtrage par ondelettesDébruiter, Défloueur, Flouter
DiffusionDébruiter, Défloueur, Flouter
Mélangeur de canauxÉclaircir, Décalage de couleur, Balance des blancs
LUTRehaussement du contraste, Décalage de couleur, Rehaussement de la coloration
Courbe de tonalitéÉclaircir, Rehaussement du contraste, Compression de la plage dynamique

Je n’ai pas refait toute la liste mais vous avez saisi l’idée : que vous vouliez classer votre liste d’outils par méthode ou par fonction, vous n’aboutissez pas à une correspondance 1:1, sauf pour quelques-uns. Aucune de ces mises en correspondance ne vous permet donc de factoriser systématiquement vos outils en éléments d’interface unitaires, de manière à honorer le principe de parcimonie.

Et puis, le traitement d’image n’est pas seulement un ensemble d’outils dans une boîte, c’est en réalité un pipeline de filtres de pixels qui doivent être insérés comme des nœuds de graphe dans un ordre qui correspond aux exigences d’entrée des filtres. Voilà (simplifié) :

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)

Et, enfin et surtout, le problème que personne ne voit : les maths. Par exemple, un filtre guidé appliqué à un masque d’opacité et guidé par l’image RGB (comme dans le raffinement de masque d’Ansel/Darktable) n’a pas les mêmes maths qu’un filtre guidé appliqué à un masque de luminance et guidé par lui-même (comme dans l’égaliseur de tonalité), ou qu’une image RGB complète guidée par elle-même (comme dans le voile). Ceux-ci doivent être implémentés plusieurs fois, avec différents types d’entrées et différents types d’optimisations. Il en va de même pour les méthodes travaillant sur des images non dématricées : nous devons tenir compte du fait que nous n’avons pas un signal RGB complet à chaque sensel, et les matrices XTrans nécessitent des maths spéciales différentes de Bayer.

Donc, étant donné que :

  1. les fonctionnalités ont différentes méthodes,
  2. les méthodes ne peuvent pas être réduites à une seule fonctionnalité,
  3. toutes sont insérées comme des nœuds dans un pipeline où l’ordre compte,
  4. les méthodes ont des variations d’implémentation selon leur signal d’entrée, c’est-à-dire leur position dans le pipeline,
  5. les utilisateurs veulent s’amuser sans avoir à apprendre quoi que ce soit,
  6. l’encombrement de l’interface ne sert personne et fatigue tout le monde,

…nous avons un problème : comment découper les fonctionnalités et les organiser en une interface cohérente ?

Dans un contexte professionnel, où l’on peut attendre des utilisateurs qu’ils sachent construire un pipeline par eux-mêmes et comprennent les tenants et aboutissants de ses nœuds, vous pouvez suivre la voie de DaVinci Resolve et construire un éditeur nodal. Vous construisez alors un nœud par méthode, et gérez en interne les variantes d’implémentation en vérifiant le type de signal d’entrée. C’est la manière la plus minimaliste, parce qu’il n’y a aucune duplication d’interface : juste une banque de nœuds, et les nœuds peuvent être placés en parallèle plutôt que forcés séquentiellement. Mais cela requiert des utilisateurs experts.

La voie de Lightroom/Capture One consiste à cacher complètement qu’il existe même un pipeline, et à fournir une interface plate. La multi-instanciation des nœuds se fait alors à travers les masques : ajouter de nouveaux masques vous permet de leur assigner un sous-ensemble des contrôles du logiciel pour éditer sélectivement les régions masquées. Mais cela s’accompagne aussi du fait qu’aucune de ces applications ne permet l’édition linéaire scene-referred, ce qui rend le floutage, le défloutage, le débruitage et les transitions de masque réelles bancals.

Ansel est sur une voie médiane. D’abord, il y a désormais un prototype d’éditeur nodal :

image
image

Cela nous permet de montrer explicitement l’ordre du pipeline, de le réordonner manuellement et de changer de préréglages d’ordonnancement, d’une manière qui montre aussi les entrées et les sorties. Auparavant, nous n’avions que la pile de modules d’interface dans la barre latérale droite, qui suggérait en quelque sorte l’ordre du pipeline si on la lisait comme une pile de calques, mais elle était souvent détournée par les utilisateurs comme une simple commodité de réordonnancement de la boîte à outils de l’interface.

Et ensuite, le découpage des fonctionnalités est hybride :

  • Les modules égaliseur de contraste, contraste local et diffusion ou netteté sont intrinsèquement doubles par nature : ils peuvent augmenter ou diminuer le contraste local et la netteté selon leurs paramètres. L’égaliseur de contraste possède même une méthode de débruitage, ce qui est logique car l’accentuation de la netteté augmente le bruit, si bien que le bon endroit pour le maîtriser est là où il est créé. Ce sont des modules orientés méthode.
  • La balance des blancs duplique la fonctionnalité de la partie adaptation chromatique de la calibration des couleurs. La balance des blancs est une simple normalisation canal par canal qui se produit dans le RGB du capteur, et elle est nécessaire à certaines méthodes de dématriçage (en particulier pour les capteurs XTrans), tandis que la calibration des couleurs effectue une compensation d’illuminant bien plus perceptuellement précise dans l’espace CIE CAT16. Cet espace est défini à partir de l’espace CIE XYZ 1931, que l’on n’obtient qu’après le profilage colorimétrique d’entrée (et cela nécessite une image dématricée pour fonctionner). Il y a des raisons et des besoins différents pour les deux, et ils doivent se situer à des endroits différents du pipeline. Ce sont des modules orientés pipeline : bien qu’ils semblent fonctionnellement similaires, leurs raisons d’exister et leurs exigences internes (et des maths complètement différentes) les rendent bien plus différents que vous ne pourriez le penser. Il en va de même pour les divers modules de débruitage : certains travaillent sur l’entrée RAW, d’autres non, et certains fonctionnent mieux sur des signaux non linéaires.
  • La balance des couleurs a été conçue comme un module de couleur tout-en-un, appliquant une ASC CDL  étendue (slope-offset-power), puis gérant la saturation et le chroma globaux et selon la luminance, remplaçant ainsi les anciens modules de Darktable comme contraste-luminosité-saturation, vibrance et velvia (tous travaillant en CIE Lab 1976). Pris isolément, c’est un module orienté fonctionnalité, mais ce n’est pas le seul module de décalage de couleur. Les autres modules de décalage de couleur utilisent des méthodes très différentes (matrices, LUT ou contrôles selon la teinte), qui sont 3 à 9 fois moins coûteuses en calcul à exécuter, et opèrent dans différents espaces colorimétriques.

Ansel hérite son concept de modules de Darktable : les modules sont à la fois un widget de boîte à outils d’interface et un filtre de pixels inséré quelque part dans le pipeline. Ainsi, concevoir de très petits modules (en termes de fonctionnalités) fera apparaître beaucoup de widgets d’interface de haut niveau dans la barre latérale droite, tandis que concevoir de très grands modules produira moins de widgets de haut niveau mais ils seront plus hauts ou utiliseront davantage d’onglets internes. La seconde option pourrait tout de même être préférable car les modules d’interface de haut niveau agissent comme des plateaux, si bien que moins de plateaux fonctionnellement cohérents aident à mieux comprendre le découpage des fonctionnalités de haut niveau (comme une table des matières).

Mais cela ne s’arrête pas là, parce que, encore une fois… les nœuds. Un module devrait être un ensemble de contrôles de couleur cohérents en tant que nœud masqué et multi-instancié dans le pipeline. Il n’est pas judicieux de bourrer un module de dizaines de fonctionnalités dont la moitié n’ont de sens qu’en tant que réglages globaux, et le reste seulement dans la localité du masque ; elles ne feront que consommer des cycles CPU pour rien une fois instanciées.

Et enfin, il y a la performance. Les contrôles de couleur qui doivent travailler dans un espace colorimétrique particulier nécessiteront une conversion colorimétrique aller-retour, qui consommera des cycles CPU, il vaut donc mieux qu’ils s’exécutent tous dans le même module s’ils ont du sens ensemble sur le plan fonctionnel. De plus, tout nouveau module exécutera une nouvelle boucle sur les pixels, ce qui signifie qu’il déplacera l’image une fois de plus dans le cache mémoire du CPU depuis/vers la RAM. Ainsi, regrouper les fonctionnalités dans la même boucle évite un abus supplémentaire de bande passante d’E/S et aide à la performance.

Donc, si l’on récapitule toute la liste des contraintes, ici, c’est un défi vraiment difficile à résoudre :

  1. nous devrions toujours nous efforcer de construire le moins d’éléments d’interface possible, car une interface encombrée rend tout difficile à trouver (et cognitivement accablant) : le meilleur endroit pour cacher un arbre, c’est la forêt,
  2. l’encombrement que nous construisons devrait être organisé du global au local, du générique au spécifique, du fréquemment utilisé au niche, parce que c’est la manière la plus facile de raisonner : penser la structure de l’interface comme une « table des matières » est ce que j’ai trouvé de mieux jusqu’à présent,
  3. mais faire une règle de découper systématiquement les fonctionnalités selon la fonctionnalité ou selon la méthode aboutit tout de même à des duplications dans les deux cas, à moins d’aller dans la direction de l’éditeur entièrement nodal, de tout faire à base de méthodes, et de reporter la responsabilité de construire les pipelines sur l’utilisateur expert,
  4. les modules devraient être conçus comme orientés fonctionnalité dès que possible, mais beaucoup de limitations s’appliquent :
    1. le type de signal d’entrée, qui détermine la position dans le pipeline, et peut nous forcer à prioriser l’orientation pipeline et à dupliquer des outils,
    2. la pertinence et la cohérence de l’ensemble des contrôles du module lorsqu’il est multi-instancié et masqué : un module devrait être une unité cohérente de workflow d’édition, pas un fourre-tout pour tout entasser. En particulier, si cela a du sens (du point de vue du workflow) d’appliquer un masque sur seulement un sous-ensemble des fonctionnalités du module, alors ce sous-ensemble devrait être son propre module,
    3. les problèmes de performance (aller-retour d’espace colorimétrique, mapping de gamut de la sortie, bande passante d’E/S) : on ne peut pas penser l’ergonomie utilisateur uniquement du côté de l’interface ; la vitesse d’exécution fait aussi partie de l’ergonomie,
    4. la nature mathématique des opérations réalisées : certaines méthodes (en particulier accentuation de la netteté/contraste local) peuvent avoir des effets opposés selon le signe de leurs paramètres, certaines méthodes se prêtent mal à être regroupées dans le même filtre de pixels,
  5. enfin, il faut prendre en compte le nombre de clics/étapes de défilement nécessaires pour atteindre une fonctionnalité fréquemment utilisée, parce que l’axe générique -> spécifique n’est pas toujours parallèle à l’axe fréquemment utilisé -> niche. Ainsi, si l’organisation de haut niveau générique -> spécifique a du sens sur le plan cognitif, ce n’est pas toujours la plus ergonomique.

Toutes ces exigences antagonistes doivent être arbitrées au cas par cas, en regardant l’intégralité du pipeline, sinon nous ne construisons pas une application de workflow mais un registre de plugins. Elles vivent au carrefour de la programmation bas niveau, des maths, du workflow de retouche et de l’ergonomie d’interface, et aucun de ces concepts n’est en général plus important que les autres. Cependant, certaines de ces contraintes sont plus faciles à comprendre que d’autres, ce qui leur fera recevoir bien plus d’attention, dans un effet réverbère  typique : continuer à traquer les problèmes dans la couche que vous comprenez tout en écartant complètement leur véritable origine parce qu’elle touche une couche que vous ne comprenez pas / dont vous ne savez rien. C’est pourquoi c’est un vrai casse-tête de travailler avec des « UX designers », parce qu’ils n’ont typiquement pas le bagage pour regarder au-delà de l’interface et ne se soucient souvent pas qu’il y ait un moteur à contrôler sous l’interface. On ne peut pas simplement choisir d’annuler la gravité parce qu’on aimerait retirer le contrôleur de tangage  pour une interface plus simple.

La conception est un processus de raffinements itératifs sous les retours des utilisateurs. Certaines de ces itérations redessineront du macro au micro (de l’architecture globale de l’application aux contrôles internes des modules), et certaines redessineront du micro au macro, jusqu’à ce que cela converge vers une sémantique unifiée et un découpage cohérent des fonctionnalités. Il est insensé de croire que quiconque y parviendra du premier coup, ou de croire qu’un seul des niveaux micro/macro a besoin d’être corrigé. C’est un pont à construire par les deux extrémités en même temps, et à trouver un moyen de les faire se rejoindre au milieu.

Les propriétés de bons contrôles de couleur

Fort de mes 17 ans d’expérience dans l’édition d’images, et de 8 ans d’expérience dans l’étude et l’expérimentation des maths du traitement d’image, il y a un certain nombre de choses que j’ai apprises sur ce qu’est un bon ou un mauvais contrôle de couleur. Par « contrôle de couleur », j’entends une manière de transmettre une intention utilisateur à un algorithme de pixels qui va éditer une propriété visuelle d’une image. De bons contrôles de couleur :

  1. sont orthogonaux les uns aux autres, ce qui signifie qu’un contrôle change une dimension de couleur à un instant donné et ne vous force pas à compenser sur un autre contrôle,
  2. ont une échelle uniforme d’un point de vue perceptuel, ce qui signifie que passer de « 0 » à « 1 » changera le résultat visuel de la même quantité que passer de « 1 » à « 2 ». Ce n’est malheureusement pas toujours possible, parce que les maths et la physique vous détestent.
  3. passent gracieusement à l’échelle à mesure que la plage dynamique augmente, ce qui écarte à peu près tous les modèles d’apparence de couleur (CIE Lab 1976, CIECAM 16, dt UCS 22), conçus pour le SDR sur des jeux de données enregistrés pour des pastilles de couleur peintes.
  4. se dégradent gracieusement à mesure que l’on augmente l’ampleur des changements, ce qui signifie qu’ils peuvent être trop poussés mais ne peuvent pas changer le contenu de l’image ni créer d’artefacts,
  5. préservent les gradients de l’image, ce qui signifie qu’ils conservent les variations locales tonales et chromatiques en tant que variations, au lieu de les aplatir, de les faire déborder (créant des halos, des franges, du bruit, etc.) ou de les inverser.
  6. permettent aux artistes de se rapprocher le plus possible de leur intention en le moins de temps possible.
  7. ne sont pas dupliqués.

Du point 1., on déduit par exemple que tout type de courbe de tonalité RGB est mauvais, parce qu’elle désaturera les hautes lumières et saturera les ombres comme sous-produit de la quantité de contraste (de luminance) que vous avez ajoutée, et vous ne pouvez pas contrôler (ni décorréler) la quantité de changement de saturation que vous obtiendrez pour la quantité de changement de contraste demandée, sauf par des bidouilles comme la préservation des ratios RGB ou en massant manuellement la saturation/désaturation à travers l’application de la courbe de tonalité. C’est la raison d’être de l’égaliseur de tonalité, qui corrige le contraste en utilisant un ajustement d’exposition sélectif au lieu d’une courbe de tonalité.

Du point 2., on déduit que les contrôles d’interface devraient utiliser des modèles d’apparence de couleur dès que possible.

Du point 3., on déduit que les modèles d’apparence de couleur utilisés dans l’interface ne devraient pas être utilisés sur les pixels mais devraient être convertis de sorte que les pixels soient traités en RGB. C’est un paradigme modèle-vue-contrôleur  typique qui est systématiquement ignoré dans toutes les applications de traitement d’image. Apparemment, il existe une croyance chez les développeurs selon laquelle le modèle de couleur des pixels devrait correspondre 1:1 à l’espace colorimétrique du contrôleur de l’interface.

Du point 4., on déduit que les contrôles qui ne sont pratiquement utilisables que sur un petit sous-ensemble de leur plage de valeurs utilisent de mauvaises maths, de mauvais modèles de couleur, de mauvais a priori. Les modes de défaillance sont tout aussi importants que ce qui se passe lorsqu’on utilise les contrôles dans leur zone optimale.

Du point 5., on confirme simplement le point 3.

Du point 6., on a soulevé un nouveau problème : beaucoup de photographes n’ont pas d’intention de retouche/édition (au sens de : un but visuel final), mais ne font que pousser et tirer des curseurs dans la direction qui semble rendre l’image plus jolie, et finissent avec un heureux hasard qu’ils seraient incapables de reproduire (ou abandonnent l’image faute de pouvoir la travailler). Dans ce cas, il n’y a pas de métrique de succès pour les contrôles parce qu’il n’y a pas de différence à calculer entre intention et résultat, puisque l’intention est indéfinie. C’est pourquoi, lorsqu’on travaille avec les retours des utilisateurs, il faut être critique et se demander qui parle et d’où. C’est-à-dire : tout retour utilisateur n’est pas un bon retour utilisateur (et des années d’expérience ne sont en elles-mêmes preuve de rien).

Et le point 7. n’est qu’un rappel de la section précédente : devoir dupliquer un réglage est généralement le signe d’un mauvais découpage des fonctionnalités, ou bien vous devez avoir une bonne raison de le faire.

Tout cela constitue évidemment les cas idéaux vers lesquels tendre. En pratique, vous devez évaluer différents candidats et choisir le meilleur, qui répondra rarement à toutes les exigences. Mais pour évaluer des candidats concurrents, vous avez d’abord besoin de points de contrôle et d’échelles objectifs. Ce sont là les points de contrôle qui me sont devenus évidents au fil des années.

Les propriétés de bons workflows d’édition

Je me souviens de chaînes d’e-mails interminables, il y a 9 ans sur la liste de diffusion de Darktable (aujourd’hui disparue), concernant la meilleure façon de réorganiser l’interface, dans lesquelles on me disait : « il n’y a pas de bon ou de mauvais workflow, seulement des préférences personnelles ». Le relativisme absolu est toujours plus bête qu’il n’en a l’air. Cette stupidité se poursuit désormais sur discuss.pixls.us. Ce sont vraiment les mêmes discussions, disant les mêmes choses sur les mêmes problèmes, tournant en boucle depuis plus de 9 ans, et toujours aucune solution tangible.

Il y a d’abord le cas évident où vous définissez un masque paramétrique sur, disons, color balance RGB, et le réglez pour masquer-vers-l’intérieur les valeurs RGB comprises entre telle et telle + epsilon. Puis, vous êtes satisfait des couleurs, mais votre image paraît un peu sombre, alors vous allez augmenter l’exposition. Maintenant votre masque paramétrique est invalide et vous devez le refaire, parce que l’exposition se situe plus tôt dans le pipeline que color balance RGB, si bien que vous avez décalé toute votre plage de valeurs de code RGB. C’est de l’édition circulaire, c’est la perte de temps la plus évitable, et si vous voulez l’éviter, il n’y a pas beaucoup de choix : vous devez faire attention à l’ordre de votre pipeline. L’édition circulaire est un workflow objectivement mauvais. Ai-je besoin de le justifier ?

Cela ne s’arrête pas aux masques, parce que beaucoup de modules de couleur ont besoin de normaliser le blanc HDR pour pouvoir utiliser des modèles de couleur qui ne peuvent fonctionner qu’avec l’hypothèse que blanc = {1, 1, 1}. C’est pourquoi je place ceux-ci plus tard dans le pipeline, après les ajustements globaux de luminosité et de contraste.

Et puis, il y a le cas de l’édition par lot : vous avez une série d’images à éditer, vous voulez qu’elles aient un aspect cohérent tout au long de la série, mais elles présentent des variations mineures d’éclairage, de contraste et de température de couleur. La seule façon de faire fonctionner cela est d’avoir une première étape de normalisation de l’image, pour gérer les variations individuelles des images et les convertir vers un état constant. Une fois cela fait, vous pouvez appliquer par lot le même style ou copier-coller par-dessus l’historique des modules ultérieurs, parce que cette étape suivante recevra des entrées « constantes » normalisées et devrait donc produire des sorties cohérentes (sinon constantes). Ne pas parvenir à cette première étape de normalisation rendra la suivante complètement peu fiable et imprévisible, ce qui défera le but de l’édition par lot. Et même avec ce workflow apparemment rigide, vous finirez tout de même par devoir faire des réglages fins individuels si vous voulez vraiment des résultats cohérents. Ce n’est pas mon opinion, c’est un simple fait : si vous voulez des sorties cohérentes pour un ensemble de modifications d’image avec des réglages rigides, vous avez besoin d’entrées cohérentes.

Mais il y a une limite à cela, parce que lorsqu’on travaille sur un signal HDR, vous devez configurer votre tonemapping HDR -> SDR tôt, afin de pouvoir réellement voir ce que vous faites dans votre image, sans écrêtage des hautes lumières. Il y a donc une première étape consistant à prendre une vue d’ensemble de votre contenu, puis une étape consistant à finaliser les bornes de la plage dynamique. Ce qui signifie que vous devriez toujours d’abord configurer l’exposition globale, en regardant les tons moyens (et rien d’autre), puis configurer votre tonemappeur de travail pour l’instant. Cette règle qui consiste à essayer d’ancrer votre workflow 1:1 sur l’ordre du pipeline (lui-même ancré sur les exigences d’entrée des modules) comporte donc quelques exceptions et ne peut pas être appliquée sans discernement.

Ce qui signifie que vous auriez dû apprendre tout cela. Les bons workflows viennent de gens qui ont réfléchi à la manière de s’adapter aux outils qu’ils utilisaient, en les regardant à la fois du point de vue pratique et du point de vue théorique, et non des joyeux campeurs qui ont pris pour un workflow toutes les habitudes mal construites qu’ils ont adoptées au fil des ans. Encore une fois, il se passe des choses sous la surface de l’interface, nous n’écrivons pas des lettres dans un traitement de texte. Depuis plus de 9 ans, je crie en boucle sur les forums : C’EST UN PIPELINE, PAS UN ENSEMBLE DÉCONNECTÉ DE CONTRÔLES D’IMAGE ALÉATOIRES. L’ordre compte. S’il n’y a qu’une seule chose que vous comprenez dans tout ce blabla, ce devrait être celle-ci.

Et je pense que Lightroom a fait beaucoup de dégâts aux attentes et à la compréhension des utilisateurs en cachant son pipeline interne. Mais ça marche pour Lightroom parce que cela retire beaucoup de degrés de liberté aux utilisateurs. Darktable a réutilisé beaucoup de la sémantique d’interface de Lightroom tout en proposant graduellement plus de liberté et de contrôle direct sur les nœuds du pipeline (en introduisant au fil des ans le masquage par module, puis la multi-instanciation des modules et le réordonnancement relatif des instances, puis les masques raster réutilisables entre modules non consécutifs, et enfin le réordonnancement complet des modules), ce qui a désorienté les habitués comme les nouveaux venus.

L’idée d’un pipeline n’est même pas spécifique à la photographie numérique. La peinture à l’huile a aussi une sorte de pipeline, où vous commencez par préparer votre support, l’enduisez d’un apprêt pour le rendre moins absorbant, puis posez les contours, puis préparez le fond, puis superposez vos glacis  et enfin appliquez la couche de vernis. Personne de sensé ne commencerait par le vernis et ne finirait par l’apprêt. La photographie argentique a évidemment un pipeline de bains chimiques, de minuteurs, etc. Et les applications de peinture comme Photoshop, Gimp ou Krita ont un pipeline explicite, matérialisé par des calques qui s’occultent les uns les autres, du bas vers le haut, avec des calques d’effet qui ne sont rien d’autre que des filtres de pixels paramétriques produisant des sorties dynamiques.

Mais, d’une manière ou d’une autre, le logiciel d’édition de photos raw donnant l’impression d’être déconnecté des réalités matérielles, il semble acceptable en numérique de travailler sans structure ni méthode. Le workflow d’édition « non destructif » a peut-être aussi été interprété librement comme du YOLO  ici, ce qui n’aide pas non plus. Ce n’est pas parce que vous avez Ctrl+Z que tout devient soudain indulgent.

Pour résumer, les bons workflows d’édition sont ceux qui vous donnent des résultats prévisibles à chaque étape tout en évitant l’édition circulaire. Ils doivent être informés par l’ordre du pipeline, mais ils ne peuvent pas s’y coller 1:1 tout le temps, et vous devez faire preuve de jugement pour distinguer quand vous coller au pipeline et quand vous en écarter. Cela laisse très peu de place aux préférences personnelles.

L’éthique du traitement d’image numérique

À l’époque de l’argentique, les artistes travaillaient avec des supports physiques, et pouvaient réaliser toutes sortes de bidouilles et trouver de nouvelles techniques pour obtenir des résultats sur mesure. C’était accessible parce que vous pouviez toucher physiquement le support avec lequel vous travailliez. Les artistes étaient libres.

L’art numérique est intrinsèquement violent, dans la mesure où il a retiré la liberté aux artistes : désormais ils ne peuvent plus trouver de nouvelles techniques par eux-mêmes, parce que leur art existe sous forme d’information pure dans la mémoire d’un ordinateur, si bien qu’ils sont limités à ce que les applications proposent, et peuvent soit supplier les éditeurs/développeurs de logiciels de prendre en compte leurs besoins, soit apprendre à coder et les coder eux-mêmes (ce qui représente un sacré droit d’entrée si vous n’avez aucune formation technique en sciences appliquées ou en informatique). La perte de liberté peut être masquée par le fait que tout ce qui est fait dans un logiciel est réversible, de sorte que les photographes n’endommagent pas les négatifs de façon permanente, par exemple. Pire, le logiciel peut vous rendre plus productif, c’est donc un gain net d’un point de vue commercial. Mais cela ne devrait pas cacher le fait que les artistes sont placés dans une position de consommateur plus passive qu’auparavant, et dominés par ceux qui savent et veulent coder pour eux, qui décident de la manière dont ils feront de l’art désormais.

« Violence », « suppression de la liberté », « domination »… Vous savez où cela mène : cela s’appelle l’oppression. Une oppression sexy qui vous promet d’obtenir des résultats professionnels en quelques clics sans avoir à aller à l’école de photographie. Ou, dans le contexte du logiciel libre, une oppression qui semble bienveillante et inoffensive parce que rien à payer et confidentialité des données intégrée. Mais rien de tout cela n’est incompatible avec le fait que, nous, les développeurs, contrôlons ce que vous avez le droit de faire dans/à vos images, ou non, parce que nous contrôlons le code. Non parce que nous avons été élus par les utilisateurs, non parce que nous sommes compétents pour la tâche en question (à ce stade, j’ai démontré de nombreuses fois ici que l’« équipe » de Darktable n’était qu’une bande d’idiots incompétents avec trop de temps libre), juste parce que nous avons des droits d’administration sur un dépôt Github. Cela nous donne du pouvoir, et le pouvoir s’accompagne de responsabilité.

Cela me trotte dans la tête depuis plusieurs années maintenant, parce que cela devient aussi un dilemme éthique (en plus de tous les dilemmes techniques mentionnés précédemment) de décider quelles fonctionnalités ajouter, ou retirer, ou refactoriser. En même temps, essayer de plaire à tout le monde n’est pas possible et finirait par submerger tout le monde avec des tas d’outils de niche qu’ils n’utiliseront jamais (encore une fois : cacher un arbre dans la forêt). Ensuite, c’est aussi plus de code à maintenir, donc plus de travail et un fardeau pour les mainteneurs à l’avenir, avec plus de menaces pour la stabilité du logiciel. Construire un couteau suisse qui est constamment à moitié cassé ne va aider personne.

Mais il reste que retirer des contrôles pour le seul bénéfice de simplifier l’interface pourrait bien revenir à retirer de la liberté, si nous ne sommes pas sûrs qu’une fonctionnalité similaire continue d’exister, d’une manière ou d’une autre, dans le logiciel. La liberté artistique n’est pas une marchandise, c’est une nécessaire bouffée d’air frais dans des sociétés qui dérivent de plus en plus vers le (techno-)fascisme, une fois de plus.

Encore une fois, tout cela doit être arbitré au cas par cas. Laisser les applications de traitement d’image partir dans toutes les directions à la fois, en essayant d’accommoder tous les besoins dans une seule application, même les plus singuliers, va construire des moutons à cinq pattes impraticables pour quiconque. Ce qui nous ramène à ma première section : construire des outils génériques, polyvalents et sans hypothèses, qui peuvent être adaptés à de nombreux besoins différents de manière factorisée. Industrie vs. artisanat.

La productivité s’obtient par la spécialisation (qui, combinée à la standardisation, débloque l’automatisation), la spécialisation s’obtient par la duplication, la duplication crée du gonflement et de l’encombrement de l’interface, le gonflement et l’encombrement sont les ennemis de l’UX et de la créativité. La conclusion de tout cela est : choisissons ce qui vaut la peine d’être spécialisé, et entravons ainsi la liberté des utilisateurs. Par conséquent, la productivité est le mauvais paradigme : sa conclusion naturelle est l’oppression.

L’opposé de la productivité est la robustesse et la polyvalence. C’est peut-être plus lent (l’est-ce vraiment ?), mais nous pouvons gérer une plus grande variété de cas avec le même nombre d’outils, sans retirer arbitrairement des options, et donc la liberté de l’utilisateur. Le concept de robustesse a déjà été développé dans le contexte de l’instabilité sociale et climatique par Olivier Hamant, dans son livre Antidote au culte de la performance. La robustesse du vivant (2024). L’un de ses principaux enseignements est que le culte de la performance (ou de l’efficacité) ne mène qu’à la compétition, qui promeut la violence, et que dans les temps instables à venir, nous avons besoin de coopération. Dans une société qui produit plus qu’assez pour couvrir les besoins de tous (mais le distribue mal), la performance ne nous rapporte rien d’autre que plus de profits (encore une fois, mal distribués). Mais ce qu’elle produit à coup sûr, c’est le burn-out, à la fois chez les gens et dans les écosystèmes.

En informatique, le burn-out peut provenir de plusieurs choses :

  1. le technostress  lié à trop d’applications, d’outils, de standards et de paradigmes auxquels s’adapter,
  2. la surcharge informationnelle , liée à une pléthore de widgets d’interface et d’outils à parcourir,
  3. la fatigue du changement  liée à des mises à jour trop fréquentes qui changent les workflows.

Pour résumer, la course à la performance se traduit en cascade par une série d’inconvénients :

  1. d’un point de vue technique, cela signifie devoir construire des outils plus spécialisés encombrant l’interface, ce qui produit une surcharge informationnelle,
  2. d’un point de vue UX, garder l’encombrement et la surcharge raisonnables implique de choisir arbitrairement quels besoins seront couverts (probablement ceux de la majorité) et quels besoins seront ignorés, ce qui revient à retirer la liberté artistique à quiconque dévie trop du courant dominant : c’est une première dans l’histoire de l’art, et aucune quantité de liberté logicielle ne la rend moins violente,
  3. d’un point de vue marketing, seuls les professionnels ont besoin de productivité, et pour l’instant ils semblent préférer les logiciels commerciaux en grande majorité. Il n’y a aucun bénéfice pour l’open-source à aller « conquérir de nouveaux marchés », il devrait plutôt s’efforcer de couvrir les niches laissées pour compte. Et aussi, la photographie professionnelle meurt lentement depuis les années 1980, donc je ne suis pas sûr qu’elle restera un marché substantiel encore bien longtemps.

C’était une longue introduction, mais dans un monde où tout le monde pense pouvoir être designer, il est nécessaire d’énoncer complètement la liste entière des exigences de conception antagonistes afin de calmer ceux qui pensent être le prochain Léonard de Vinci, et de leur faire sentir que l’idée simple qu’ils ont eue ne semble brillante que parce qu’ils n’ont pas la note de spécification complète. J’en ai eu bien trop dans ma boîte mail et sur mes gestionnaires de tickets.


Comment cela est géré dans Ansel

Toutes les captures d’écran ont été réalisées sur un ordinateur portable de 15,6’’.

Présentation générale des modules

Tout d’abord, rappelons comment la présentation générale de la chambre noire a été refaite :

image
  • les onglets de modules ont reçu des noms explicites au lieu d’icônes cryptiques,
  • les onglets sont ordonnés (de l’extérieur) dans l’ordre de workflow suggéré, de gauche à droite, si bien que les utilisateurs n’ont qu’à suivre l’interface comme un guide,
  • à l’intérieur des onglets, les modules sont ordonnés dans l’ordre du pipeline (avec une logique de calque « au-dessus », de bas en haut), qui est aussi l’ordre de workflow généralement conseillé. Le nouvel onglet « basique » fait exception, comportant des sections de modules : à l’intérieur des sections, les modules sont ordonnés selon le pipeline, mais les sections elles-mêmes sont ordonnées selon le workflow (encore une fois, logique de calque « au-dessus », donc de bas en haut),
  • l’onglet « pipeline » ou le graphe nodal d’ordre des modules lève toute ambiguïté et montre une vue directe des nœuds du pipeline sans réordonnancement intermédiaire,
  • les onglets « favoris » ont été entièrement supprimés, car ils ne prétendent résoudre le gonflement qu’en en ajoutant davantage.

Parallèlement, les barres d’outils centrales ont été entièrement supprimées, libérant un maximum d’espace pour les images en portrait, sur les écrans 16:9 et 16:10 où l’espace vertical est vraiment plus précieux que l’horizontal. L’utilisation d’un menu global a de nouveau permis de retirer beaucoup de boutons-icônes étranges des barres d’outils, et de les remplacer par des éléments de menu textuels et explicites. Ainsi, en mode plein écran, vous ne perdez désormais que la hauteur de la barre de menu globale :

image

Les options de fusion et de masquage, étant unifiées entre les modules, ont été déplacées vers la barre latérale gauche. Cela libère beaucoup d’espace vertical pour les modules, réduisant le besoin d’onglets internes et évitant beaucoup de clics de-ci de-là. Notez que les options de fusion sont actuellement en cours de réécriture, après que l’API de masque a été entièrement refactorisée, simplifiée et étendue, il ne s’agit donc que d’une vue temporaire.

Les vues d’Ansel sont assez verbeuses, aussi, pour aider à distinguer entre le texte constant (les libellés) et les variables (les valeurs), une coloration syntaxique a été introduite :

  • les libellés constants sont en blanc,
  • les valeurs variables sont en orange.

Calibration des couleurs

Dans calibration des couleurs, les 3 onglets R, G et B ont été fusionnés dans le même onglet mélangeur, qui tient désormais entièrement verticalement. Il en va de même pour luminosité, coloration et N&B qui sont maintenant fusionnés dans sorties.

L’onglet mélangeur a désormais 2 modes d’interface alternatifs, en plus du mode habituel (désormais baptisé complet) ;

La vue primaires a été reprise dans le Darktable amont, sauf qu’ils en ont fait un module autonome, ce qui est stupide : les maths internes des pixels sont exactement une multiplication matricielle 3×3, ce qu’est aussi la calibration des couleurs, il n’y avait donc pas besoin d’un module supplémentaire. C’est encore un problème résolu dans la mauvaise couche : il fallait une couche d’interface supplémentaire dans un module existant, ils en ont fait un module dupliqué.

À la place, Ansel l’implémente comme une couche d’interface graphique, ce qui signifie que les paramètres typiques du mélangeur de canaux sont convertis dans les deux sens vers les paramètres de la vue par primaires, et que les mathématiques pixel du module n’ont pas changé depuis 2021. Pour obtenir une transformation entièrement inversible depuis la matrice 3×3 vers la vue par primaires, il a fallu ajouter un paramètre supplémentaire de gain afin de refermer mathématiquement la transformation.

La vue simple est quelque chose que je laissais mijoter depuis plusieurs années : ré-exprimer les paramètres peu conviviaux du mélangeur en termes de rotation de teinte, d’étirement du plan de chroma (contraste de couleur) et de redimensionnement achromatique. L’étirement U/V remplace l’ancien module Darktable contraste de couleur qui travaille en CIE Lab 1976, et poussait/tirait les chromaticités a et b. Les vues simples vont plus loin et vous permettent de définir votre propre espace de chromaticité uv à l’aide de la rotation des axes de chroma (uv) : lorsqu’elle est réglée à 0°, u est un axe vert-magenta et v un axe bleu-jaune (similaire au contraste de couleur). Mais ensuite, vous pouvez le tourner selon vos besoins, par exemple autour de -20°, l’axe v devient assez proche d’un axe de température de couleur, et l’axe u de l’axe de teinte orthogonal. Je vous laisse avec la documentation.

Ce mode est particulièrement bien adapté pour récupérer des éclairages de scène bleus envahissants, bien plus facilement qu’avec l’interface typique du mélangeur de canaux :

Après Après
Avant Avant
Photo © Reinout Nonhebel, 2018
  1. en compressant l’axe V, nous compressons fortement le gamut sur l’axe bleu-jaune, ce qui est beaucoup plus doux pour le reste du gamut que d’utiliser une compression globale de chroma,
  2. en compressant l’axe U, nous compressons également le gamut sur l’axe magenta-vert, mais beaucoup plus doucement,
  3. la teinte de couplage achromatique est réglée sur bleu profond. En augmentant la quantité de couplage, nous remappons une portion du bleu dans l’axe achromatique, ce qui signifie que nous le désaturons et l’éclaircissons à la fois, ce qui aide beaucoup à le ramener dans le gamut, tout en préservant l’impression générale de bleu. Inversement, la couleur complémentaire s’assombrit et se resature, mais comme cette couleur opposée est le jaune, et que nous avons compressé l’axe jaune-bleu via V, alors nous nous retrouvons à peu près au même endroit.

Cette réécriture simple des coordonnées des paramètres du mélangeur de canaux produit donc 6 contrôles au lieu de 9, et ils sont beaucoup plus significatifs et plus faciles à contrôler. C’est un problème d’UX qui a été abordé purement du côté mathématique, car cela ne consiste en rien de plus que ré-exprimer une matrice 3×3 dans une nouvelle base orthogonale de vecteurs propres, tournée sur l’axe RVB achromatique, ce qui signifie que tout est parti purement d’une intuition d’algèbre linéaire. Grâce aux propriétés de cette nouvelle base de vecteurs propres (qui sont imposées par conception), j’ai pu supprimer des dimensions et transformer celles qui restaient en contrôles plus significatifs. C’est ce que je veux dire lorsque je répète qu’on ne peut pas résoudre des problèmes d’UX en regardant simplement l’interface graphique.

Virage partiel RVB

L’ancien module Darktable virage partiel travaillait dans l’espace TSL, qui ne prend pas en charge les valeurs de code RVB supérieures à 1 (donc, pas de scene-referred). De plus, mélanger des couleurs en TSL est bancal et donne l’impression d’un filtre jouet dès qu’on commence à augmenter les réglages.

Dans le même temps, le schéma d’adaptation chromatique actuel dans Ansel suppose un illuminant unique. Cependant, les scènes réelles ont toujours au moins deux illuminants :

  1. la source lumineuse principale, qui est l’illuminant primaire, et pèsera surtout sur les hautes lumières et les tons moyens,
  2. les surfaces colorées qui renvoient la lumière de la source principale et la teintent, qui agissent comme des illuminants secondaires, et pèseront surtout des ombres jusqu’aux tons moyens.

Jusqu’à présent, pour gérer cette situation d’illuminants mixtes, il fallait dupliquer des instances de calibration des couleurs et les masquer sélectivement. Mais essayer de découper un masque binaire (une région attribuée à un illuminant, et le reste à l’autre illuminant) est fragile car cela ne tient pas compte du mélange de lumière qui se produit autour des tons moyens.

Le nouveau module virage partiel dans Ansel propose donc deux mélangeurs de canaux et deux corrections de température de couleur, et duplique les nouveaux modes d’interface de la calibration des couleurs. Il vous permet de définir la luminosité de chaque illuminant, associe une matrice de couleur à chacun, et calcule un mélange des deux matrices à appliquer à chaque pixel en fonction de sa luminance.

Après Après
Avant Avant
© Luc Viatour, 2016

À ce stade, vous pourriez penser que je suis obsédé par la photographie de concert, mais c’est uniquement parce que les éclairages de scène sont la configuration la plus exigeante et ne pardonnent aucune erreur dans le pipeline de couleur. Ce sont des problèmes restés sans solution pendant des décennies ; les éclairages bleus sont réputés pour virer au magenta, et ils constituent le banc d’essai ultime en matière de couleur.

Ici, nous avons ajusté la température des hautes lumières pour obtenir des tons de peau plus naturels, tout en préservant l’ambiance bleue générale dans les ombres. Dans une telle scène, il n’y a aucun blanc que vous puissiez échantillonner, donc viser des tons de peau naturels est le seul guide. Ensuite, vous faites de votre mieux pour préserver l’esprit de l’éclairage de scène (garder le bleu bleu), tout en tenant compte des limites de votre gamut RVB. Pour plus de détails, voir la documentation.

Primaires de couleur

Comme je l’ai mentionné plus tôt, le module primaires de Darktable n’est qu’un simple doublon du mélangeur de canaux avec une interface différente. Mais il existe des cas où manipuler tout l’espace colorimétrique via ses primaires endommage trop la plage de faible saturation qui était parfaitement valable. Il y avait donc un besoin d’affecter les couleurs primaires et secondaires (aux sommets du cube de gamut) d’une manière qui exclut le centre du gamut, tout en fusionnant les effets de façon douce entre les deux régions et en préservant les dégradés de l’image.

Ceci a été réalisé en construisant une LUT RVB dans un nouveau module : primaires de couleur.

Après Après
Avant Avant
© Andrea (source )

Cet exemple a été conçu pour rendre le rouge et l’orange moins envahissants, mais approfondir considérablement les bleus, afin de montrer à quel point la transformation de couleur est stable le long des bords entre des surfaces de couleurs différentes.

Comme, en interne, le module construit dynamiquement une LUT en décalant la couleur des nœuds de contrôle, les utilisateurs ont la possibilité de décider à quelle distance des sommets du cube RVB se situent les nœuds de contrôle, à l’aide du curseur couverture du gamut. Ensuite, 3 paramètres de lissage permettent de fusionner plus ou moins fortement les décalages de couleur en RVB, et de protéger plus ou moins les couleurs neutres du décalage. Enfin, le module dispose d’un visualiseur de LUT 3D :

image

Le visualiseur de LUT montre les décalages de couleur à travers tout le cube RVB, de l’origine à la destination. Il peut être tourné autour de l’axe achromatique (azimut), ou placé dans une vue en plan de chromaticité (inclinaison de l’axe = 90°). Il peut être zoomé, déplacé et tourné en 3D à partir des événements de la souris, et découpé en tranches pour obtenir une meilleure vue à une certaine profondeur. Enfin, la LUT 3D générée peut être exportée sous forme de fichier cLUT .cube afin d’être réutilisée dans tout logiciel qui les prend en charge. Pour plus de détails, voir la documentation.

Égaliseur de couleur

La « team » Darktable a pris mon deuxième prototype (non fonctionnel)  d’égaliseur de couleur, n’a pas compris pourquoi il ne fonctionnait pas, a ajouté des étapes de post-filtrage pour masquer les problèmes, et l’a publié comme si c’était leur propre travail, sans même me créditer. Ils peuvent le garder : c’est de la merde. Et de toute façon je ne signe pas mon nom sur de la merde.

Voyez-vous, le problème de ce prototype est qu’il appliquait le décalage de saturation dans l’espace colorimétrique dt UCS 22 HSB, que j’ai conçu en 2021 . Cet espace colorimétrique est déjà utilisé dans balance des couleurs RVB pour la saturation, et visait à trouver la juste quantité d’assombrissement à appliquer à une couleur lorsqu’on augmente sa « saturation » (en fait, son chroma, en termes rigoureux de science des couleurs), afin d’éviter de dégénérer en couleurs fluo et néon non naturelles, qui sont les pièges typiques lorsqu’on ajoute beaucoup de « saturation ». Ainsi, au lieu du réglage typique de chroma qui réduit la coloration à luminance ou clarté constante, cette formule de saturation assombrit aussi. Et si cela fonctionne très bien sur des aplats de couleur unis, le problème est que les images ne sont pas des surfaces de couleur unie, mais ont des dégradés.

On m’a signalé vers 2022 que la saturation dt UCS HSB de balance des couleurs RVB créait une étrange frange achromatique claire entre des feuilles d’automne jaunes vives et saturées et le ciel bleu profond derrière elles. Le problème était qu’au niveau du bord, la lumière jaune des feuilles et la lumière bleue du ciel se mélangeaient en achromatique (comme elles le devaient, étant des couleurs complémentaires) à cause d’un objectif légèrement doux ou d’une brume atmosphérique. L’algorithme de saturation assombrissait le jaune et le bleu de chaque côté de la frange achromatique, mais pas la frange elle-même, qui ressortait désormais plus claire. Et il n’y a aucune correction à cela ; ce n’est pas un bug algorithmique : le problème est le modèle de couleur, qui tient compte de la perception mais pas du mélange de lumière. J’étais donc encore un auteur de plus d’un espace colorimétrique défectueux de plus, qui m’avait pris des mois à développer et 20 heures de calcul pour ajuster numériquement les paramètres du modèle.

Tenter d’implémenter un égaliseur de couleur en réutilisant ce même espace colorimétrique a rendu ces problèmes encore pires, car désormais l’effet était piloté par la teinte, ce qui signifiait des problèmes sur deux dimensions au lieu d’une. Pour atténuer le problème, j’ai essayé de tout lisser à l’aide de filtres guidés RVB. Mais je n’arrivais pas tout à fait à trouver la formule magique pour obtenir une fusion correcte et robuste. C’est à ce moment que la team Darktable a décidé de récupérer la nouvelle babiole toute brillante sur l’étagère, et que j’ai compris que cela ne pouvait se produire qu’en RVB si l’on voulait une fusion correcte et la préservation des dégradés.

Après Après
Avant Avant
© baongoc124 (source )

L’égaliseur de couleur hérite du même curseur interactif que l’égaliseur de tons, pour une édition directe sur l’image en échantillonnant la teinte du pixel sous le curseur, et le défilement mettra automatiquement à jour le graphe. Des nœuds peuvent être ajoutés librement n’importe où, et depuis le curseur interactif, l’ajout d’un nœud à la teinte courante se fait par un clic droit.

L’égaliseur de couleur permet de définir un décalage de couleur par teinte pour les ombres, les tons moyens et les hautes lumières. La pipette de couleur permet de voir où se situe une région entre les contrôles tonaux. Cela permet un contrôle très fin qui, avec le même lissage 3D que primaires de couleur, offre un moyen très robuste de fusionner les décalages de couleur. Le bruit de chroma qui était le principal problème, lors de la définition de décalages de couleur spectaculaires, avec l’ancien module Darktable zones de couleur (travaillant en CIE Lab 1976) ou avec le prototype précédent d’égaliseur de couleur n’apparaît plus.

Comme pour primaires de couleur, ce module crée dynamiquement une LUT RVB 3D qui peut être visualisée et enregistrée dans des fichiers .cube de la même manière. Pour plus de détails, voir la documentation.

Dessin

image

Ai-je besoin d’en dire plus ?

Ansel implémente désormais un prototype de module de dessin qui vous permet de dessiner des images matricielles dans un pipeline scene-referred à partir de pinceaux 32 bits prenant en charge les couleurs HDR (>100 %). Les pinceaux prennent en charge l’opacité et le flux (comme Photoshop), les projections aléatoires, le lissage de tracé, l’adoucissement des bords, et peuvent être utilisés en modes peinture, gomme, étalement et flou. La taille, l’opacité, le flux et la dureté du pinceau peuvent être mappés sur la pression et l’inclinaison du stylet Wacom, ou sur une accélération générique du curseur. Ils utilisent un alpha prémultiplié correct et enregistrent les calques dans des fichiers annexes TIFF flottants 16 bits qui peuvent être édités dans la plupart des grandes applications de dessin.

Plusieurs calques peuvent être utilisés en instanciant plusieurs instances du module dessin et en les composant sur l’image à l’aide des options génériques de fusion et de masquage d’Ansel. Il peut aussi être utilisé pour composer n’importe quel type de calque arbitraire provenant de n’importe quel logiciel, tant qu’il est enregistré en flottant 16 bits comme calque dans le fichier annexe TIFF d’Ansel. L’image de fond (avant le module) peut être exportée comme calque de fond si vous avez besoin d’une image de référence pour dessiner dans un autre logiciel et réimporter le résultat.

Ceci a été rendu possible par la nouvelle architecture de pipeline qui a permis un mode temps réel. Certes, ce n’est toujours pas aussi rapide que Photoshop car, à chaque rafraîchissement de coup de pinceau, d’autres modules s’exécutent après dessin dans le pipeline.

C’est la liberté ultime d’accomplir tout ce que les boutons et les curseurs ne vous permettront jamais d’obtenir, qu’il s’agisse d’éclaircir et d’assombrir, de réparer des parties endommagées (hautes lumières écrêtées, zones manquantes) ou simplement de mélanger photographie et peinture. Pour plus de détails, voir la documentation.

Grain photographique

L’ancien module grain de Darktable était vraiment insatisfaisant, car il ne permettait qu’un grain de luminance et était appliqué sur le canal de clarté de l’espace colorimétrique CIE Lab 1976. Les résultats étaient étranges, ne correspondant en rien aux halogénures d’argent. J’ai finalement implémenté la synthèse stochastique de grain  que j’ai développée en 2023 dans un nouveau module : grain photographique. Celui-ci divise le champ lumineux en cristaux virtuels d’halogénure d’argent et simule des capteurs de grain empilés sur des couches. Il fonctionne aussi bien pour le grain N&B que couleur, bien que j’aie dû prendre quelques distances avec mon article initial pour gérer la couleur.

Après Après
Avant Avant
© Alessandro Amato del Monte (source )
Après Après
Avant Avant
© Alessandro Amato del Monte (source )

Filmic

Pendant plusieurs années, des gens m’ont répété que les modules stupides de Darktable sigmoid et le plus récent AgX leur donnaient un peu plus de contrôle. Et aucun d’entre eux n’a été capable de me dire exactement le contrôle sur quoi. Il m’a donc fallu longtemps pour le comprendre.

Sigmoid et AgX ne sont pas des révolutions, ce sont d’autres filmics :

  1. vous convertissez les couleurs à l’aide d’un logarithme ou d’une mise en forme par puissance,
  2. vous plaquez une courbe en forme de S par-dessus,
  3. puis vous faites de votre mieux pour rattraper ce que la courbe de tonalité a fait au chroma tout au long du processus,
  4. et enfin vous annulez la mise en forme.

Sigmoid et AgX auraient pu être des modes alternatifs à l’intérieur de filmic : ils passent tous par les mêmes étapes avec des priorités et des stratégies légèrement différentes. Faire cela aurait fourni un seul module pour la compression de plage dynamique, avec différents modes selon le degré de contrôle fin que les utilisateurs souhaitaient. Au lieu de cela, ils ont dupliqué des fonctionnalités et ajouté de la surcharge d’interface, de sorte que les utilisateurs doivent désormais choisir entre courbe de base (qui était déjà une variante dupliquée et spécialisée de la courbe de tonalité elle-même), filmic, sigmoid et AgX pour accomplir la même tâche, alors qu’aucun d’entre eux n’indique réellement la fonctionnalité qu’il fournit.

La seule chose que filmic fait le mieux est de gérer explicitement les limites de la plage dynamique, ce qui permet de l’utiliser pour la compensation du point noir lors de l’impression. Les deux autres les gèrent comme un sous-produit du réglage de contraste. Comme les développeurs des deux autres se moquent des tirages, vous pouvez parier que cela relâche certaines contraintes sur la conception, et supprime quelques curseurs dans l’interface. La seule chose que les deux autres font mieux est de fournir des contrôles de couleur manuels pour rattraper les problèmes de saturation et de décalage de teinte à travers le mappage tonal, mais je ne pense vraiment pas que ce niveau de granularité de couleur ait sa place dans une fonctionnalité de mappage tonal : c’est un flux de travail et une répartition de fonctionnalités complètement bancals.

Quoi qu’il en soit, j’ai finalement compris que le contrôle de contraste plus fin venait du fait que sigmoid fournit directement un contrôle des nœuds de pied et d’épaule, tandis que filmic utilise une latitude et un décalage globaux qui sont pénibles à utiliser puisqu’ils lient les deux. Ceci a été conçu à l’origine pour le mapper sur de véritables fiches techniques de pellicules, car la latitude est une chose bien réelle en photographie argentique, afin de peut-être émuler de vraies pellicules un jour. Ce jour n’est jamais venu.

J’ai donc résolu le problème dans la couche d’interface graphique en ajoutant une conversion entre les réglages latitude/décalage et hautes lumières/ombres, et désormais filmic RVB vous permet de manipuler directement la position des nœuds de pied/épaule :

image

Aucune mathématique pixel n’a été modifiée dans le processus, les paramètres du module sont toujours les mêmes qu’avant, aucun nouveau module n’a été créé, c’est juste une étape intermédiaire de conversion dans l’interface graphique.

Conclusion

Tous les nouveaux modules prennent en charge le déchargement sur GPU via OpenCL. Ils ont été conçus pour la robustesse, et je pense que cet objectif a été atteint. Ils ont remplacé de précédents modules moins bons, travaillant en CIE Lab 1976, qui ont montré leurs limites et leurs défauts depuis longtemps. Vous exécutez désormais un pipeline entièrement RVB dans Ansel. Les anciens modules sont toujours présents dans le programme et s’exécuteront encore pour les anciennes éditions. De plus, les curseurs colorés et les graphes de teinte sont gérés en couleur à l’aide du profil colorimétrique de l’écran.

Les modules que j’ai récemment introduits ne sont pas de nouveaux jouets brillants dont il faut s’enthousiasmer. Ils sont l’aboutissement d’années de réflexion sur une répartition cohérente et cohérente des fonctionnalités qui aide le flux de travail scene-referred. Ce flux de travail scene-referred est plus complexe que le précédent display-referred, ne serait-ce que parce que nous devons normaliser le « blanc » avant d’entrer dans toute LUT ou espace colorimétrique perceptuel, mais c’est la seule façon d’aborder les images HDR, la fusion alpha correcte pour les masques, et les filtres pixel physiquement exacts qui simulent le mélange de lumière. Les filtres physiquement exacts sont robustes et produisent des résultats organiques, même poussés à des réglages spectaculaires. Mais ils sont souvent moins accessibles aux nouveaux venus et déroutants pour les retoucheurs expérimentés habitués à Lightroom et consorts.

Ce sera mon dernier billet sur ce site car je me retire du développement. Cela m’a coûté trop cher : trop de stress, trop de burn-outs, trop d’années passées à réparer la merde des autres et à souffrir de leurs mauvaises décisions. Je suis fatigué au-delà de ce que vous pouvez imaginer. Je déteste la programmation et je déteste les programmeurs. J’en connais très peu qui programment pour construire des choses ou résoudre des problèmes, la plupart aiment simplement trop passer du bon temps avec un ordinateur, et se transforment en pompiers pyromanes à qui l’on ne peut pas confier la conception des choses. Je déteste la technologie et la soi-disant « innovation » : tout cela n’est qu’une escroquerie capitaliste conçue pour une croissance infinie dans un monde où les ressources sont limitées, et nous prétendons résoudre les problèmes créés par la technologie avec encore plus de technologie. C’est de la folie. Le monde open-source hérite du même état d’esprit, y compris le techno-solutionnisme , car c’est le genre de pourriture cérébrale que produisent 350 ans de capitalisme, même si le FLOSS n’a pas les profits pour le justifier. Il est plein de mensonges et plein de merde, car libre ne signifie liberté que pour les ingénieurs, et les utilisateurs peuvent aller au diable. Le problème, c’est que je croyais à ces mensonges, à ces valeurs : elles étaient (et sont toujours) les miennes. Mais réaliser que ce ne sont que des mots vides répétés dans des « communautés » toxiques d’hommes blancs d’âge mûr titulaires de diplômes d’ingénieur, de master et de doctorat a été un réveil brutal. Que faisons-nous réellement pour donner du pouvoir aux utilisateurs qui en ont réellement besoin ? À quel moment exiger nonchalamment d’utiliser la ligne de commande donne-t-il du pouvoir à quiconque ne sait pas lire du code ? Nous ne faisons que contribuer à creuser le fossé entre les élites lettrées en informatique et les paysans. Rappelez-vous, nous faisons ici un logiciel de photographie, pas une bibliothèque backend, pas une infrastructure serveur, mais une application de bureau pour utilisateur final.

J’ai vidé mon cerveau ici, pour consigner tout ce que j’ai appris sur la conception du traitement d’image, comment je l’ai fait, et pourquoi. Il est important de comprendre que les utilisateurs, et la plupart des développeurs, ne connaissent que le comportement d’une seule application sur leurs propres images. Pendant 8 ans, j’ai reçu de nombreuses images pathologiques que des gens m’ont envoyées, mettant en évidence les défauts et les limites des outils. J’ai environ 45 Go de ces images sur mon disque dur, en ce moment même. Cela donne une perspective complètement différente sur les vrais problèmes que celle que peuvent avoir tous les joyeux vacanciers : je suis le type qui sait ce qui casse et quand. Je suis le type que les problèmes trouvent. Je suis la Cassandre  du projet. Et c’est agaçant de devoir tout le temps justifier, à des gens qui ne voient pas les problèmes, pourquoi cette chose qui pourrait être bien plus simple ne peut pas être bien plus simple parce qu’il existe des cas pathologiques où nous devons nous adapter à la variabilité des entrées. Pour s’adapter à la variabilité des entrées, il faut des paramètres utilisateur au lieu de constantes codées en dur. D’où la surcharge d’interface. Le genre de surcharge d’interface que vous ne pouvez pas éviter sans nuire à l’utilisabilité.

Vous ne pouvez pas évaluer la qualité d’une conception si vous ne connaissez pas ses exigences. « Moi aimer » ou « moi pas aimer » n’a aucune pertinence. Personne n’aime porter une ceinture de sécurité, c’est quand même une bonne conception si l’on considère combien de vies elle a sauvées. Toute véritable critique ne peut porter que sur la manière dont la solution proposée a atteint l’objectif, ce qui ne peut se produire que si vous connaissez l’objectif. En traitement d’image, la nature mixte des exigences rend difficile d’éviter de plonger dans les mathématiques et leurs hiéroglyphes à un moment donné, et c’est là que vous perdez les gens. Mais cela ne les empêche pas pour autant de donner leur avis inutile, en commençant par « Je ne suis pas programmeur »/« Je ne suis pas mathématicien »/« Je ne suis pas coloriste scientifique »… « MAIS »… [insérer ici un bruit cérébral quelconque]. Faire du code open-source, où tout est public, autorise ce genre de bruit un peu partout : c’est vraiment épuisant, et il y a bien des fois où j’ai souhaité que le code source soit fermé, juste pour pouvoir travailler en paix. La plupart de ces types sont bien intentionnés et veulent simplement faire partie de quelque chose, mais contribuer à la surcharge d’information n’aide pas et ne fait que contribuer à créer de la fatigue. La communication est l’endroit où tout travail d’équipe perd en productivité

La conception ne consiste pas à écouter ce que les gens aiment. Si 65 % de votre panel de test aime le texte écrit en rouge, et 72 % aime le texte écrit sur fond rouge, écrivez-vous du texte rouge sur fond rouge ? Cela n’a aucun sens. Nous ne faisons pas de politique et n’essayons pas de plaire aux électeurs pendant une campagne, nous cherchons des solutions à long terme, pérennes, à des problèmes. La conception consiste à écouter ce dont les gens ont besoin, ce qu’ils peuvent rarement exprimer clairement, et à trouver des moyens de factoriser ces besoins. Ainsi, les seules statistiques qui valent la peine d’être calculées portent sur les cas d’usage : comment le logiciel est utilisé, quels sont les points de douleur les plus courants, et quelle en est la cause profonde. Puis corriger la cause profonde, qui peut être très éloignée de la manifestation réelle du problème. Cela aussi est une compétence réelle et précieuse : suivre le fil du problème, à travers des indices et des odeurs, pour découvrir la véritable origine, et non pas simplement rapiécer le problème final ou le contourner. « Écouter les utilisateurs » ne signifie pas écouter chaque individu et lui donner ce qu’il veut individuellement : nous ne fournissons pas de thérapie. Cela signifie écouter l’ensemble de la base d’utilisateurs, et identifier les besoins et points de douleur communément partagés afin de concevoir une solution factorisée qui couvrira le plus de besoins avec le moins de technologie. Cela n’implique pas d’écarter quiconque s’écarte de la moyenne de plus d’un écart-type, mais ces personnes devront peut-être recourir à des méthodes qui ne sont pas sur mesure ni optimisées pour leurs besoins.

La conception n’existe pas sur une île déserte : il y a d’autres applications d’édition d’image autour. Il est là encore difficile d’évaluer quand votre conception doit copier les autres parce que les utilisateurs seront habitués à leur sémantique d’interface, et quand vous devez vous en écarter parce que le problème que vous essayez de résoudre est trop différent de ce que fait la concurrence, ou que votre utilisateur type est trop différent. L’open-source est constamment tiraillé entre la tentation de copier au 1:1 les leaders commerciaux qu’il déteste si tendrement (mais auxquels il aspire en silence), et l’envie de surpasser tout le monde en réinventant la roue (souvent en pire). Dans tout cela, votre étoile Polaire est de vous demander, chaque heure de chaque jour : quel est le problème que nous essayons de résoudre, et qui sont les gens qui y sont confrontés ? C’est ainsi que vous pouvez adapter les choses à votre public, plutôt que de tomber dans des cultes du cargo  et d’adopter des solutions parce qu’elles ont eu du succès dans un contexte que vous ne comprenez pas vraiment et qui n’est pas nécessairement le vôtre.

Mon principal enseignement de toutes ces années est qu’appliquer des transformations de couleur aux pixels dans tout autre espace que le RVB est voué à l’échec, comme le montre l’exemple de colorbalance RGB : bien que cela puisse sembler une excellente idée de décorréler le travail de « couleur » (au sens de teinte/chroma) du travail tonal, ce ne sera jamais qu’une question de choisir sa douleur. Augmenter le chroma à clarté constante dégrade les couleurs en fluo, augmenter la saturation à luminosité constante (donc en assombrissant globalement) ne respecte pas la théorie du mélange de lumière, et les deux produisent du bruit de chroma en raison de la nature instable des angles de teinte. Mais d’un autre côté, le RVB n’est pas perceptuellement uniforme, et la plage verdâtre de toute échelle de teinte TSL/TSV occupe environ 30 % de l’espace, alors que le vert ne représente que 1/6 de l’anneau perceptuel de teinte. La seule solution est de gérer l’interface graphique dans des modèles de couleur perceptuels, et de convertir, d’une manière ou d’une autre, en RVB avant d’appliquer aux pixels. Ce qui nécessite une gymnastique d’abstraction supplémentaire de la part des développeurs. Et ce n’est clairement pas leur fort, puisque le niveau en maths est assez bas.

J’ai déjà un successeur, mais l’avenir d’Ansel devra être une coopérative où les utilisateurs garantissent aux développeurs des conditions de travail équitables, et les développeurs garantissent aux utilisateurs que leurs besoins seront couverts, réciprocité des responsabilités mutuelles. Nous ne pouvons pas continuer comme ça, ce n’est pas sain. Et, par « comme ça », je veux dire d’un côté le « développeur amateur » sans aucune responsabilité, et de l’autre, le développeur unique en burn-out vivant sous le seuil de pauvreté pour faire à peu près avancer les choses. Ce paradigme a donné tout ce qu’il pouvait, il ne peut pas être ajusté. Les mêmes causes ne mèneront qu’aux conséquences que nous connaissons déjà : l’open-source, c’est nul. Si vous voulez plus, ce paradigme devra changer. L’open-source, d’un côté, est une dictature des développeurs (ceux qui savent et peuvent) sur les utilisateurs (ceux qui ont besoin), mais de l’autre côté, c’est l’exploitation de ceux qui travaillent par ceux qui prennent. Cela ne fait qu’alimenter le ressentiment mutuel, le mépris sourd et le paternalisme. Tout le monde y perd.

L’alternative est l’actuelle emmerdification des plateformes des entreprises et le technofascisme qu’elle est en train de rendre possible. Vous êtes prévenus.


Translated from English by : Aurélien Pierre, ChatGPT, Claude, Claude (Anthropic). 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  ↩︎