Inleiding

Gereedschappen versus machines, ambachten versus industrie

In zijn boek The Technological Society (1954) presenteert Jacques Ellul het verschil tussen de tijd vóór en na de industriële revolutie als volgt:

Het pre-industriële tijdperk is het rijk van het gereedschap en van het ambacht. De belangrijkste eigenschap van gereedschappen is dat ze generiek, veelzijdig en aanpasbaar zijn. Het is aan de ambachtsman om zijn vaardigheden te ontwikkelen om de gereedschappen zijn bedoeling te laten volgen, zodat de hand de beperkingen van het instrument compenseert. Dit concept is vandaag de dag nog steeds welbekend bij muzikanten: je moet oefenen, leren, proberen, falen, opnieuw proberen… er zijn geen sluiproutes. Ellul benadrukt het idee van spaarzaamheid dat bij gereedschappen hoort: middelen zijn beperkt, dus je gereedschapsset wordt vrijwel bepaald door wat je je kunt veroorloven, kunt dragen, kunt beheersen en lokaal kunt bouwen. Trends veranderen langzaam en zijn lokaal, omdat ze lokale middelen gebruiken en zich aanpassen aan lokale behoeften, en gereedschappen volgen hetzelfde patroon. Gereedschappen zijn erfstukken die van meester op leerling worden doorgegeven, van ouder op kind. Ze worden niet incompatibel of verouderd.

Het industriële tijdperk is het rijk van de machine. Het komt voort uit een cultuur van standaardisatie en massificatie. De machine is veel productiever omdat ze gespecialiseerd is in één taak, maar ze is nutteloos voor al het andere en kan zelden voor een ander gebruik worden aangepast. Wanneer de productiebehoeften veranderen, wordt de machine vervangen door een andere omdat ze nergens goed voor is. Dit is geen spaarzaam schema meer, en het is toegestaan omdat middelen veel goedkoper zijn en massaproductie schaalvoordelen mogelijk maakt. Vervolgens worden mensen de dienaren van de machine, en wordt handwerk een luxe.

Producties die thuis of in kleine werkplaatsen werden gemaakt, in een familiale context, worden verplaatst naar grote fabrieken, waar genoeg ruimte is voor machines. Overigens had dat zeer concrete effecten op hoe we ons dagelijks leven organiseren, waaronder wanneer en hoe vaak we eten1, evenals slaappatronen2. Het is dus niet vergezocht om te zeggen dat de industriële revolutie ook diepgaand veranderde hoe we denken, wat we normaal of vanzelfsprekend vinden.

Dat sprak me aan omdat het is hoe ik kleurbewerkingsgereedschappen had ontwikkeld, intuïtief, sinds ik begon: proberen generieke gereedschappen te bouwen die op de minste aannames steunden om veelzijdig te blijven, terwijl ze fijnkorrelige controle over beeldparameters gaven, en uiteindelijk steunend op de vaardigheden van ambachtslieden in plaats van op halfkapotte, ongevalideerde, automagische gereedschappen die alleen in ideale gevallen werken.

Digitale fotografie: het proces automatiseren of ervan genieten?

Ik heb nooit de passie begrepen van veel fotografen, vooral de meest technofiele, voor drukknop-workflows en geautomatiseerde procedures. Ik heb piano geleerd en gegeven, en ik ben gewend aan het shut up and practice-paradigma: trainen om behendigheid te ontwikkelen en te behouden, en dan dezelfde paar maten steeds opnieuw herhalen totdat het geluid goed is. Werken aan de kwaliteit, de textuur en de expressiviteit van het geluid, via de hoeveelheid gewicht die je op de toetsen legt, de snelheid van de aanslag, de beweging van de pols en onderarm. Je lichaam gebruiken voor fijne beweging en het trainen voorbij zijn huidige vaardigheden, waarbij zeer onnatuurlijke gebaren reflexen worden. En ten slotte leren om in je hoofd het geluid te horen waar je naar streeft, nog voordat je je handen beweegt. Al die dingen die nooit herleidbaar zullen zijn tot GUI-schuifregelaars en -knoppen, metrieken, variabelen of algoritmen.

De manier waarop veel fotografen fotobewerking benaderen klinkt alsof ze door de digitale fotografie gestraft werden omdat ze nu een software moeten gebruiken om hun foto’s te krijgen. Dus moet het gereduceerd worden tot een zielloze procedure waarbij alles geautomatiseerd zou moeten worden als het kan. We wisselen presets en recepten uit, sommigen verkopen ze zelfs. En nu hebben we AI om de ene of de andere stijl na te bootsen. Waar is de vreugde in het industrialiseren van artistieke creatie? Wat heeft het voor zin om een hobby te hebben die aanvoelt als de last van het moeten ontwikkelen van je foto’s? Kunst is een proces, geen procedure. Welke zieke geest zou een robot ontwerpen die in jouw plaats pottenbakt, graveert of bloemstukken maakt? Wat dacht je ervan om software te gebruiken als een kans om de look van je beelden af te maken naar jouw smaak en gevoeligheid? Zijn we het rauwe plezier verloren om dingen zelf te doen, zelfs slecht? Op welke leeftijd raakt deze eetlust verloren?

Toegegeven, vechten tegen een fotobewerkingssoftware is een frustrerende ervaring, maar je moet begrijpen waartegen je vecht. Is het gewoon de intrinsieke moeilijkheid van je ambacht en je gebrek aan vaardigheden, of is het het slechte ontwerp van het gereedschap? Wanneer je worstelt op een piano van 25 k€ die net de pianotechnicus zag, weet je dat het instrument niet het probleem is. Maar met software, hoe weet je dat? Wel, dat kun je niet totdat je je volledig committeert aan het shut up and practice-paradigma. Goede retoucheurs halen goede resultaten uit elke software, het verschil zit in hoeveel tijd dat hun kost. En, wel, soms moet je veel wegwerken voor de kapotte kleurmodellen van bewerkingsapplicaties.

Gereedschappen in de fotobewerkings-GUI

Wat UI-ontwerp betreft, is de spaarzaamheid van generieke, veelzijdige gereedschappen de beste manier om te voorkomen dat je overweldigd raakt door tientallen functies die elkaar verbergen, in functionaliteit overlappen en gewoon je gezichtsveld vervuilen. Het is software-feng shui. Maar dan verschuift de aard van de gereedschappen een beetje.

Er zijn twee manieren om over kleurbediening voor beeldverwerking na te denken: vanuit hun functioneel gebruik, en vanuit de manier waarop ze het mogelijk maken kleureigenschappen te manipuleren. Vanuit hun functioneel gebruik:

FunctieMethoden
RuisonderdrukkingWaveletfiltering, non-local means, bilateraal filter, geleid filter, diffusie,
OntwazenRichardson-Lucy-deconvolutie, Gauss-/Laplace-piramide, hoogdoorlaatfilter, waveletfiltering, tegendiffusie, onscherpmasker
VervagenWaveletfiltering, diffusie, bilateraal filter, geleid filter
OphelderenBelichtingscorrectie, tooncurve, macht-(“gamma”)-overdrachtsfunctie, kanaalmixer
WitbalansKanaalgewijze normalisatie, chromatische-adaptatietransformatie, kanaalmixer
KleurverschuivingKanaalmixer, lift-gamma-gain, slope-offset-power, tintrotatie, LUT
KleurrijkheidsverbeteringVerzadiging, chroma, levendigheid, LUT
ContrastverbeteringTooncurve, sigmoïdale overdrachtsfuncties, bereiknormalisatie (“niveaus”), LUT
Compressie van dynamisch bereikHetzelfde als contrast, maar in “verminder”-modus in plaats van “vergroot”-modus

Merk op dat kleurverschuiving weer in twee modi zou kunnen worden opgesplitst: corrigerend (wat om lichtmodellen vraagt) en creatief (wat om perceptuele modellen vraagt). Zo ver zullen we niet gaan.

Als we dezelfde lijst vanuit het andere ingangspunt benaderen, de manier waarop ze het mogelijk maken kleureigenschappen te manipuleren, krijgen we:

MethodeFuncties
WaveletfilteringRuisonderdrukking, Ontwazen, Vervagen
DiffusieRuisonderdrukking, Ontwazen, Vervagen
KanaalmixerOphelderen, Kleurverschuiving, Witbalans
LUTContrastverbetering, Kleurverschuiving, Kleurrijkheidsverbetering
TooncurveOphelderen, Contrastverbetering, Compressie van dynamisch bereik

Ik heb de hele lijst niet opnieuw gedaan maar je snapt het idee: of je nu je lijst met gereedschappen wilt classificeren op methode of op functie, je eindigt niet met een 1:1-overeenkomst, behalve voor enkele. Dus geen van deze afbeeldingen laat je toe je gereedschappen systematisch te factoriseren tot GUI-eenheidselementen, om het principe van spaarzaamheid te eren.

En dan is beeldverwerking niet zomaar een set gereedschappen in een doos, het is eigenlijk een pipeline van pixelfilters die als grafknopen moeten worden ingevoegd in een volgorde die overeenkomt met de invoervereisten van de filters. Alsjeblieft (vereenvoudigd):

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)

En, last but not least, het probleem dat niemand ziet: de wiskunde. Bijvoorbeeld, een geleid filter toegepast op een dekkingsmasker en geleid door het RGB-beeld (zoals in de maskerverfijning van Ansel/Darktable) heeft niet dezelfde wiskunde als een geleid filter toegepast op een luminantiemasker en geleid door zichzelf (zoals in de toonequalizer), of een volledig RGB-beeld geleid door zichzelf (zoals in dehaze). Die moeten meerdere keren geïmplementeerd worden, met verschillende soorten invoer en verschillende soorten optimalisaties. Hetzelfde geldt voor methoden die op niet-gedemozaïceerde beelden werken: we moeten rekening houden met het feit dat we niet op elke sensel een volledig RGB-signaal hebben, en XTrans-arrays hebben speciale wiskunde nodig die verschilt van Bayer.

Dus, gegeven dat:

  1. functionaliteiten verschillende methoden hebben,
  2. methoden niet tot één enkele functionaliteit kunnen worden herleid,
  3. ze allemaal als knopen worden ingevoegd in een pipeline waar volgorde ertoe doet,
  4. methoden implementatievariaties hebben afhankelijk van hun invoersignaal, d.w.z. hun positie in de pipeline,
  5. gebruikers plezier willen hebben zonder iets te hoeven leren,
  6. GUI-rommel niemand dient en iedereen vermoeit,

…hebben we een probleem: hoe splits je functies op en organiseer je ze als een coherente GUI?

In een professionele opstelling, waar je van gebruikers kunt verwachten dat ze weten hoe ze zelf een pipeline moeten bouwen en de ins en outs van de knopen ervan begrijpen, kun je de DaVinci Resolve-weg opgaan en een nodale editor bouwen. Dan bouw je één knoop per methode, en handel je intern de implementatievarianten af door het invoersignaaltype te controleren. Dit is de meest minimalistische manier, omdat er nul GUI-duplicatie is: gewoon een bank van knopen, en knopen kunnen parallel worden gezet in plaats van geforceerd sequentieel. Maar het vereist expertgebruikers.

De Lightroom/Capture One-weg is om volledig te verbergen dat er überhaupt een pipeline is, en een platte GUI te bieden. Dan wordt multi-instantiatie van knopen gedaan via maskers: door nieuwe maskers toe te voegen kun je ze een subset van de softwarebediening toewijzen om de gemaskeerde gebieden selectief te bewerken. Maar dat gaat ook gepaard met het feit dat geen van deze applicaties scènegerefereerd (scene-referred) lineair bewerken toestaat, wat vervagen, ontwazen, ruisonderdrukking en werkelijke maskerovergangen wankel maakt.

Ansel bewandelt een middenweg. Ten eerste is er nu een prototype nodale editor:

image
image

Dit laat ons toe de pipelinevolgorde expliciet te tonen, deze handmatig te herordenen, en ordeningspresets te wijzigen, op een manier die ook invoer en uitvoer toont. Voorheen hadden we alleen de stapel GUI-modules in de rechterzijbalk, die enigszins de pipelinevolgorde suggereerde als je hem als een laagstapel las, maar hij werd vaak door gebruikers misbruikt als louter een herordeningsgemak voor een GUI-gereedschapskist.

En dan is de functie-opsplitsing hybride:

  • De modules contrastequalizer, lokaal contrast en diffuse or sharpen zijn intrinsiek duaal van aard: ze kunnen lokaal contrast en scherpte vergroten of verkleinen afhankelijk van hun parameters. De contrastequalizer heeft zelfs een ruisonderdrukkingsmethode, wat logisch is omdat verscherpen ruis verhoogt, dus de juiste plek om het onder controle te houden is waar het gecreëerd wordt. Dit zijn methode-eerst-modules.
  • Witbalans dupliceert de functionaliteit van het chromatische-adaptatiegedeelte van kleurkalibratie. Witbalans is een eenvoudige kanaalgewijze normalisatie die plaatsvindt in sensor-RGB, en is nodig voor sommige demozaïceermethoden (vooral voor XTrans-sensoren), terwijl kleurkalibratie een veel perceptueel nauwkeurigere illuminantcompensatie uitvoert in de CIE CAT16-ruimte. Die ruimte is gedefinieerd vanuit de CIE XYZ 1931-ruimte, die we pas krijgen na invoerkleurprofilering (en dat vereist een gedemozaïceerd beeld om te werken). Er zijn verschillende redenen en behoeften voor beide, en ze moeten op verschillende plaatsen in de pipeline zitten. Dit zijn pipeline-eerst-modules: hoewel ze functioneel gelijkaardig lijken, maken hun bestaansredenen en hun interne vereisten (en volledig verschillende wiskunde) hen veel verschillender dan je zou denken. Hetzelfde geldt voor de verschillende ruisonderdrukkingsmodules: sommige werken op RAW-invoer, sommige niet, en sommige werken beter op niet-lineaire signalen.
  • Kleurbalans werd ontworpen als een alles-in-één kleurmodule, die een uitgebreide ASC CDL  (slope-offset-power) toepast, en vervolgens globale en luminantiegewijze verzadiging en chroma afhandelt, waardoor het eerdere Darktable-modules zoals contrast-brightness-saturation, vibrance en velvia vervangt (die allemaal in CIE Lab 1976 werken). Op zichzelf genomen is het een functionaliteit-eerst-module, maar het is niet de enige kleurverschuivende module. De andere kleurverschuivende modules gebruiken zeer verschillende methoden (matrices, LUT’s of tintgewijze bediening), die 3 tot 9 keer minder rekenintensief zijn om uit te voeren, en werken in verschillende kleurruimten.

Ansel erft zijn concept van modules van Darktable: modules zijn tegelijkertijd een GUI-gereedschapskistwidget en een pixelfilter dat ergens in de pipeline is ingevoegd. Dus zeer kleine modules ontwerpen (functioneel gezien) zal een heleboel hoogniveau-GUI-widgets in de rechterzijbalk voortbrengen, terwijl zeer grote modules ontwerpen minder hoogniveauwidgets zal maken, maar ze zullen hoger zijn of meer interne tabbladen gebruiken. De tweede optie kan nog steeds de voorkeur verdienen omdat hoogniveau-GUI-modules als bladen fungeren, dus minder bladen die functioneel consistent zijn helpen om de hoogniveau-functie-opsplitsing beter te begrijpen (zoals een inhoudsopgave).

Maar het houdt daar niet op, want nogmaals… knopen. Een module zou een set kleurbedieningen moeten zijn die consistent zijn als een multi-geïnstantieerde gemaskeerde knoop in de pipeline. Het is niet goed om een module vol te proppen met tientallen functies waarvan de helft zinvol is als globale instellingen, en de rest alleen in de maskerlocaliteit; ze zullen alleen CPU-cycli verbruiken voor niets zodra ze geïnstantieerd zijn.

En ten slotte is er prestatie. Kleurbediening die in een bepaalde kleurruimte moet werken zal een heen-en-weer-kleurconversie nodig hebben, wat CPU-cycli zal verbruiken, dus het is beter voor hen om allemaal in dezelfde module te draaien als ze functioneel gezien samen zinvol zijn. Ook zal elke nieuwe module een nieuwe lus over pixels draaien, wat betekent dat het beeld nog een keer van/naar het RAM naar de CPU-geheugencache wordt verplaatst. Dus het samenvoegen van functies in dezelfde lus voorkomt extra misbruik van I/O-bandbreedte en helpt met prestatie.

Dus, als we de hele lijst met beperkingen samenvatten, is het hier een echt moeilijke uitdaging om op te lossen:

  1. we zouden er altijd naar moeten streven de minste GUI-elementen te bouwen omdat een overvolle GUI alles moeilijk vindbaar maakt (en cognitief overweldigend): de beste plek om een boom te verbergen is in het bos,
  2. de rommel die we bouwen zou georganiseerd moeten worden van globaal naar lokaal, generiek naar specifiek, vaakgebruikt naar niche, omdat het de makkelijkste manier is om erover te redeneren: denken aan de GUI-structuur als een “inhoudsopgave” is het beste waar ik tot nu toe op ben gekomen,
  3. maar er een regel van maken om systematisch functies op te splitsen op basis van functionaliteit of op basis van methode eindigt nog steeds met duplicaties in beide gevallen, tenzij we de volledige-node-editor-richting opgaan, alles methode-gebaseerd doen, en de verantwoordelijkheid voor het bouwen van pipelines uitstellen naar de expertgebruiker,
  4. modules zouden waar mogelijk als functionaliteit-eerst moeten worden ontworpen, maar er gelden veel beperkingen:
    1. het invoersignaaltype, dat de positie in de pipeline bepaalt, en ons kan dwingen om pipeline-eerst te prioriteren en gereedschappen te dupliceren,
    2. de relevantie en consistentie van de set modulebedieningen wanneer multi-geïnstantieerd en gemaskeerd: een module zou een consistente eenheid van bewerkingsworkflow moeten zijn, geen ratjetoe om alles in te persen. Vooral, als het zinvol is (workflow-gewijs) om een masker op slechts een subset van de modulefuncties toe te passen, dan zou deze subset zijn eigen module moeten zijn,
    3. prestatieproblemen (kleurruimte-rondgang, gamut-mapping van de uitvoer, I/O-bandbreedte): we kunnen gebruikersergonomie niet uitsluitend vanuit de UI-kant bedenken; runtime-snelheid maakt ook deel uit van ergonomie,
    4. de wiskundige aard van de gerealiseerde bewerkingen: sommige methoden (vooral verscherping/lokaal contrast) kunnen tegengestelde effecten hebben afhankelijk van het teken van hun parameters, sommige methoden zijn slecht geschikt om samen in hetzelfde pixelfilter te worden gegroepeerd,
  5. ten slotte moet het aantal klikken/scrolstappen dat nodig is om een vaakgebruikte functie te bereiken in overweging worden genomen, omdat de generiek -> specifiek-as niet altijd parallel loopt aan de vaakgebruikt -> niche-as. Dus, hoewel de generiek -> specifiek-hoogniveauorganisatie cognitief zinvol is, is het niet altijd de meest ergonomische.

Al deze tegenstrijdige vereisten moeten geval per geval worden gearbitreerd, door naar de gehele pipeline te kijken, anders bouwen we geen workflow-applicatie maar een plugin-register. Ze leven op het kruispunt tussen laagniveauprogrammering, wiskunde, retoucheworkflow en UI-ergonomie, en geen van deze concepten is over het algemeen belangrijker dan de andere. Sommige van deze beperkingen worden echter makkelijker begrepen dan andere, waardoor ze veel meer aandacht zullen krijgen, in een typisch straatlanterneffect : problemen blijven najagen in de laag die je begrijpt terwijl je hun ware oorsprong volledig negeert omdat die een laag raakt die je niet begrijpt/waar je niets van weet. Dit is waarom het een echte kwelling is om met “UX-ontwerpers” te werken, omdat ze doorgaans niet de achtergrond hebben om verder te kijken dan de GUI en het hen vaak niets kan schelen dat er onder de UI een engine te besturen is. Je kunt niet zomaar kiezen om de zwaartekracht op te heffen omdat je de pitch -controller zou willen verwijderen voor een eenvoudigere UI.

Ontwerp is een proces van iteratieve verfijningen onder gebruikersfeedback. Sommige van deze iteraties zullen macro naar micro herontwerpen (globale applicatiearchitectuur naar interne modulebediening), en sommige zullen micro naar macro herontwerpen, totdat het convergeert naar geünificeerde semantiek en coherente functie-opsplitsing. Het is dwaas om te denken dat iemand het in één keer goed zal krijgen, of om te denken dat slechts één van de micro-/macroniveaus gerepareerd hoeft te worden. Het is een brug die je vanaf beide uiteinden tegelijk moet bouwen, en een manier moet vinden om ze in het midden te laten samenkomen.

De eigenschappen van goede kleurbediening

Vanuit mijn 17 jaar ervaring met het bewerken van foto’s, en 8 jaar ervaring met het bestuderen en experimenteren met beeldverwerkingswiskunde, zijn er een paar dingen die ik heb geleerd over wat een goede of een slechte kleurbediening is. Met “kleurbediening” bedoel ik een of andere manier om een gebruikersbedoeling te voeden aan een pixelalgoritme dat een visuele eigenschap van een beeld zal bewerken. Goede kleurbediening:

  1. is orthogonaal ten opzichte van elkaar, wat betekent dat één bediening op elk gegeven moment één kleurdimensie verandert en je niet dwingt op een andere bediening te compenseren,
  2. is gelijkmatig geschaald vanuit een perceptueel perspectief, wat betekent dat gaan van “0” naar “1” het visuele resultaat met dezelfde hoeveelheid zal veranderen als gaan van “1” naar “2”. Dit is helaas niet altijd mogelijk, omdat wiskunde en fysica je haten.
  3. schaalt sierlijk naarmate het dynamische bereik toeneemt, wat vrijwel alle kleurverschijningsmodellen (CIE Lab 1976, CIECAM 16, dt UCS 22) uitsluit, gebouwd voor SDR op datasets die op geschilderde kleurstalen werden opgenomen.
  4. degradeert sierlijk naarmate we de omvang van veranderingen vergroten, wat betekent dat ze overgaar kunnen worden maar de beeldinhoud niet kunnen veranderen en artefacten kunnen creëren,
  5. behoudt beeldgradiënten, wat betekent dat ze de tonale en chromatische lokale variaties als variaties behouden, in plaats van ze af te vlakken, ze te laten overschieten (halo’s, franjes, ruis enz. te creëren) of ze om te keren.
  6. laat kunstenaars toe hun bedoeling zo dicht mogelijk te benaderen in de minste hoeveelheid tijd.
  7. is niet gedupliceerd.

Uit 1. leiden we bijvoorbeeld af dat elke soort RGB-tooncurve slecht is, omdat het de hooglichten zal ontzadigen en de schaduwen zal verzadigen als bijproduct van de hoeveelheid (luminantie)contrast die je toevoegde, en je kunt de hoeveelheid verzadigingsverandering die je zult krijgen voor de hoeveelheid contrastverandering waar je om vroeg niet controleren (of decorreleren), behalve via hacks zoals behoud van RGB-verhoudingen of het handmatig masseren van verzadiging/ontzadiging via de tooncurvetoepassing. Dit is de bestaansreden voor de toonequalizer, die contrast corrigeert door een selectieve belichtingsaanpassing te gebruiken in plaats van een tooncurve.

Uit 2. leiden we af dat GUI-bedieningen waar mogelijk kleurverschijningsmodellen zouden moeten gebruiken.

Uit 3. leiden we af dat de kleurverschijningsmodellen die in de GUI worden gebruikt niet op pixels zouden moeten worden gebruikt maar zouden moeten worden geconverteerd zodat pixels in RGB worden afgehandeld. Dit is een typisch model-view-controller -paradigma dat consequent wordt genegeerd in alle beeldverwerkingsapplicaties. Blijkbaar is er onder ontwikkelaars een overtuiging dat het pixelkleurmodel 1:1 zou moeten overeenkomen met de kleurruimte van de GUI-controller.

Uit 4. leiden we af dat bedieningen die praktisch alleen bruikbaar zijn op een klein subset van hun waardebereik slechte wiskunde, slechte kleurmodellen, slechte priors gebruiken. De faalmodi zijn net zo belangrijk als wat er gebeurt bij het gebruik van de bedieningen in hun sweet spot.

Uit 5. bevestigen we gewoon punt 3.

Uit 6. hebben we een nieuw probleem opgeworpen: veel fotografen hebben geen retoucheer-/bewerkingsbedoeling (als in: een visueel einddoel), maar duwen en trekken alleen aan schuifregelaars in de richting die het beeld mooier lijkt te maken, en eindigen met een gelukkig toeval dat ze niet zouden kunnen reproduceren (of laten het beeld vallen omdat ze het niet kunnen bewerken). In dit geval is er geen metriek van succes voor de bedieningen omdat er geen verschil te berekenen is tussen bedoeling en resultaat, aangezien de bedoeling ongedefinieerd is. Daarom moeten we, wanneer we met gebruikersfeedback werken, kritisch zijn en onderzoeken wie er spreekt en van waaruit. Dat wil zeggen: niet elke gebruikersfeedback is goede gebruikersfeedback (en jarenlange ervaring is op zichzelf geen bewijs van iets).

En 7. is louter een herinnering aan de vorige sectie: het moeten dupliceren van een instelling is meestal een indicatie van slechte functie-opsplitsing, of je moet een goede reden hebben om dat te doen.

Dit zijn uiteraard allemaal de ideale gevallen om naar te streven. In de praktijk moet je verschillende kandidaten evalueren en de beste kiezen, die zelden aan alle vereisten zal voldoen. Maar om concurrerende kandidaten te evalueren, heb je eerst objectieve ijkpunten en schalen nodig. Dat zijn de ijkpunten die me in de loop der jaren duidelijk zijn geworden.

De eigenschappen van goede bewerkingsworkflows

Ik herinner me eindeloze e-mailketens, 9 jaar geleden op de Darktable-mailinglijst (nu ter ziele), over hoe je de GUI het best kunt reorganiseren, waarin mij werd verteld: “er is geen goede of foute workflow, alleen persoonlijke voorkeuren”. Absoluut relativisme is altijd dommer dan het klinkt. Die stommiteit gaat nu door op discuss.pixls.us. Het zijn echt dezelfde discussies, die dezelfde dingen zeggen over dezelfde kwesties, 9+ jaar in kringetjes ronddraaiend, en nog steeds geen enkele tastbare oplossing.

Ten eerste is er het voor de hand liggende geval waarin je een parametrisch masker definieert op, zeg, color balance RGB, en het instelt om RGB-waarden tussen wat dan ook en wat dan ook + epsilon in te maskeren. Dan ben je tevreden met de kleuren, maar je beeld ziet er een beetje donker uit, dus je gaat de belichting verhogen. Nu is je parametrische masker ongeldig en moet je het opnieuw doen, omdat belichting eerder in de pipeline zit dan color balance RGB, dus je hebt je hele bereik van RGB-codewaarden verschoven. Dit is circulair bewerken, het is het meest te voorkomen tijdverlies, en als je het wilt voorkomen, is er niet veel keuze: je moet op je pipelinevolgorde letten. Circulair bewerken is een objectief slechte workflow. Moet ik het rechtvaardigen?

Het houdt niet op bij maskers, omdat veel kleurmodules HDR-wit moeten normaliseren om kleurmodellen te kunnen gebruiken die alleen kunnen werken onder de aanname dat wit = {1, 1, 1}. Daarom plaats ik die later in de pipeline, na de globale helderheids- en contrastaanpassingen.

En dan is er het batchbewerkingsgeval: je hebt een reeks beelden om te bewerken, je wilt dat ze er consistent uitzien door de hele reeks heen, maar ze hebben kleine variaties in belichting, contrast en kleurtemperatuur. De enige manier om dat te laten werken is om een eerste stap van beeldnormalisatie te hebben, om individuele beeldvariaties af te handelen en ze naar een constante staat te converteren. Zodra dit gedaan is, kun je dezelfde stijl in batch toepassen of de geschiedenis van de latere modules erbovenop kopiëren-plakken, omdat die volgende stap genormaliseerde “constante” invoer zal krijgen en daarom consistente (zo niet constante) uitvoer zou moeten produceren. Het niet bereiken van die eerste normalisatiestap zal de volgende volledig onbetrouwbaar en onvoorspelbaar maken, wat het doel van batchbewerken tenietdoet. En zelfs met die schijnbaar-rigide workflow zul je nog steeds individuele fijnafstemming moeten doen als je echt consistente resultaten wilt. Dit is niet mijn mening, het is een simpel feit: als je consistente uitvoer wilt voor een set beeldwijzigingen met rigide instellingen, heb je consistente invoer nodig.

Maar daar zit een beperking aan, want wanneer je op HDR-signaal werkt, moet je je HDR -> SDR-tonemapping vroeg opzetten, zodat je daadwerkelijk kunt zien wat je in je beeld doet, zonder clipping van hooglichten. Er is dus een eerste stap van een overzicht nemen over je inhoud, en dan een stap van het finaliseren van de grenzen van het dynamische bereik. Wat betekent dat je altijd eerst de globale belichting zou moeten opzetten, kijkend naar de middentonen (en niets anders), en dan voorlopig je werkende tonemapper zou moeten opzetten. Dus die regel om te proberen je workflow 1:1 te verankeren op pipelinevolgorde (zelf verankerd op de invoervereisten van modules) heeft enkele uitzonderingen en kan niet zonder onderscheidingsvermogen worden toegepast.

Wat betekent dat je dat allemaal geleerd zou moeten hebben. Goede workflows komen van mensen die nadachten over hoe ze zich moesten aanpassen aan de gereedschappen die ze gebruikten, door er zowel vanuit het praktische als het theoretische oogpunt naar te kijken, en niet van de gelukzalige kampeerders die alle gewoonten die ze in de loop der jaren aannamen verkeerd interpreteerden als een workflow. Nogmaals, er gebeuren dingen onder het GUI-oppervlak, we schrijven geen brieven in een tekstverwerkingsapp. 9+ jaar lang heb ik in kringetjes op forums geschreeuwd: HET IS EEN PIPELINE, GEEN LOSGEKOPPELDE SET WILLEKEURIGE BEELDBEDIENINGEN. Volgorde doet ertoe. Als er maar één ding is dat je begrijpt in dit hele gebrabbel, zou het dit moeten zijn.

En ik denk dat Lightroom veel schade heeft aangericht aan de verwachtingen en het begrip van gebruikers door zijn interne pipeline te verbergen. Maar het werkt voor Lightroom omdat het gebruikers veel vrijheidsgraden ontneemt. Darktable heeft veel Lightroom-UI-semantiek hergebruikt terwijl het geleidelijk meer vrijheid en directe controle over de pipelineknopen bood (in de loop der jaren modulegewijze maskering introducerend, dan module-multi-instantiatie en herordening van relatieve instanties, dan rastermaskers herbruikbaar tussen niet-opeenvolgende modules, en ten slotte volledige moduleherordening), wat zowel oudgedienden als nieuwkomers heeft verward.

Het idee van een pipeline is niet eens specifiek voor digitale fotografie. Olieverfschilderen heeft ook een soort pipeline, waarbij je begint met het voorbereiden van je drager, deze bekleedt met primer om hem minder absorberend te maken, dan de contouren plaatst, dan de achtergrond voorbereidt, dan je glaceerlaag  aanbrengt en ten slotte de vernislaag opbrengt. Niemand die goed bij zijn hoofd is zou beginnen met de vernis en eindigen met de primer. Analoge fotografie heeft uiteraard een pipeline van chemische baden, timers, en dergelijke. En schilderapps zoals Photoshop, Gimp of Krita hebben een expliciete pipeline, gematerialiseerd door lagen die elkaar afdekken, van onder naar boven, met effectlagen die niets anders zijn dan parametrische pixelfilters die dynamische uitvoer produceren.

Maar op een of andere manier, doordat raw-fotobewerkingssoftware het losgekoppeld doet lijken van materiële realiteiten, lijkt het in digitaal oké om zonder structuur of methode te werken. De “niet-destructieve” bewerkingsworkflow is hier misschien ook liberaal geïnterpreteerd als YOLO , wat ook niet helpt. Alleen omdat je Ctrl+Z hebt, betekent niet dat plotseling alles vergevingsgezind is.

Om samen te vatten, goede bewerkingsworkflows zijn diegene die je voorspelbare resultaten geven bij elke stap terwijl je circulair bewerken vermijdt. Ze moeten geïnformeerd worden door pipelinevolgorde, maar ze kunnen er niet altijd 1:1 aan vasthouden, en je moet je oordeel gebruiken om te onderscheiden wanneer je je aan de pipeline moet houden en wanneer je moet afdrijven. Dat laat heel weinig ruimte voor persoonlijke voorkeuren.

De ethiek van digitale beeldverwerking

In analoge tijden werkten kunstenaars met fysieke media, en konden allerlei hacks uitvoeren en nieuwe technieken vinden om aangepaste resultaten te bereiken. Het was toegankelijk omdat je het medium waarmee je werkte fysiek kon aanraken. Kunstenaars waren vrij.

Digitale kunst is inherent gewelddadig, in zoverre dat ze kunstenaars vrijheid heeft ontnomen: nu kunnen ze niet zelf nieuwe technieken vinden, omdat hun kunst bestaat als pure informatie op een computergeheugen, dus ze zijn beperkt tot wat de applicaties voorstellen, en kunnen ofwel software-editors/-ontwikkelaars smeken om hun behoeften in overweging te nemen, ofwel leren coderen en ze zelf coderen (wat behoorlijk een toegangsprijs is als je geen technische achtergrond hebt in toegepaste wetenschappen of informatica). Het verlies van vrijheid kan worden verborgen door het feit dat alles wat in software gedaan wordt omkeerbaar is, dus fotografen beschadigen bijvoorbeeld geen negatieven permanent. Erger nog, software kan je productiever maken, dus het is een nettowinst vanuit een zakelijk oogpunt. Maar het zou niet moeten verbergen dat kunstenaars in een passievere consumentenpositie worden gezet dan voorheen, en gedomineerd worden door degenen die weten hoe en voor hen willen coderen, die mogen beslissen hoe ze voortaan kunst zullen maken.

“Geweld”, “onderdrukking van vrijheid”, “dominantie”… Je weet waar dit heen gaat: het heet onderdrukking. Een sexy onderdrukking die je belooft professionele resultaten te bereiken in slechts een paar klikken zonder naar de fotografieschool te hoeven gaan. Of, in de context van vrije software, een onderdrukking die welwillend en onschadelijk lijkt omdat er niets te betalen valt en er ingebouwde gegevensprivacy is. Maar niets daarvan is onverenigbaar met het feit dat wij, de ontwikkelaars controleren wat je het recht hebt te doen in/met je beelden, of niet, omdat wij de code controleren. Niet omdat we door gebruikers zijn verkozen, niet omdat we competent zijn voor de taak in kwestie (ik heb inmiddels vele malen hier aangetoond dat het Darktable-“team” niets anders was dan een stel onbenullige idioten met te veel vrije tijd), gewoon omdat we admin-rechten hebben op een of andere Github-repository. Dat geeft ons macht, en macht komt met verantwoording.

Dit zit me nu al enkele jaren achter in mijn hoofd, omdat het ook een ethisch dilemma wordt (bovenop alle eerder genoemde technische) om te beslissen welke functies toe te voegen, of te verwijderen, of te herstructureren. Tegelijkertijd is het niet mogelijk om iedereen tevreden te stellen en zou het uiteindelijk iedereen overweldigen met veel niche-gereedschappen die ze nooit zullen gebruiken (nogmaals: een boom verbergen in het bos). Dan is het ook meer code om te onderhouden, dus meer werk en een last voor de beheerders in de toekomst, met meer bedreigingen voor de stabiliteit van de software. Een Zwitsers zakmes bouwen dat constant halfkapot is, gaat niemand helpen.

Maar het blijft zo dat het verwijderen van bedieningen omwille van het vereenvoudigen van de GUI misschien gewoon vrijheid wegneemt, als we er niet zeker van zijn dat vergelijkbare functionaliteit op de een of andere manier blijft bestaan in de software. Artistieke vrijheid is geen handelswaar, het is een noodzakelijke frisse neus in samenlevingen die steeds meer afdrijven naar (techno-)fascisme, alweer.

Nogmaals, dat alles moet geval per geval worden gearbitreerd. Beeldverwerkingsapps in alle richtingen tegelijk laten gaan, proberen alle behoeften in één enkele app onder te brengen, zelfs de meest eigenaardige, gaat vijfpotige schapen bouwen die voor niemand praktisch bruikbaar zijn. Wat terugkeert naar mijn eerste sectie: het bouwen van generieke, veelzijdige en aannamevrije gereedschappen die op een gefactoriseerde manier aan veel verschillende behoeften kunnen worden aangepast. Industrie versus ambacht.

Productiviteit wordt bereikt door specialisatie (die, gecombineerd met standaardisatie, automatisering ontsluit), specialisatie wordt bereikt door duplicatie, duplicatie creëert GUI-opgeblazenheid en -rommel, opgeblazenheid en rommel zijn de vijanden van UX en creativiteit. De conclusie van dat alles is: laten we kiezen wat het waard is om te specialiseren, en dus de vrijheid van gebruikers belemmeren. Daarom is productiviteit het verkeerde paradigma: de natuurlijke conclusie ervan is onderdrukking.

Het tegenovergestelde van productiviteit is robuustheid en veelzijdigheid. Het is misschien langzamer (is het dat wel?), maar we kunnen een grotere variëteit aan gevallen aan met hetzelfde aantal gereedschappen, zonder willekeurig opties te verwijderen, en dus de vrijheid van de gebruiker. Het concept van robuustheid is al ontwikkeld in de context van sociale en klimaatinstabiliteit door Olivier Hamant, in zijn boek Antidote to the cult of performance. Robustness from nature (2024). Een van zijn belangrijkste kernpunten is dat de cultus van prestatie (of efficiëntie) alleen leidt tot competitie, die geweld bevordert, en in de onstabiele tijden die komen, hebben we samenwerking nodig. In een samenleving die meer dan genoeg produceert om ieders behoeften te dekken (maar het slecht verdeelt), wint prestatie ons niets behalve meer winst (nogmaals, slecht verdeeld). Maar wat het zeker produceert is burn-out, zowel bij mensen als in ecosystemen.

In software kan burn-out van verschillende dingen komen:

  1. technostress  gekoppeld aan te veel applicaties, gereedschappen, standaarden en paradigma’s om je aan aan te passen,
  2. informatieoverload , gekoppeld aan een overvloed aan GUI-widgets en gereedschappen om doorheen te navigeren,
  3. veranderingsmoeheid  gekoppeld aan te frequente updates die workflows veranderen.

Samengevat, het najagen van prestatie cascadeert in een reeks nadelen:

  1. vanuit een technisch oogpunt betekent het dat er meer gespecialiseerde gereedschappen gebouwd moeten worden die de GUI verrommelen, wat informatieoverload produceert,
  2. vanuit een UX-oogpunt impliceert het redelijk houden van rommel en overload het willekeurig kiezen wiens behoeften gedekt zullen worden (waarschijnlijk de meerderheid) en wiens behoeften genegeerd zullen worden, wat neerkomt op het wegnemen van artistieke vrijheid aan iedereen die te veel afwijkt van de mainstream: dit is een primeur in de kunstgeschiedenis, en geen enkele hoeveelheid softwarevrijheid maakt het minder gewelddadig,
  3. vanuit een marketingoogpunt hebben alleen professionals productiviteit nodig, en op dit moment lijken ze in grote meerderheid de voorkeur te geven aan commerciële software. Er is geen voordeel voor open-source om “nieuwe markten te winnen”, het zou eerder moeten streven om de achtergelaten niches te dekken. En ook, professionele fotografie sterft langzaam uit sinds de jaren 1980, dus ik ben er niet zeker van dat het nog lang een substantiële markt zal blijven.

Dat was een lange inleiding, maar in een Wereld waar iedereen denkt dat ze een ontwerper kunnen zijn, is het noodzakelijk om de volledige lijst van tegenstrijdige ontwerpvereisten helemaal uiteen te zetten om degenen te kalmeren die denken dat ze de volgende Leonardo Da Vinci zijn, en hun een gevoel te geven dat het simpele idee dat ze kregen alleen briljant lijkt omdat ze niet de volledige specificatienota hebben. Ik heb er te veel van hen in mijn mailbox en op mijn issue-trackers gehad.


Hoe het wordt afgehandeld in Ansel

Alle schermafbeeldingen zijn gemaakt op een 15,6’’-laptop.

Presentatie van globale modules

Laten we allereerst herhalen hoe de algemene presentatie van de donkere kamer opnieuw werd gedaan:

image
  • moduletabbladen kregen expliciete namen in plaats van cryptische pictogrammen,
  • tabbladen zijn (extern) geordend in voorgestelde workflowvolgorde, van links naar rechts, zodat gebruikers alleen de UI als gids hoeven te volgen,
  • binnen tabbladen zijn modules geordend in pipelinevolgorde (met een laag-“over”-logica, van onder naar boven), wat ook de algemeen aangeraden workflowvolgorde is. Het nieuwe “basis”-tabblad is een uitzondering, met modulesecties: binnen secties zijn modules pipelinegewijs geordend, maar de secties zelf zijn workflowgewijs geordend (nogmaals, laag-“over”-logica, dus van onder naar boven),
  • het “pipeline”-tabblad of de nodale grafiek van moduleordening maken alles ondubbelzinnig en tonen een direct beeld van de pipelineknopen zonder tussenliggende herordening,
  • de “favoriet”-tabbladen zijn volledig verwijderd, aangezien ze alleen doen alsof ze opgeblazenheid oplossen door er meer van toe te voegen.

Ondertussen zijn centrale werkbalken volledig verwijderd, waardoor een maximale hoeveelheid ruimte vrijkomt voor portretbeelden, op 16:9- en 16:10-schermen waar verticale ruimte echt kostbaarder is dan horizontale. Het gebruik van een globaal menu heeft opnieuw toegelaten om veel vreemde pictogramknoppen uit de werkbalken te verwijderen, en ze te vervangen door expliciete, tekstuele menu-items. Dus in volledig-schermmodus verlies je nu alleen de hoogte van de globale menubalk:

image

Meng- en maskeeropties, geünificeerd tussen modules, zijn verplaatst naar de linkerzijbalk. Dit maakt veel verticale ruimte vrij voor modules, waardoor de behoefte aan interne tabbladen wordt verminderd en veel rondklikken wordt voorkomen. Merk op dat de mengopties momenteel worden herschreven, nadat de masker-API volledig is geherstructureerd, vereenvoudigd en uitgebreid, dus dit is slechts een tijdelijk beeld.

Ansel-weergaven zijn behoorlijk uitvoerig, dus om te helpen onderscheiden tussen constante tekst (labels) en variabelen (waarden), is een syntaxiskleuring geïntroduceerd:

  • constante labels zijn wit,
  • variabele waarden zijn oranje.

Kleurkalibratie

In kleurkalibratie zijn de 3 tabbladen R, G en B samengevoegd tot hetzelfde mixer-tabblad, dat nu volledig verticaal past. Hetzelfde geldt voor helderheid, kleurrijkheid en Z&W, die nu zijn samengevoegd tot uitgangen.

Het mixer-tabblad heeft nu 2 alternatieve GUI-modi, naast de gebruikelijke (nu compleet genoemd) ;

De primaries-weergave is overgenomen door upstream Darktable, alleen maakten zij er een op zichzelf staande module van, wat stom is : de interne pixelwiskunde is precies een 3×3 matrixvermenigvuldiging, wat kleurkalibratie ook is, dus er was geen behoefte aan een extra module. Dit is opnieuw een probleem dat in de verkeerde laag is opgelost : het had een extra GUI-laag in een bestaande module nodig, zij maakten er een gedupliceerde module van.

In plaats daarvan implementeert Ansel het als een GUI-laag, wat betekent dat de gebruikelijke kanaalmixerparameters heen en weer worden omgezet naar de primaries-weergaveparameters, en de pixelwiskunde van de module is niet veranderd sinds 2021. Omwille van een volledig omkeerbare transformatie van de 3×3 matrix naar de primaries-weergave moest er een extra gain-parameter worden toegevoegd om de transformatie wiskundig te sluiten.

De simple-weergave is iets wat ik al enkele jaren op de plank had liggen : het opnieuw uitdrukken van de niet-gebruiksvriendelijke mixerparameters in termen van tintrotatie, chromavlak-uitrekking (kleurcontrast) en achromatische herschaling. De U/V stretch vervangt de oude Darktable-module color contrast die werkt in CIE Lab 1976, en de a- en b-chromaticiteit duwde/trok. De simple views gaat verder en laat je je eigen uv-chromaticiteitsruimte definiëren met de chroma (uv) axes rotation : ingesteld op 0° is u een groen-magenta-as en v een blauw-geel-as (vergelijkbaar met color contrast). Maar dan kun je hem draaien naar wat je maar nodig hebt, bijvoorbeeld rond -20° wordt de v-as vrij dicht bij een kleurtemperatuuras en de u-as bij de orthogonale tintas. Ik laat je verder met de documentatie.

Deze modus is bijzonder geschikt om overweldigend blauw podiumlicht te herstellen, veel gemakkelijker dan met de gebruikelijke kanaalmixer-UI :

After After
Before Before
Foto © Reinout Nonhebel, 2018
  1. door de V-as te comprimeren comprimeren we de gamut sterk op de blauw-geel-as, wat veel milder is voor de rest van de gamut dan een globale chromacompressie gebruiken,
  2. door de U-as te comprimeren comprimeren we de gamut ook op de magenta-groen-as, maar veel milder,
  3. de achromatische koppelingstint is ingesteld op diepblauw. Door de hoeveelheid koppeling te verhogen, brengen we een deel van blauw over naar de achromatische as, wat betekent dat we het tegelijk ontverzadigen en ophelderen, wat enorm helpt om het weer in gamut te krijgen, terwijl het algehele blauwe gevoel behouden blijft. Omgekeerd wordt de complementaire kleur donkerder en opnieuw verzadigd, maar aangezien die tegengestelde kleur geel is, en we de geel-blauw-as via V hebben gecomprimeerd, komen we ongeveer op dezelfde plek uit.

Dus deze simple herschrijving van de coördinaten van de kanaalmixerparameters levert 6 regelaars op in plaats van 9, en ze zijn veel betekenisvoller en gemakkelijker te bedienen. Dit is een UX-probleem dat puur vanaf de wiskundige kant is aangepakt, want dit is niets meer dan het opnieuw uitdrukken van een 3×3 matrix in een nieuwe orthogonale eigenvectorbasis, gedraaid op de achromatische RGB-as, wat betekent dat het puur begon vanuit een intuïtie uit de lineaire algebra. Vanwege de eigenschappen van deze nieuwe eigenvectorbasis (die door het ontwerp worden opgelegd) kon ik dimensies verwijderen en de resterende omzetten in betekenisvollere regelaars. En dat is wat ik bedoel als ik herhaal dat je UX-problemen niet kunt oplossen door alleen naar de GUI te kijken.

Split-toning RGB

De oude Darktable-split-toning-module werkte in de HSL-ruimte, die geen RGB-codewaarden groter dan 1 ondersteunt (dus geen scene-referred). Ook is het mengen van kleuren in HSL raar en voelt het als speelgoedfilters zodra je de instellingen begint op te voeren.

Tegelijkertijd gaat het huidige chromatische-adaptatieschema in Ansel uit van één enkele lichtbron. Echte scènes hebben echter altijd minstens twee lichtbronnen :

  1. de hoofdlichtbron, die de primaire lichtbron is, en die vooral zal wegen op de hooglichten en middentonen,
  2. gekleurde oppervlakken die licht van de hoofdbron weerkaatsen en het tinten, die als secundaire lichtbronnen fungeren, en die vooral zullen wegen op de schaduwen tot aan de middentonen.

Tot nu toe moest je, om deze situatie met gemengde lichtbronnen aan te pakken, instanties van kleurkalibratie dupliceren en ze in-/uitmaskeren. Maar proberen een binair masker te snijden (één gebied toegewezen aan de ene lichtbron, en de rest aan de andere lichtbron) is broos omdat het geen rekening houdt met de lichtmenging die rond de middentonen plaatsvindt.

Dus de nieuwe split-toning-module in Ansel biedt twee kanaalmixers en twee kleurtemperatuurcorrecties, en dupliceert de nieuwe GUI-modi van kleurkalibratie. Het laat je de helderheid van elke lichtbron definiëren, koppelt aan elke een kleurmatrix, en berekent een mix van beide matrices om op elke pixel toe te passen afhankelijk van diens luminantie.

After After
Before Before
© Luc Viatour, 2016

Op dit punt denk je misschien dat ik geobsedeerd ben door concertfotografie, maar dat is alleen omdat podiumverlichting de meest veeleisende opstelling is en geen enkele fout in de kleurpipeline vergeeft. Dat zijn al decennialang onopgeloste problemen; het is bekend dat blauwe lichten uiteenvallen in magenta, en ze vormen de ultieme kleurbenchmark.

Hier hebben we de temperatuur van de hooglichten aangepast voor natuurlijkere huidtinten, terwijl we de algehele blauwe omgeving in de schaduwen behielden. In zo’n scène is er geen wit dat je kunt bemonsteren, dus het mikken op natuurlijke huidtinten is de enige leidraad. Vervolgens doe je je best om de geest van de podiumverlichting te behouden (houd blauw blauw), terwijl je rekening houdt met de grenzen van je RGB-gamut. Zie voor meer details de documentatie.

Kleurprimaries

Zoals ik eerder al noemde, is de Darktable-module primaries slechts een duplicaat van de kanaalmixer met een andere UI. Maar er zijn gevallen waarin het bewerken van de hele kleurruimte via haar primaries het laagverzadigde bereik dat volkomen in orde was te veel beschadigt. Er was dus behoefte om primaire en secundaire kleuren (op de hoekpunten van de gamutkubus) te beïnvloeden op een manier die het centrum van de gamut uitsloot, maar toch de effecten soepel tussen beide gebieden mengde en de beeldgradiënten behield.

Dit werd bereikt door een RGB-LUT te bouwen in een nieuwe module : color primaries.

After After
Before Before
© Andrea (source )

Dit voorbeeld was ontworpen om rood en oranje minder overweldigend te maken, maar de blauwtinten dramatisch te verdiepen, om te laten zien hoe stabiel de kleurtransformatie is langs randen tussen verschillend gekleurde oppervlakken.

Aangezien de module intern dynamisch een LUT bouwt door de kleur van controleknopen te verschuiven, krijgen gebruikers de mogelijkheid om te bepalen hoe ver van de hoekpunten van de RGB-kubus de controleknopen zitten, via de schuifregelaar gamut coverage. Vervolgens laten 3 gladstrijkparameters toe om de kleurverschuivingen in RGB min of meer sterk te mengen, en om neutrale kleuren min of meer tegen de verschuiving te beschermen. Tot slot heeft de module een 3D-LUT-viewer:

image

De LUT-viewer toont kleurverschuivingen over de hele RGB-kubus van oorsprong naar bestemming. Hij kan rond de achromatische as worden gedraaid (azimut), of in een chromaticiteitsvlak-weergave worden gezet (axis tilt = 90°). Hij kan met muisgebeurtenissen worden ingezoomd, gepand en in 3D gedraaid, en gesneden om een beter zicht te krijgen op een bepaalde diepte. Tot slot kan de gegenereerde 3D-LUT worden geëxporteerd als een .cube cLUT-bestand om te hergebruiken in elke software die deze ondersteunt. Zie voor meer details de documentatie.

Kleuregalisator

Het Darktable-“team” nam mijn tweede (niet-werkende) prototype  voor color equalizer, begreep niet waarom het niet werkte, voegde nafilterstappen toe om de problemen te verbergen, en bracht het uit alsof het hun eigen werk was, zonder mij ook maar te crediteren. Ze mogen het houden : het is stront. En ik zet mijn naam sowieso niet op stront.

Kijk, het probleem van dat prototype is dat het de verzadigingsverschuiving toepaste in de dt UCS 22 HSB-kleurruimte, die ik in 2021 ontwierp . Deze kleurruimte wordt al gebruikt in color balance RGB voor verzadiging, en was erop gericht om de juiste hoeveelheid verduistering te vinden die moet worden toegepast op een kleur wanneer je zijn “verzadiging” verhoogt (eigenlijk zijn chroma, in strikte kleurwetenschappelijke termen), om te voorkomen dat het degradeert tot onnatuurlijke fluo- en neonkleuren, wat de typische valkuilen zijn bij het toevoegen van veel “verzadiging”. Dus in plaats van de gebruikelijke chroma-instelling die de kleurrijkheid vermindert bij constante luminantie of lichtheid, verduistert deze verzadigingsformule ook. En terwijl dat heel goed werkt op vlakke kleurvlakken, is het probleem dat beelden geen vlakgekleurde oppervlakken zijn, maar gradiënten hebben.

Rond 2022 werd mij gemeld dat de dt UCS HSB-verzadiging van color balance RGB een vreemde achromatische heldere zoom creëerde tussen heldere, verzadigde gele herfstbladeren en de diepblauwe lucht erachter. Het probleem was dat aan de rand geel licht van de bladeren en blauw licht van de lucht zich mengden tot achromatisch (zoals het hoort, aangezien het complementaire kleuren zijn) door een licht zachte lens of atmosferische nevel. Het verzadigingsalgoritme verduisterde geel en blauw aan weerszijden van de achromatische zoom, maar niet de zoom zelf, die nu helderder afstak. En daar is geen oplossing voor; het is geen algoritmische bug: het probleem is het kleurmodel, dat rekening houdt met waarneming maar niet met lichtmenging. Dus ik was alweer een auteur van weer een kapotte kleurruimte die me maanden kostte om te ontwikkelen en 20 uur rekentijd om de parameters van het model numeriek te fitten.

Proberen een kleuregalisator te implementeren die diezelfde kleurruimte hergebruikt maakte deze problemen alleen maar erger, want nu werd het effect tintgewijs aangestuurd, wat problemen op twee dimensies betekende in plaats van één. Om het probleem te verlichten, probeerde ik de zaken glad te strijken met behulp van geleide RGB-filters. Maar ik kon niet helemaal de toverformule vinden om een fatsoenlijke, robuuste menging te krijgen. Op dat moment besloot het Darktable-team het glimmende nieuwe ding uit het schap te ritselen, en toen begreep ik dat dit alleen in RGB kon gebeuren als het goed moest mengen en gradiënten behouden.

After After
Before Before
© baongoc124 (source )

De kleuregalisator erft dezelfde interactieve cursor als de toonegalisator, voor directe bewerking op het beeld door de tint van de pixel onder de cursor te bemonsteren, en scrollen zal de grafiek automatisch bijwerken. Knopen kunnen overal vrij worden toegevoegd, en vanuit de interactieve cursor gebeurt het toevoegen van een knoop bij de huidige tint met een rechtermuisklik.

De kleuregalisator laat toe een tintgewijze kleurverschuiving voor schaduwen, middentonen en hooglichten te definiëren. De kleurenkiezer laat toe te zien waar een gebied zich bevindt tussen de tonale regelaars. Dit maakt zeer fijnkorrelige controle mogelijk die, samen met dezelfde 3D-gladstrijking als color primaries, een zeer robuuste manier biedt om kleurverschuivingen te mengen. De chromaruis die het belangrijkste probleem was bij het definiëren van dramatische kleurverschuivingen, met de oude Darktable-module color zones (die werkt in CIE Lab 1976) of met het vorige prototype van color equalizer, komt niet meer voor.

Zoals bij color primaries creëert deze module dynamisch een 3D-RGB-LUT die op precies dezelfde manier kan worden bekeken en opgeslagen naar .cube-bestanden. Zie voor meer details de documentatie.

Tekenen

image

Moet ik nog meer zeggen ?

Ansel implementeert nu een prototype tekenmodule waarmee je rasterafbeeldingen kunt tekenen in een scene-referred pipeline met 32-bits penselen die HDR-kleuren (>100%) ondersteunen. Penselen ondersteunen dekking en flow (net als Photoshop), willekeurige spikkels, padgladstrijking en randvervaging, en kunnen worden gebruikt in schilder-, gum-, uitsmeer- en vervagingsmodi. Penseelgrootte, dekking, flow en hardheid kunnen worden gekoppeld aan de druk en kanteling van een Wacom-pen, of aan generieke cursorversnelling. Ze gebruiken correcte voorvermenigvuldigde alpha en slaan lagen op in 16-bits float TIFF-sidecarbestanden die in de meeste grote tekenapps kunnen worden bewerkt.

Er kunnen meerdere lagen worden gebruikt door meerdere instanties van de tekenmodule te instantiëren, die met behulp van de generieke Ansel-meng- en maskeeropties op het beeld worden samengesteld. Het kan ook worden gebruikt om elk willekeurig soort laag afkomstig uit welke software dan ook samen te stellen, zolang die als laag in 16-bits float wordt opgeslagen in het Ansel-TIFF-sidecarbestand. Het achtergrondbeeld (vóór de module) kan als achtergrondlaag worden geëxporteerd als je een referentiebeeld nodig hebt om in een andere software te tekenen en het resultaat weer te importeren.

Dit werd mogelijk gemaakt door de nieuwe pipeline-architectuur die een real-time modus mogelijk maakte. Toegegeven, het is nog steeds niet zo snel als Photoshop omdat er bij elke verversing van een penseelstreek andere modules na tekenen in de pipeline draaien.

Dat is de ultieme vrijheid om alles te bereiken wat knoppen en schuifregelaars je nooit zullen opleveren, of het nu gaat om doordrukken en tegenhouden, het herstellen van beschadigde delen (geklipte hooglichten, ontbrekende gebieden) of gewoon het mengen van fotografie en schilderkunst. Zie voor meer details de documentatie.

Fotografische korrel

De oude Darktable-module grain was echt onbevredigend, omdat het alleen luminantiekorrel toeliet en werd toegepast op het lichtheidskanaal van de CIE Lab 1976-kleurruimte. De resultaten waren vreemd en kwamen op geen enkele manier overeen met zilverhalide. Ik heb eindelijk de stochastische korrelsynthese  geïmplementeerd die ik in 2023 heb ontwikkeld in een nieuwe module: fotografische korrel. Dit splitst het lichtveld in virtuele zilverhalidekristallen en simuleert korrelsensoren gestapeld op lagen. Het werkt zowel voor Z&W- als kleurkorrel, hoewel ik enige afstand van mijn oorspronkelijke artikel moest nemen om kleur te verwerken.

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

Filmic

Al enkele jaren vertellen mensen me dat de stomme Darktable-modules sigmoid en het recentere AgX hun wat meer controle gaven. En geen van hen is in staat geweest me precies te vertellen controle waarover. Dus het kostte me lang om het uit te vogelen.

Sigmoid en AgX zijn geen revoluties, het zijn andere filmics :

  1. je zet kleuren om met een logaritme of een macht-shaper,
  2. je klakt er een S-vormige curve bovenop,
  3. dan doe je je best om te ontfronsen wat de tooncurve gedurende het proces met de chroma heeft gedaan,
  4. en tot slot maak je de shaper ongedaan.

Sigmoid en AgX hadden alternatieve modi binnen filmic kunnen zijn : ze doorlopen allemaal dezelfde stappen met licht verschillende prioriteiten en strategieën. Dat zou één enkele module voor dynamisch-bereikcompressie hebben opgeleverd, met verschillende modi afhankelijk van hoeveel fijnkorrelige controle gebruikers wilden. In plaats daarvan dupliceerden ze functionaliteit en voegden ze GUI-opgeblazenheid toe, zodat gebruikers nu moeten kiezen tussen base curve (die zelf al een gedupliceerde en gespecialiseerde variant van tone curve was), filmic, sigmoid en AgX om dezelfde taak te volbrengen, terwijl geen van deze eigenlijk aangeeft welke functionaliteit het biedt.

Het enige wat filmic het beste doet is expliciet omgaan met de grenzen van het dynamisch bereik, waardoor het kan worden gebruikt voor zwartpuntcompensatie bij het afdrukken. De twee andere behandelen ze als een bijproduct van de contrastinstelling. Aangezien de ontwikkelaars van de twee andere zich niet bekommeren om afdrukken, kun je erop rekenen dat dat enkele beperkingen op het ontwerp wegneemt, en enkele schuifregelaars in de GUI verwijdert. Het enige wat de twee andere beter doen is handmatige kleurregelaars bieden om verzadigings- en tintverschuivingsproblemen door de tone mapping heen te ontfronsen, maar ik vind echt niet dat dat niveau van kleurgranulariteit thuishoort in een __toon__mappingfunctie : het is een volledig gebrekkige workflow- en functie-opsplitsing.

Hoe dan ook, ik kwam er eindelijk achter dat de fijnere contrastcontrole voortkwam uit het feit dat sigmoid rechtstreeks een toe- en shoulder-knoopregeling biedt, terwijl filmic een globale latitude en offset gebruikt die onhandig te gebruiken is omdat het beide koppelt. Dit was oorspronkelijk ontworpen om het te koppelen aan echte datasheets van filmsoorten, want de latitude is een echt filmding, om misschien ooit echte filmsoorten te kunnen emuleren. Die dag is er nooit gekomen.

Dus ik loste het probleem in de GUI-laag op door een omzetting toe te voegen tussen latitude/offset en instellingen voor hooglichten/schaduwen, en nu laat filmic RGB je de positie van de toe-/shoulder-knopen rechtstreeks manipuleren :

image

Er is in het proces geen pixelwiskunde veranderd, de moduleparameters zijn nog steeds dezelfde als voorheen, er is geen nieuwe module gemaakt, het is slechts een tussenliggende GUI-omzettingsstap.

Conclusie

Alle nieuwe modules ondersteunen GPU-offloading via OpenCL. Ze zijn ontworpen voor robuustheid, en ik denk dat dat doel is bereikt. Ze hebben slechtere vorige modules vervangen, die werkten in CIE Lab 1976 en die al lange tijd hun grenzen en gebreken hebben getoond. Je draait nu een volledige RGB-pipeline in Ansel. Oude modules zitten nog steeds in het programma en zullen nog steeds draaien voor oude bewerkingen. Ook zijn de gekleurde schuifregelaars en tintgrafieken kleurbeheerd met behulp van het schermkleurprofiel.

De modules die ik recentelijk heb geïntroduceerd zijn geen glimmende nieuwe speeltjes om enthousiast over te worden. Ze zijn de conclusie van jarenlang nadenken over een consistente, coherente functie-opsplitsing die de scene-referred workflow helpt. Die scene-referred workflow is complexer dan de vorige display-referred, al was het maar omdat we “wit” moeten normaliseren voordat we een LUT of perceptuele kleurruimte ingaan, maar het is de enige manier om HDR-beelden, correct alpha-mengen voor maskers en fysisch-nauwkeurige pixelfilters die lichtmenging simuleren aan te pakken. Fysisch-nauwkeurige filters zijn robuust en produceren organische resultaten, zelfs tot dramatische instellingen doorgevoerd. Maar ze zijn vaak minder toegankelijk voor nieuwkomers en verontrustend voor ervaren retoucheerders die gewend zijn aan Lightroom en dergelijke.

Dit zal mijn laatste bericht op deze website zijn, want ik ga met pensioen als ontwikkelaar. Het heeft me te veel gekost : te veel stress, te veel burn-outs, te veel jaren besteed aan het opruimen van andermans stront en aan het lijden onder hun slechte beslissingen. Ik ben moe, meer dan je je kunt voorstellen. Ik haat programmeren en ik haat programmeurs. Ik ken er maar heel weinig die programmeren om dingen te bouwen of om problemen op te lossen; de meesten genieten er gewoon te veel van om kwaliteitstijd door te brengen met een computer, en veranderen in pyromane brandweerlieden die je niet kunt vertrouwen om dingen te ontwerpen. Ik haat technologie en zogenaamde “innovatie”: dit alles is gewoon een kapitalistische zwendel ontworpen voor oneindige groei in een Wereld waar de hulpbronnen beperkt zijn, en we doen alsof we problemen die door technologie zijn gecreëerd oplossen met nog meer technologie. Dat is krankzinnig. De opensource-wereld erft dezelfde mentaliteit, met inbegrip van het techno-solutionisme , want dat is het soort hersenrot dat 350 jaar kapitalisme voortbrengt, ook al heeft FLOSS niet de winsten om het te rechtvaardigen. Het zit vol leugens en vol stront, want libre betekent alleen vrijheid voor ingenieurs, en gebruikers kunnen naar de hel lopen. Het probleem is dat ik vroeger in die leugens geloofde, in die waarden : ze waren (en zijn nog steeds) de mijne. Maar beseffen dat ze slechts lege woorden zijn die worden herhaald in toxische “gemeenschappen” van blanke mannen van middelbare leeftijd met een B.Eng, M.Sc en Ph.D was een brute wekker. Wat doen we daadwerkelijk om gebruikers te empoweren die het daadwerkelijk nodig hebben ? Op welk punt is het achteloos vereisen om de CLI te gebruiken empowerend voor iemand die geen code kan lezen ? We dragen alleen maar bij aan het verdiepen van de kloof tussen de computergeletterde elites en de boeren. Vergeet niet, we maken hier fotografiesoftware, geen backendbibliotheek, geen serverinfrastructuur, maar een eindgebruiker-desktoptoepassing.

Ik heb mijn brein hier geleegd, om alles te loggen wat ik heb geleerd over het ontwerp van beeldverwerking, hoe ik het deed, en waarom. Het is belangrijk om te begrijpen dat gebruikers, en de meeste ontwikkelaars, alleen weten hoe één toepassing zich gedraagt op hun eigen beelden. Gedurende 8 jaar heb ik veel pathologische beelden ontvangen die mensen me stuurden, die gebreken en beperkingen van de tools aantoonden. Ik heb op dit moment ongeveer 45 GB van die beelden op mijn harde schijf. Dat geeft een compleet ander perspectief op de daadwerkelijke problemen dan wat alle blije kampeerders misschien hebben : ik ben de man die weet wat er stukgaat en wanneer. Ik ben de man die de problemen vinden. Ik ben de Cassandra  van het project. En het is vervelend om de hele tijd te moeten rechtvaardigen, aan mensen die de problemen niet zien, waarom dat ding dat veel eenvoudiger zou kunnen zijn niet veel eenvoudiger kan zijn omdat er pathologische gevallen zijn waarin we ons moeten aanpassen aan de variabiliteit van de invoer. Om je aan de invoervariabiliteit aan te passen heb je gebruikersparameters nodig in plaats van hardgecodeerde constanten. Vandaar GUI-opgeblazenheid. Het soort GUI-opgeblazenheid dat je niet kunt vermijden zonder de bruikbaarheid te schaden.

Je kunt de kwaliteit van een ontwerp niet beoordelen als je de vereisten ervan niet kent. “Ik vind het leuk” of “ik vind het niet leuk” is irrelevant. Niemand draagt graag een gordel, het is nog steeds goed ontwerp als je bedenkt hoeveel levens het heeft gered. Elke echte kritiek kan alleen gaan over hoe de voorgestelde oplossing het doel bereikte, wat alleen kan gebeuren als je het doel kent. In beeldverwerking maakt de gemengde aard van de vereisten het moeilijk om te vermijden dat je op een gegeven moment in de wiskunde en haar hiërogliefen duikt, en dat is waar je mensen kwijtraakt. Maar dat weerhoudt hen er nog steeds niet van hun nutteloze mening te geven, te beginnen met “Ik ben geen programmeur”/“Ik ben geen wiskundige”/“Ik ben geen kleurwetenschapper”… “MAAR”… [voeg wat willekeurig hersengeruis in]. Opensource-code doen, waar alles openbaar is, laat dat soort ruis overal toe : het is echt vermoeiend, en er zijn veel keren waarop ik wenste dat de broncode gesloten was, alleen maar om in vrede te kunnen werken. De meeste van die kerels menen het goed en willen gewoon deel uitmaken van iets, maar bijdragen aan informatie-overbelasting helpt niet en draagt alleen bij aan het creëren van vermoeidheid. Communicatie is waar elk teamwerk aan productiviteit verliest

Ontwerp gaat niet over luisteren naar wat mensen leuk vinden. Als 65% van je testpanel tekst in het rood geschreven leuk vindt, en 72% tekst over een rode achtergrond leuk vindt, schrijf je dan rode tekst over een rode achtergrond ? Dat slaat nergens op. We doen niet aan politiek en proberen geen kiezers te behagen tijdens een campagne, we zoeken naar langetermijn-/toekomstbestendige oplossingen voor problemen. Ontwerp gaat over luisteren naar wat mensen nodig hebben, wat ze zelden duidelijk kunnen uitdrukken, en manieren vinden om die behoeften te factoriseren. Dus de enige statistieken die de moeite waard zijn om te berekenen gaan over de gebruiksscenario’s : hoe de software wordt gebruikt, wat de meest voorkomende pijnpunten zijn, en wat de grondoorzaak ervan is. Los dan de grondoorzaak op, die ver verwijderd kan zijn van de daadwerkelijke manifestatie van het probleem. Ook dat is een echte en kostbare vaardigheid : de draad van het probleem volgen, via aanwijzingen en geurtjes, om de echte oorsprong te ontdekken, en niet alleen het eindprobleem oplappen of eromheen werken. “Luisteren naar gebruikers” betekent niet luisteren naar elk individu en hun geven wat ze individueel willen : we bieden geen therapie. Het betekent luisteren naar de hele gebruikersbasis, en de gemeenschappelijk gedeelde behoeften en pijnpunten identificeren om een gefactoriseerde oplossing te bedenken die de meeste behoeften dekt met de minste hoeveelheid technologie. Dit impliceert niet dat je iedereen die meer dan een standaarddeviatie van het gemiddelde afwijkt moet negeren, maar die mensen zullen misschien hun toevlucht moeten nemen tot methoden die niet op maat zijn gemaakt en geoptimaliseerd voor hun behoeften.

Ontwerp bestaat niet op een eiland : er zijn andere beeldbewerkingsapps in de buurt. Het is opnieuw moeilijk in te schatten wanneer je ontwerp anderen zou moeten kopiëren omdat gebruikers gewend zullen zijn aan hun UI-semantiek, en wanneer je moet afdrijven omdat het probleem dat je probeert op te lossen te verschillend is van wat de concurrentie doet, of je typische gebruiker te verschillend is. Opensource wordt voortdurend heen en weer geslingerd tussen de verleiding om de commerciële leiders die ze zo dierbaar haten (maar in stilte naar streven te zijn) 1:1 te kopiëren, en het verlangen om iedereen te slim af te zijn terwijl ze het wiel opnieuw uitvinden (vaak op een slechtere manier). In dat alles is je Poolster om jezelf, elk uur van elke dag, af te vragen : wat is het probleem dat we proberen op te lossen, en wie zijn de mensen die ermee te maken hebben ? Zo kun je dingen aanpassen aan je publiek, in plaats van te vervallen in cargocultussen  en oplossingen over te nemen omdat ze succesvol zijn geweest in een context die je niet echt begrijpt en niet noodzakelijkerwijs de jouwe is.

Mijn belangrijkste conclusie uit al die jaren is dat het toepassen van kleurtransformaties op pixels in een andere ruimte dan RGB gedoemd is te mislukken, zoals het voorbeeld van colorbalance RGB laat zien : hoewel het misschien een geweldig idee klinkt om “kleur”-werk (zoals tint/chroma) te decorreleren van tonaal werk, zal het altijd slechts een kwestie zijn van het kiezen van je pijn. Chroma verhogen bij constante lichtheid degradeert kleuren tot fluo, verzadiging verhogen bij constante helderheid (en dus altemaal verduisteren) respecteert de lichtmengingstheorie niet, en beide produceren chromaruis door de instabiele aard van tinthoeken. Maar dan is RGB niet perceptueel gelijkmatig, en de groenige reeks van elke HSL/HSV-tintschaal beslaat ongeveer 30 % van de ruimte, terwijl groen slechts 1/6de is van de perceptuele tintring. De enige oplossing is de GUI in perceptuele kleurmodellen te behandelen, en op de een of andere manier naar RGB om te zetten voordat je het op pixels toepast. Wat extra abstractiegymnastiek voor ontwikkelaars vereist. En dat is duidelijk niet hun sterkste kant, aangezien het wiskundeniveau vrij laag is.

Ik heb al een opvolger, maar de toekomst van Ansel zal een coöperatie moeten zijn waar gebruikers ontwikkelaars eerlijke werkomstandigheden garanderen, en ontwikkelaars gebruikers garanderen dat in hun behoeften zal worden voorzien, in een wederkerigheid van wederzijdse verantwoordelijkheden. We kunnen niet zo doorgaan, het is niet gezond. En met “zo” bedoel ik enerzijds de “hobbyontwikkelaar” met nul verantwoordingsplicht, en anderzijds de opgebrande eenzame ontwikkelaar die onder de armoedegrens leeft om dingen enigszins voor elkaar te krijgen. Dat paradigma heeft alles opgeleverd wat het kon, het kan niet worden bijgesteld. Dezelfde oorzaken zullen alleen maar leiden tot de gevolgen die we al kennen : opensource is waardeloos. Als je meer wilt, zal dat paradigma moeten veranderen. Opensource is aan de ene kant een dictatuur van ontwikkelaars (zij die weten en kunnen) over gebruikers (zij die nodig hebben), maar aan de andere kant is het uitbuiting van wie werkt door wie neemt. Dat voedt alleen maar wederzijds wrok, stiekeme minachting en betutteling. Iedereen verliest.

Het alternatief is de huidige verklotting van bedrijfsplatforms en het technofascisme dat het momenteel mogelijk maakt. Je bent gewaarschuwd.


Translated from English by : 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  ↩︎