Introdução

Ferramentas vs. Máquinas, Ofícios vs. Indústria

Em seu livro, A Sociedade Tecnológica (1954), Jacques Ellul apresenta a diferença entre o período pré e pós-revolução industrial da seguinte forma:

A era pré-industrial é o reinado da ferramenta e do artesanato. A propriedade principal das ferramentas é serem genéricas, versáteis e adaptáveis. Cabe ao artesão desenvolver suas habilidades para fazer as ferramentas seguirem sua intenção, de modo que a mão compense as limitações do instrumento. Esse conceito ainda é bem conhecido pelos músicos hoje: você tem que praticar, aprender, tentar, falhar, tentar de novo… não há atalhos. Ellul enfatiza a ideia de parcimônia que acompanha as ferramentas: os recursos são limitados, então seu conjunto de ferramentas é praticamente definido pelo que você pode pagar, carregar, dominar e construir localmente. As tendências mudam lentamente e são locais, porque usam recursos locais e se adaptam a necessidades locais, e as ferramentas seguem o mesmo padrão. As ferramentas são heranças passadas de mestre para aprendiz, de pai para filho. Elas não se tornam incompatíveis nem obsoletas.

A era industrial é o reinado da máquina. Ela vem de uma cultura de padronização e massificação. A máquina é muito mais produtiva porque é especializada em uma tarefa, mas é inútil para todo o resto e raramente pode ser adaptada a outro uso. Quando as necessidades de produção mudam, a máquina é substituída por outra porque não serve para mais nada. Esse não é mais um esquema parcimonioso, e ele é permitido porque os recursos são muito mais baratos e a produção em massa possibilita economias de escala. Então, os humanos se tornam os servos da máquina, e o artesanato se torna um luxo.

Produções que costumavam ser feitas em casa ou em pequenas oficinas, em um contexto familiar, são transferidas para grandes fábricas, onde há espaço suficiente para as máquinas. Aliás, isso teve efeitos bem concretos sobre como organizamos nossa vida cotidiana, inclusive quando e quantas vezes comemos1, bem como os padrões de sono2. Então não é exagero dizer que a revolução industrial também mudou profundamente a maneira como pensamos, o que consideramos normal ou evidente.

Isso me tocou porque é assim que eu vinha desenvolvendo ferramentas de edição de cor, intuitivamente, desde que comecei: tentando construir ferramentas genéricas que se baseavam no menor número possível de suposições para se manterem versáteis, ao mesmo tempo em que davam controle refinado sobre os parâmetros da imagem, e, em última análise, apoiando-se nas habilidades dos artesãos em vez de em ferramentas semiquebradas, não validadas e automagicamente milagrosas que só funcionam em casos ideais.

Fotografia digital : automatizar ou apreciar o processo ?

Nunca entendi a paixão de muitos fotógrafos, especialmente os mais tecnófilos, por fluxos de trabalho de apertar botões e procedimentos automatizados. Aprendi e ensinei piano, e estou acostumado ao paradigma do cale a boca e pratique : treinar para desenvolver e manter a agilidade, e então repetir os mesmos poucos compassos várias e várias vezes até o som sair certo. Trabalhando a qualidade, a textura e a expressividade do som, através da quantidade de peso que você coloca nas teclas, da velocidade do ataque, do movimento do pulso e do antebraço. Usando seu corpo para movimentos refinados e treinando-o além de suas capacidades atuais, transformando gestos muito pouco naturais em reflexos. E, finalmente, aprendendo a ouvir na sua mente o som que você está buscando, antes mesmo de mover as mãos. Todas essas coisas que nunca serão redutíveis a controles deslizantes e botões de interface, métricas, variáveis ou algoritmos.

A maneira como muitos fotógrafos abordam a edição de fotos soa como se eles tivessem sido punidos pela fotografia digital porque agora precisam usar um software para obter suas fotos. Então isso deveria ser reduzido a um procedimento sem alma onde tudo deveria ser automatizado, se possível. Trocamos predefinições e receitas, alguns até as vendem. E agora temos IA para emular um estilo ou outro. Onde está a alegria em industrializar a criação artística ? Qual é o sentido de ter um hobby que parece o fardo de ter que revelar suas fotos ? A arte é um processo, não um procedimento. Que mente doente projetaria um robô que faz cerâmica, gravura ou arranjos florais no seu lugar ? Que tal usar o software como uma oportunidade de finalizar a aparência das suas imagens de acordo com seu gosto e sensibilidade ? Será que perdemos o prazer bruto de fazer as coisas nós mesmos, mesmo que mal ? Em que idade esse apetite se perde ?

Reconheço, lutar contra um software de edição de fotos é uma experiência frustrante, mas você precisa entender contra o que está lutando. É apenas a dificuldade intrínseca do seu ofício e a sua falta de habilidade, ou é o design ruim da ferramenta ? Quando você tem dificuldades em um piano de 25 k€ que acabou de passar pelo técnico de pianos, você sabe que o instrumento não é o problema. Mas com software, como você sabe ? Bem, você não pode saber até se comprometer totalmente com o paradigma do cale a boca e pratique. Bons retocadores conseguirão bons resultados com qualquer software, a diferença está em quanto tempo isso vai lhes tomar. E, bem, às vezes você tem que fazer muita cobertura para os modelos de cor quebrados dos aplicativos de edição.

Ferramentas na interface de edição de fotos

Em termos de design de UI, a parcimônia de ferramentas genéricas e versáteis é a melhor maneira de evitar ser sobrecarregado por dezenas de recursos que se ocultam uns aos outros, se sobrepõem em funcionalidade e apenas poluem seu campo visual. É o feng shui de software. Mas então, a natureza das ferramentas muda um pouco.

Há duas maneiras de pensar nos controles de cor de processamento de imagem : a partir de seu uso funcional, e a partir da forma como permitem manipular as propriedades da cor. A partir de seu uso funcional :

FunçãoMétodos
Reduzir ruídoFiltragem por wavelets, médias não-locais, filtro bilateral, filtro guiado, difusão,
DesborrarDeconvolução de Richardson-Lucy, pirâmide gaussiana/laplaciana, filtro passa-alta, filtragem por wavelets, contradifusão, máscara de nitidez
BorrarFiltragem por wavelets, difusão, filtro bilateral, filtro guiado
ClarearCorreção de exposição, curva tonal, função de transferência de potência (“gama”), misturador de canais
Balanço de brancoNormalização por canal, transformação de adaptação cromática, misturador de canais
Deslocamento de corMisturador de canais, lift-gamma-gain, slope-offset-power, rotação de matiz, LUT
Realce de coloridoSaturação, croma, vibração, LUT
Realce de contrasteCurva tonal, funções de transferência sigmoidais, normalização de faixa (“níveis”), LUT
Compressão de faixa dinâmicaIgual ao contraste, mas em modo “reduzir” em vez de modo “aumentar”

Note que o deslocamento de cor poderia ser redividido em dois modos: corretivo (que exige modelos de luz) e criativo (que exige modelos perceptuais). Não iremos tão longe.

Se abordarmos a mesma lista a partir do outro ponto de entrada, a forma como permitem manipular as propriedades da cor, obtemos :

MétodoFunções
Filtragem por waveletsReduzir ruído, Desborrar, Borrar
DifusãoReduzir ruído, Desborrar, Borrar
Misturador de canaisClarear, Deslocamento de cor, Balanço de branco
LUTRealce de contraste, Deslocamento de cor, Realce de colorido
Curva tonalClarear, Realce de contraste, Compressão de faixa dinâmica

Não refiz a lista inteira, mas você entendeu a ideia : quer você queira classificar sua lista de ferramentas por método ou por função, você não acaba com uma correspondência 1:1, exceto por algumas poucas. Então nenhum desses mapeamentos permite que você fatore sistematicamente suas ferramentas em elementos unitários de interface, de modo a honrar o princípio da parcimônia.

E então, o processamento de imagem não é apenas um conjunto de ferramentas em uma caixa, é na verdade um pipeline de filtros de pixels que precisam ser inseridos como nós de grafo em uma ordem que corresponda aos requisitos de entrada dos filtros. Aqui está (simplificado):

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

E, por último, mas não menos importante, o problema que ninguém vê: a matemática. Por exemplo, um filtro guiado aplicado a uma máscara de opacidade e guiado pela imagem RGB (como no refinamento de máscara do Ansel/Darktable) não tem a mesma matemática que um filtro guiado aplicado a uma máscara de luminância e guiado por si mesma (como no equalizador de tons), ou uma imagem RGB completa guiada por si mesma (como no dehaze). Esses precisam ser implementados várias vezes, com diferentes tipos de entrada e diferentes tipos de otimizações. O mesmo se aplica aos métodos que trabalham em imagens não demosaicadas: temos que levar em conta o fato de que não temos um sinal RGB completo em cada sensel, e as matrizes XTrans precisam de uma matemática especial, diferente da de Bayer.

Então, dado que:

  1. funcionalidades têm métodos diferentes,
  2. métodos não podem ser reduzidos a uma única funcionalidade,
  3. todos eles são inseridos como nós em um pipeline onde a ordem importa,
  4. métodos têm variações de implementação dependendo de seu sinal de entrada, isto é, de sua posição no pipeline,
  5. os usuários querem se divertir sem ter que aprender nada,
  6. a desordem da interface não serve a ninguém e cansa a todos,

…temos um problema: como dividir os recursos e organizá-los como uma interface coerente?

Em um ambiente profissional, onde se pode esperar que os usuários saibam como construir um pipeline por conta própria e entendam os meandros de seus nós, você pode seguir o caminho do DaVinci Resolve e construir um editor nodal. Então você constrói um nó por método, e trata internamente as variantes de implementação verificando o tipo do sinal de entrada. Essa é a maneira mais minimalista, porque há zero duplicação de interface: apenas um banco de nós, e os nós podem ser dispostos em paralelo em vez de forçados sequencialmente. Mas isso exige usuários especialistas.

A maneira do Lightroom/Capture One é ocultar completamente que existe sequer um pipeline, e fornecer uma interface plana. Então a multi-instanciação de nós é feita através de máscaras: adicionar novas máscaras permite atribuir a elas um subconjunto dos controles do software para editar seletivamente as regiões mascaradas. Mas isso também vem acompanhado do fato de que nenhum desses aplicativos permite edição linear referente à cena (scene-referred), o que torna o borramento, o desborramento, a redução de ruído e as transições de máscara propriamente ditas problemáticos.

O Ansel está em um caminho do meio. Primeiro, agora há um protótipo de editor nodal:

image
image

Isso nos permite mostrar explicitamente a ordem do pipeline, reordená-lo manualmente e alterar as predefinições de ordenação, de uma forma que também mostra as entradas e saídas. Anteriormente, tínhamos apenas a pilha de módulos de interface na barra lateral direita, que meio que sugeria a ordem do pipeline se lida como uma pilha de camadas, mas ela era frequentemente mal utilizada pelos usuários como um mero recurso de reordenação da caixa de ferramentas da interface.

E então, a divisão de recursos é híbrida:

  • Os módulos equalizador de contraste, contraste local e difusão ou nitidez são intrinsecamente duais em sua natureza: eles podem aumentar ou diminuir o contraste local e a nitidez dependendo de seus parâmetros. O equalizador de contraste tem até um método de redução de ruído, o que faz sentido porque a aplicação de nitidez aumenta o ruído, então o lugar certo para mantê-lo sob controle é onde ele é criado. Esses são módulos orientados a método.
  • O balanço de branco duplica a funcionalidade da parte de adaptação cromática da calibração de cor. O balanço de branco é uma simples normalização por canal que acontece no RGB do sensor, e é necessário por alguns métodos de interpolação cromática (especialmente para sensores XTrans), enquanto a calibração de cor realiza uma compensação de iluminante muito mais precisa perceptualmente no espaço CIE CAT16. Esse espaço é definido a partir do espaço CIE XYZ 1931, que só obtemos após a perfilagem de cor de entrada (e isso requer uma imagem demosaicada para funcionar). Há razões e necessidades diferentes para ambos, e eles devem ficar em lugares diferentes no pipeline. Esses são módulos orientados ao pipeline: embora pareçam funcionalmente semelhantes, suas razões de existência e seus requisitos internos (e matemática completamente diferente) os tornam muito mais diferentes do que você poderia imaginar. O mesmo se aplica aos vários módulos de redução de ruído: alguns funcionam sobre a entrada RAW, outros não, e alguns funcionam melhor sobre sinais não lineares.
  • O balanço de cor foi projetado como um módulo de cor unificado, aplicando uma ASC CDL  (slope-offset-power) estendida, e então tratando a saturação e o croma global e por luminância, substituindo assim módulos anteriores do Darktable como contraste-brilho-saturação, vibração e velvia (todos trabalhando em CIE Lab 1976). Tomado isoladamente, ele é um módulo orientado à funcionalidade, mas não é o único módulo de deslocamento de cor. Os outros módulos de deslocamento de cor usam métodos muito diferentes (matrizes, LUTs ou controles por matiz), que são 3 a 9 vezes menos custosos computacionalmente de executar, e operam em espaços de cor diferentes.

O Ansel herda seu conceito de módulos do Darktable: os módulos são ao mesmo tempo um widget de caixa de ferramentas da interface e um filtro de pixels inserido em algum lugar do pipeline. Assim, projetar módulos muito pequenos (em termos de recursos) fará surgir muitos widgets de interface de alto nível na barra lateral direita, enquanto projetar módulos muito grandes fará menos widgets de alto nível, mas eles serão mais altos ou usarão mais abas internas. A segunda opção ainda pode ser preferível porque os módulos de interface de alto nível funcionam como bandejas, então menos bandejas que sejam funcionalmente consistentes ajudam a entender melhor a divisão de recursos de alto nível (como um sumário).

Mas não para por aí, porque, de novo… nós. Um módulo deve ser um conjunto de controles de cor que sejam consistentes como um nó mascarado multi-instanciado no pipeline. Não adianta encher um módulo com dezenas de recursos onde metade deles faz sentido como configurações globais, e o restante apenas na localidade da máscara; eles só consumirão ciclos de CPU à toa uma vez instanciados.

E, finalmente, há o desempenho. Controles de cor que precisam funcionar em algum espaço de cor específico precisarão de uma conversão de cor de ida e volta, o que consumirá ciclos de CPU, então é melhor que todos eles rodem no mesmo módulo se fizerem sentido juntos em termos de funcionalidade. Além disso, qualquer novo módulo executará um novo laço sobre os pixels, o que significa que moverá a imagem mais uma vez para a memória cache da CPU de/para a RAM. Portanto, agrupar recursos no mesmo laço evita abuso adicional de largura de banda de I/O e ajuda no desempenho.

Então, se recapitularmos toda a lista de restrições, aqui está, é um desafio realmente difícil de resolver:

  1. devemos sempre nos esforçar para construir o menor número de elementos de interface porque uma interface desordenada torna tudo difícil de encontrar (e cognitivamente sobrecarregante): o melhor lugar para esconder uma árvore é na floresta,
  2. a desordem que construirmos deve ser organizada do global para o local, do genérico para o específico, do frequentemente usado para o de nicho, porque é a maneira mais fácil de raciocinar sobre ela: pensar na estrutura da interface como um “sumário” é o melhor que consegui elaborar até agora,
  3. mas fazer disso uma regra de dividir sistematicamente os recursos com base na funcionalidade ou no método ainda acaba com duplicações em ambos os casos, a menos que sigamos na direção do editor totalmente nodal, façamos tudo baseado em método e transfiramos a responsabilidade de construir pipelines para o usuário especialista,
  4. os módulos devem ser projetados como orientados à funcionalidade sempre que possível, mas muitas limitações se aplicam :
    1. o tipo do sinal de entrada, que determina a posição no pipeline, e pode nos forçar a priorizar o orientado ao pipeline e a duplicar ferramentas,
    2. a relevância e a consistência do conjunto de controles do módulo quando multi-instanciado e mascarado: um módulo deve ser uma unidade consistente de fluxo de trabalho de edição, não um cabide para espremer tudo. Especialmente, se fizer sentido (em termos de fluxo de trabalho) aplicar uma máscara em apenas um subconjunto dos recursos do módulo, então esse subconjunto deveria ser seu próprio módulo,
    3. questões de desempenho (ida e volta de espaço de cor, mapeamento de gamut da saída, largura de banda de I/O): não podemos pensar na ergonomia do usuário apenas do lado da interface; a velocidade de execução também faz parte da ergonomia,
    4. a natureza matemática das operações realizadas : alguns métodos (especialmente nitidez/contraste local) podem ter efeitos opostos dependendo do sinal de seus parâmetros, alguns métodos são pouco adequados para serem agrupados juntos no mesmo filtro de pixels,
  5. finalmente, a quantidade de cliques/passos de rolagem necessários para alcançar um recurso frequentemente usado precisa ser considerada, porque o eixo genérico -> específico nem sempre é paralelo ao eixo frequentemente usado -> nicho. Então, embora a organização de alto nível do genérico -> específico faça sentido cognitivamente, ela nem sempre é a mais ergonômica.

Todos esses requisitos antagônicos precisam ser arbitrados caso a caso, olhando para a totalidade do pipeline, caso contrário não construímos um aplicativo de fluxo de trabalho, mas um registro de plugins. Eles vivem na encruzilhada entre programação de baixo nível, matemática, fluxo de trabalho de retoque e ergonomia de interface, e nenhum desses conceitos é, em geral, mais importante do que os outros. No entanto, algumas dessas restrições são mais facilmente compreendidas do que outras, o que fará com que recebam muito mais atenção, num típico efeito poste de luz : continuar caçando problemas na camada que você entende enquanto descarta completamente sua verdadeira origem porque ela toca uma camada que você não entende/sobre a qual não sabe nada. É por isso que é uma verdadeira dor de cabeça trabalhar com “designers de UX”, porque eles tipicamente não têm a bagagem para enxergar além da interface e muitas vezes não se importam que exista um motor a ser controlado por baixo da UI. Você não pode simplesmente escolher cancelar a gravidade porque gostaria de remover o controlador de arfagem  para uma UI mais simples.

O design é um processo de refinamentos iterativos sob o feedback dos usuários. Algumas dessas iterações redesenharão do macro ao micro (da arquitetura global do aplicativo aos controles internos do módulo), e algumas redesenharão do micro ao macro, até convergir para uma semântica unificada e uma divisão de recursos coerente. É tolice pensar que alguém vai acertar de primeira, ou pensar que apenas um dos níveis micro/macro precisa de ajuste. É uma ponte a ser construída de ambas as extremidades ao mesmo tempo, encontrando uma maneira de fazê-las se encontrarem no meio.

As propriedades de bons controles de cor

Dos meus 17 anos de experiência editando fotos, e 8 anos de experiência estudando e experimentando matemática de processamento de imagem, há algumas coisas que aprendi sobre o que é um bom ou um mau controle de cor. Por “controle de cor”, quero dizer alguma forma de alimentar a intenção do usuário a um algoritmo de pixels que editará uma propriedade visual de uma imagem. Bons controles de cor :

  1. são ortogonais entre si, o que significa que um controle altera uma dimensão de cor em qualquer momento dado e não força você a compensar em outro controle,
  2. têm escala uniforme de uma perspectiva perceptual, o que significa que ir de “0” a “1” mudará o resultado visual na mesma medida que ir de “1” a “2”. Infelizmente, isso nem sempre é possível, porque a matemática e a física odeiam você.
  3. escalam graciosamente à medida que a faixa dinâmica aumenta, o que descarta praticamente todos os modelos de aparência de cor (CIE Lab 1976, CIECAM 16, dt UCS 22), construídos para SDR sobre conjuntos de dados registrados a partir de amostras de cor pintadas.
  4. degradam graciosamente à medida que aumentamos a magnitude das mudanças, o que significa que podem ficar exageradas, mas não podem mudar o conteúdo da imagem nem criar artefatos,
  5. preservam os gradientes da imagem, o que significa que mantêm as variações locais tonais e cromáticas como variações, em vez de achatá-las, fazê-las ultrapassar (criando halos, franjas, ruído etc.) ou invertê-las.
  6. permitem que os artistas cheguem o mais perto possível de sua intenção no menor tempo possível.
  7. não são duplicados.

Do item 1., deduzimos, por exemplo, que qualquer tipo de curva tonal RGB é ruim, porque ela dessaturará as realces e saturará as sombras como um subproduto da quantidade de contraste (de luminância) que você adicionou, e você não pode controlar (ou descorrelacionar) a quantidade de mudança de saturação que obterá para a quantidade de mudança de contraste que pediu, exceto por gambiarras como a preservação de razões RGB ou a manipulação manual da saturação/dessaturação através da aplicação da curva tonal. Essa é a razão de existência do equalizador de tons, que corrige o contraste usando um ajuste seletivo de exposição em vez de uma curva tonal.

Do item 2., deduzimos que os controles da interface devem usar modelos de aparência de cor sempre que possível.

Do item 3., deduzimos que os modelos de aparência de cor usados na interface não devem ser usados sobre os pixels, mas devem ser convertidos de modo que os pixels sejam tratados em RGB. Esse é um típico paradigma model-view-controller  que é consistentemente ignorado em todos os aplicativos de processamento de imagem. Aparentemente, há uma crença entre os desenvolvedores de que o modelo de cor dos pixels deveria corresponder 1:1 ao espaço de cor do controlador da interface.

Do item 4., deduzimos que os controles que são praticamente utilizáveis apenas em um pequeno subconjunto de sua faixa de valores estão usando matemática ruim, modelos de cor ruins, priors ruins. Os modos de falha são tão importantes quanto o que acontece ao usar os controles em seu ponto ideal.

Do item 5., apenas confirmamos o item 3.

Do item 6., levantamos um novo problema : muitos fotógrafos não têm uma intenção de retoque/edição (no sentido de: um objetivo visual final), mas apenas puxam e empurram controles deslizantes na direção que parece deixar a imagem mais bonita, e acabam com um feliz acidente que seriam incapazes de reproduzir (ou descartam a imagem por serem incapazes de trabalhá-la). Nesse caso, não há métrica de sucesso para os controles porque não há diferença a computar entre intenção e resultado, já que a intenção é indefinida. É por isso que, ao trabalhar com feedback dos usuários, precisamos ser críticos e investigar quem está falando e de onde. Ou seja : nem todo feedback de usuário é um bom feedback de usuário (e anos de experiência não são prova de nada por si só).

E o item 7. é apenas uma retomada da seção anterior : ter que duplicar uma configuração costuma ser indicativo de má divisão de recursos, ou você precisa ter uma boa razão para fazê-lo.

Todos esses são, obviamente, os casos ideais para os quais tender. Na prática, você tem que avaliar diferentes candidatos e escolher o melhor, que raramente atenderá a todos os requisitos. Mas para avaliar candidatos concorrentes, você primeiro precisa de pontos de verificação e escalas objetivos. Esses são os pontos de verificação que se tornaram óbvios para mim ao longo dos anos.

As propriedades de bons fluxos de trabalho de edição

Lembro-me de intermináveis correntes de e-mail, 9 anos atrás na lista de discussão do Darktable (agora extinta), sobre a melhor forma de reorganizar a interface, nas quais me disseram : “não há fluxo de trabalho certo ou errado, apenas preferências pessoais”. O relativismo absoluto é sempre mais burro do que parece. Essa estupidez agora continua no discuss.pixls.us. São realmente as mesmas discussões, dizendo as mesmas coisas sobre os mesmos problemas, andando em círculos por mais de 9 anos, e ainda sem nenhuma solução tangível.

Primeiro há o caso óbvio em que você define uma máscara paramétrica em, digamos, o balanço de cor RGB, e a configura para mascarar valores RGB entre tanto e tanto + épsilon. Então, você está satisfeito com as cores, mas sua imagem parece um pouco escura, então você aumenta a exposição. Agora sua máscara paramétrica é inválida e você tem que refazê-la de novo, porque a exposição fica antes no pipeline do que o balanço de cor RGB, então você deslocou toda a sua faixa de valores de código RGB. Isto é edição circular, é a mais evitável perda de tempo, e se você quiser preveni-la, não há muita escolha : você tem que prestar atenção à ordem do seu pipeline. A edição circular é um fluxo de trabalho objetivamente ruim. Preciso justificar isso ?

Não para nas máscaras, porque muitos módulos de cor precisam normalizar o branco HDR para poder usar modelos de cor que só funcionam com a suposição de que branco = {1, 1, 1}. É por isso que coloco esses mais adiante no pipeline, depois dos ajustes globais de brilho e contraste.

E então, há o caso da edição em lote : você tem uma série de imagens para editar, quer que elas pareçam consistentes ao longo de toda a série, mas elas têm variações menores de iluminação, contraste e temperatura de cor. A única maneira de fazer isso funcionar é ter uma primeira etapa de normalização da imagem, para tratar as variações individuais das imagens e convertê-las para um estado constante. Uma vez feito isso, você pode aplicar em lote o mesmo estilo ou copiar e colar o histórico dos módulos posteriores por cima, porque essa próxima etapa receberá entradas “constantes” normalizadas e deveria, portanto, produzir saídas consistentes (se não constantes). Falhar em realizar essa primeira etapa de normalização tornará a próxima completamente não confiável e imprevisível, o que anulará o propósito da edição em lote. E mesmo com esse fluxo de trabalho aparentemente rígido, você ainda acabará tendo que fazer ajustes finos individuais se realmente quiser resultados consistentes. Isto não é minha opinião, é um simples fato : se você quer saídas consistentes para um conjunto de modificações de imagem com configurações rígidas, você precisa de entradas consistentes.

Mas há uma limitação a isso, porque ao trabalhar com sinal HDR, você precisa configurar seu mapeamento tonal HDR -> SDR cedo, para poder de fato ver o que está fazendo na sua imagem, sem clipping das realces. Então há uma primeira etapa de ter uma visão sobre seu conteúdo, e depois uma etapa de finalizar os limites da faixa dinâmica. O que significa que você deveria sempre configurar a exposição global primeiro, olhando para os meios-tons (e nada mais), e então configurar seu mapeador tonal de trabalho por ora. Portanto, aquela regra de tentar ancorar seu fluxo de trabalho 1:1 na ordem do pipeline (ela mesma ancorada nos requisitos de entrada dos módulos) tem algumas exceções e não pode ser aplicada sem discernimento.

O que significa que você deveria ter aprendido tudo isso. Bons fluxos de trabalho vêm de pessoas que pensaram sobre como se adaptar às ferramentas que estavam usando, olhando para elas tanto do ponto de vista prático quanto do teórico, e não dos felizardos que confundiram todos os hábitos que adquiriram ao longo dos anos com um fluxo de trabalho. De novo, há coisas acontecendo por baixo da superfície da interface, não estamos escrevendo cartas em um processador de texto. Por mais de 9 anos, venho gritando em círculos nos fóruns: É UM PIPELINE, NÃO UM CONJUNTO DESCONEXO DE CONTROLES DE IMAGEM ALEATÓRIOS. A ordem importa. Se há apenas uma coisa que você entende em toda essa lengalenga, deveria ser esta.

E acho que o Lightroom causou muito dano às expectativas e à compreensão dos usuários ao ocultar seu pipeline interno. Mas funciona para o Lightroom porque ele remove muitos graus de liberdade dos usuários. O Darktable reutilizou muita da semântica de UI do Lightroom enquanto propunha gradualmente mais liberdade e controle direto sobre os nós do pipeline (introduzindo, ao longo dos anos, o mascaramento por módulo, depois a multi-instanciação de módulos e a reordenação de instâncias relativas, depois máscaras raster reutilizáveis entre módulos não consecutivos, e finalmente a reordenação completa de módulos), o que confundiu tanto os veteranos quanto os recém-chegados.

A ideia de um pipeline não é sequer específica da fotografia digital. A pintura a óleo também tem um pipeline de certa forma, em que você começa preparando seu suporte, cobrindo-o com primer para torná-lo menos absorvente, depois coloca os contornos, depois prepara o fundo, depois aplica em camadas sua veladura  e finalmente coloca a camada de verniz. Ninguém em sã consciência começaria pelo verniz e terminaria pelo primer. A fotografia analógica obviamente tem um pipeline de banhos químicos, temporizadores e afins. E aplicativos de pintura como Photoshop, Gimp ou Krita têm um pipeline explícito, materializado por camadas que ocluem umas às outras, de baixo para cima, com camadas de efeito que nada mais são do que filtros de pixels paramétricos que produzem saídas dinâmicas.

Mas, de alguma forma, como o software de edição de fotos raw faz com que ela pareça desconectada das realidades materiais, parece aceitável, no digital, trabalhar sem estrutura nem método. O fluxo de trabalho de edição “não destrutivo” também pode ter sido interpretado liberalmente como YOLO  aqui, o que também não ajuda. Só porque você tem o Ctrl+Z não significa que de repente tudo seja indulgente.

Para resumir, bons fluxos de trabalho de edição são aqueles que lhe dão resultados previsíveis a cada etapa, evitando a edição circular. Eles precisam ser informados pela ordem do pipeline, mas não podem se ater a ela 1:1 o tempo todo, e você tem que usar seu julgamento para distinguir quando se ater ao pipeline e quando desviar. Isso deixa muito pouco espaço para preferências pessoais.

A ética do processamento digital de imagens

Nos tempos analógicos, os artistas trabalhavam com mídias físicas, e podiam realizar todo tipo de gambiarra e encontrar novas técnicas para alcançar resultados personalizados. Era acessível porque você podia tocar fisicamente o meio com o qual estava trabalhando. Os artistas eram livres.

A arte digital é inerentemente violenta, na medida em que retirou a liberdade dos artistas: agora eles não podem encontrar novas técnicas por conta própria, porque sua arte existe como pura informação em alguma memória de computador, então ficam limitados ao que os aplicativos propõem, e podem ou implorar aos editores/desenvolvedores de software que considerem suas necessidades, ou aprender a programar e programá-las eles mesmos (o que é uma taxa de entrada e tanto se você não tem formação técnica em ciências aplicadas ou ciência da computação). A perda de liberdade pode ser ocultada pelo fato de que qualquer coisa feita em software é reversível, então os fotógrafos não danificam permanentemente os negativos, por exemplo. Pior, o software pode torná-lo mais produtivo, então é um ganho líquido do ponto de vista de negócios. Mas isso não deveria ocultar o fato de que os artistas são colocados em uma posição de consumidor mais passiva do que antes, e dominados por aqueles que sabem como e querem programar para eles, que passam a decidir como eles farão arte de agora em diante.

“Violência”, “supressão da liberdade”, “dominação”… Você sabe para onde isso está indo: chama-se opressão. Uma opressão sexy que promete a você alcançar resultados profissionais em apenas alguns cliques sem ter que ir à escola de fotografia. Ou, no contexto do software livre, uma opressão que parece benevolente e inofensiva porque não há nada a pagar e há privacidade de dados embutida. Mas nada disso é incompatível com o fato de que nós, os desenvolvedores, controlamos o que você tem o direito de fazer nas/com as suas imagens, ou não, porque controlamos o código. Não porque fomos eleitos pelos usuários, não porque somos competentes para a tarefa em questão (a essa altura, já demonstrei muitas vezes aqui que a “equipe” do Darktable não passava de um bando de idiotas sem noção com tempo livre demais), apenas porque temos direitos de administrador em algum repositório do Github. Isso nos dá poder, e poder vem com responsabilização.

Isso vem me rondando a cabeça há vários anos, porque também se torna um dilema ético (além de todos os técnicos mencionados anteriormente) decidir quais recursos adicionar, ou remover, ou refatorar. Ao mesmo tempo, tentar agradar a todo mundo não é possível e acabaria sobrecarregando todos com muitas ferramentas de nicho que eles nunca usarão (de novo: esconder uma árvore na floresta). Além disso, é mais código para manter, então mais trabalho e um fardo para os mantenedores no futuro, com mais ameaças à estabilidade do software. Construir um canivete suíço que está constantemente semiquebrado não vai ajudar ninguém.

Mas permanece o fato de que remover controles em prol de simplificar a interface pode ser simplesmente remover liberdade, se não tivermos certeza de que funcionalidade semelhante continua a existir, de uma forma ou de outra, no software. A liberdade artística não é uma mercadoria, é um necessário sopro de ar fresco em sociedades que estão cada vez mais derivando para o (tecno-)fascismo, mais uma vez.

De novo, tudo isso tem que ser arbitrado caso a caso. Deixar os aplicativos de processamento de imagem irem em todas as direções ao mesmo tempo, tentando acomodar todas as necessidades em um único aplicativo, até as mais peculiares, vai construir ovelhas de cinco patas que são impraticáveis de usar para qualquer um. O que nos leva de volta à minha primeira seção: construir ferramentas genéricas, versáteis e livres de suposições que possam ser adaptadas a muitas necessidades diferentes de forma fatorada. Indústria vs. artesanato.

A produtividade é alcançada através da especialização (que, combinada com a padronização, desbloqueia a automação), a especialização é alcançada através da duplicação, a duplicação cria inchaço e desordem na interface, o inchaço e a desordem são os inimigos da UX e da criatividade. A conclusão de tudo isso é: vamos escolher o que vale a pena especializar e, assim, cercear a liberdade dos usuários. Portanto, a produtividade é o paradigma errado: sua conclusão natural é a opressão.

O oposto da produtividade é a robustez e a versatilidade. Pode ser mais lento (será mesmo ?), mas podemos lidar com uma variedade maior de casos com o mesmo número de ferramentas, sem remover arbitrariamente opções e, com isso, a liberdade do usuário. O conceito de robustez já foi desenvolvido no contexto da instabilidade social e climática por Olivier Hamant, em seu livro Antidote to the cult of performance. Robustness from nature (2024). Uma de suas principais conclusões é que o culto ao desempenho (ou à eficiência) só leva à competição, que promove a violência, e nos tempos instáveis que virão, precisamos de cooperação. Em uma sociedade que produz mais do que o suficiente para cobrir as necessidades de todos (mas distribui mal), o desempenho não nos rende nada exceto mais lucros (novamente, mal distribuídos). Mas o que ele certamente produz é esgotamento, tanto nas pessoas quanto nos ecossistemas.

No software, o esgotamento pode vir de várias coisas :

  1. tecnoestresse  ligado a aplicativos, ferramentas, padrões e paradigmas demais aos quais se adaptar,
  2. sobrecarga de informação , ligada a um excesso de widgets e ferramentas de interface para navegar,
  3. fadiga de mudança  ligada a atualizações frequentes demais que mudam os fluxos de trabalho.

Resumindo, buscar desempenho desemboca em uma série de desvantagens:

  1. de um ponto de vista técnico, significa ter que construir ferramentas mais especializadas que abarrotam a interface, o que produz sobrecarga de informação,
  2. de um ponto de vista de UX, manter a desordem e a sobrecarga razoáveis implica escolher arbitrariamente quais necessidades serão cobertas (provavelmente as da maioria) e quais serão ignoradas, o que é remover a liberdade artística de qualquer um que se desvie demais do mainstream : isso é inédito na história da arte, e nenhuma quantidade de liberdade de software torna isso menos violento,
  3. de um ponto de vista de marketing, apenas os profissionais precisam de produtividade, e, no momento, eles parecem preferir software comercial na grande maioria. Não há benefício para o código aberto em ir “conquistar novos mercados”, ele deveria antes se esforçar para cobrir os nichos deixados de lado. E, além disso, a fotografia profissional está morrendo lentamente desde os anos 1980, então não tenho certeza de que continuará sendo um mercado substancial por muito mais tempo.

Essa foi uma longa introdução, mas em um Mundo onde todo mundo acha que pode ser um designer, é necessário enunciar completamente a lista completa de requisitos de design antagônicos a fim de acalmar aqueles que pensam ser o próximo Leonardo Da Vinci, e lhes dar a noção de que a ideia simples que tiveram só parece brilhante porque eles não têm a nota de especificação completa. Já recebi muitos deles na minha caixa de entrada e nos meus rastreadores de issues.


Como isso é tratado no Ansel

Todas as capturas de tela foram feitas em um laptop de 15,6’’.

Apresentação dos módulos globais

Antes de tudo, vamos relembrar como a apresentação geral da sala escura foi refeita :

image
  • as abas dos módulos ganharam nomes explícitos em vez de ícones enigmáticos,
  • as abas são ordenadas (externamente) na ordem sugerida de fluxo de trabalho, da esquerda para a direita, então os usuários só precisam seguir a UI como um guia,
  • dentro das abas, os módulos são ordenados na ordem do pipeline (com uma lógica de camada “por cima”, de baixo para cima), que também é a ordem de fluxo de trabalho geralmente recomendada. A nova aba “básico” é uma exceção, tendo seções de módulos : dentro das seções, os módulos são ordenados na ordem do pipeline, mas as próprias seções são ordenadas na ordem do fluxo de trabalho (novamente, lógica de camada “por cima”, então de baixo para cima),
  • a aba “pipeline” ou o grafo nodal de ordem dos módulos desambiguam tudo e mostram uma visão direta dos nós do pipeline sem reordenação intermediária,
  • as abas de “favoritos” foram inteiramente removidas, pois só fingem resolver o inchaço adicionando mais dele.

Enquanto isso, as barras de ferramentas centrais foram inteiramente removidas, liberando o máximo de espaço para imagens em retrato, em telas 16:9 e 16:10 onde o espaço vertical é realmente mais precioso do que o horizontal. O uso de um menu global permitiu, mais uma vez, remover muitos botões de ícones estranhos das barras de ferramentas e substituí-los por itens de menu explícitos e textuais. Assim, no modo de tela cheia, você agora perde apenas a altura da barra de menu global :

image

As opções de mesclagem e mascaramento, sendo unificadas entre os módulos, foram movidas para a barra lateral esquerda. Isso libera muito espaço vertical para os módulos, reduzindo a necessidade de abas internas e evitando muitos cliques para lá e para cá. Note que as opções de mesclagem estão sendo reescritas no momento, depois que a API de máscaras foi inteiramente refatorada, simplificada e estendida, então esta é apenas uma visão temporária.

As visões do Ansel são bastante verbosas, então, para ajudar a distinguir entre texto constante (rótulos) e variáveis (valores), foi introduzida uma coloração de sintaxe :

  • os rótulos constantes são brancos,
  • os valores variáveis são laranja.

Calibração de cor

Na calibração de cor, as 3 abas R, G e B foram fundidas na mesma aba mixer, que agora cabe inteiramente na vertical. O mesmo vale para brilho, colorido e P&B, que agora estão fundidos em saídas.

A aba mixer agora tem 2 modos alternativos de interface gráfica, além do típico (agora apelidado de completo) ;

A visão de primárias foi levada ao Darktable upstream, exceto que fizeram dela um módulo independente, o que é estúpido : a matemática interna dos pixels é exatamente uma multiplicação de matriz 3×3, que é o que a calibração de cor também é, então não havia necessidade de um módulo adicional. Este é mais um problema resolvido na camada errada : precisava de uma camada de interface gráfica adicional em um módulo existente, e fizeram dela um módulo duplicado.

Em vez disso, o Ansel a implementa como uma camada de interface gráfica, ou seja, os parâmetros típicos do mixer de canais são convertidos de ida e volta para os parâmetros da visão de primárias, e a matemática dos pixels do módulo não mudou desde 2021. Para o bem de uma transformação totalmente invertível da matriz 3×3 para a visão de primárias, um parâmetro extra de ganho teve que ser adicionado para fechar matematicamente a transformação.

A visão simples é algo que eu tinha na gaveta havia vários anos : reexpressar os parâmetros pouco amigáveis do mixer em termos de rotação de matiz, esticamento do plano de croma (contraste de cor) e redimensionamento acromático. O esticamento U/V substitui o módulo legado do Darktable contraste de cor, que funciona no CIE Lab 1976, e empurrava/puxava as cromaticidades a e b. As visões simples vão além e permitem que você defina seu próprio espaço de cromaticidade uv usando a rotação dos eixos de croma (uv) : quando ajustada para 0°, u é um eixo verde-magenta e v é um eixo azul-amarelo (semelhante ao contraste de cor). Mas então, você pode girá-lo conforme precisar, por exemplo, em torno de -20°, o eixo v fica bastante próximo de um eixo de temperatura de cor, e o eixo u do eixo de matiz ortogonal. Vou deixá-lo com a documentação.

Esse modo é particularmente bem adequado para recuperar luzes de palco azuis avassaladoras, muito mais facilmente do que com a interface típica do mixer de canais :

After After
Before Before
Foto © Reinout Nonhebel, 2018
  1. ao comprimir o eixo V, comprimimos fortemente o gamut no eixo azul-amarelo, o que é muito mais suave sobre o resto do gamut do que usar uma compressão global de croma,
  2. ao comprimir o eixo U, também comprimimos o gamut no eixo magenta-verde, mas de forma muito mais suave,
  3. o matiz de acoplamento acromático é ajustado para azul profundo. Ao aumentar a quantidade de acoplamento, remapeamos uma porção de azul para o eixo acromático, ou seja, o dessaturamos e clareamos de uma só vez, o que ajuda muito a recuperá-lo dentro do gamut, ao mesmo tempo em que preserva a sensação geral de azul. Inversamente, a cor complementar é escurecida e ressaturada, mas como essa cor oponente é o amarelo, e comprimimos o eixo amarelo-azul através de V, acabamos aproximadamente no mesmo lugar.

Então essa reescrita de coordenadas simples dos parâmetros do mixer de canais gera 6 controles em vez de 9, e eles são muito mais significativos e fáceis de controlar. Este é um problema de UX que foi enfrentado puramente pelo lado matemático, porque isso nada mais é do que reexpressar uma matriz 3×3 em uma nova base ortogonal de autovetores, girada sobre o eixo RGB acromático, ou seja, começou puramente a partir de uma intuição de álgebra linear. Por causa das propriedades dessa nova base de autovetores (que são impostas por design), eu pude remover dimensões e transformar as restantes em controles mais significativos. É o que quero dizer quando repito que você não consegue resolver problemas de UX apenas olhando para a interface gráfica.

Tonalização dividida (split-toning) RGB

O módulo legado split-toning do Darktable funcionava no espaço HSL, que não suporta valores de código RGB maiores que 1 (portanto, nada de referente à cena). Além disso, misturar cores em HSL é esquisito e parece filtros de brinquedo quando você começa a aumentar os ajustes.

Ao mesmo tempo, o esquema atual de adaptação cromática no Ansel assume um único iluminante. No entanto, cenas reais sempre têm pelo menos dois iluminantes :

  1. a fonte de luz principal, que é o iluminante primário, e pesará principalmente sobre as realces e os meios-tons,
  2. superfícies coloridas que refletem a luz da fonte principal, tingindo-a, que atuam como iluminantes secundários, e pesarão principalmente das sombras até os meios-tons.

Até agora, para lidar com essa situação de iluminantes mistos, você precisava duplicar instâncias da calibração de cor e mascará-las para entrar/sair. Mas tentar recortar uma máscara binária (uma região atribuída a um iluminante, e o resto ao outro iluminante) é frágil porque não leva em conta a mistura de luz que acontece em torno dos meios-tons.

Então o novo módulo split-toning no Ansel propõe dois mixers de canais e duas correções de temperatura de cor, e duplica os novos modos de interface gráfica da calibração de cor. Ele permite que você defina o brilho de cada iluminante, associa uma matriz de cor a cada um, e calcula uma mistura de ambas as matrizes para aplicar a cada pixel dependendo de sua luminância.

After After
Before Before
© Luc Viatour, 2016

Nesse ponto, você pode pensar que estou obcecado com fotografia de shows, mas é só porque as luzes de palco são o cenário mais exigente e não perdoam nenhum erro no pipeline de cor. Esses têm sido problemas não resolvidos por décadas; sabe-se que luzes azuis se quebram em magenta, e elas são o benchmark de cor definitivo.

Aqui, ajustamos a temperatura das realces para tons de pele mais naturais, ao mesmo tempo em que preservamos o azul geral ao redor nas sombras. Em uma cena como essa, não há nenhum branco que você possa amostrar, então mirar em tons de pele naturais é o único guia. Depois, você faz o seu melhor para preservar o espírito da iluminação de palco (manter o azul azul), atentando aos limites do seu gamut RGB. Para mais detalhes, veja a documentação.

Primárias de cor

Como mencionei anteriormente, o módulo primárias do Darktable é uma mera duplicata do mixer de canais com uma interface diferente. Mas há casos em que manipular todo o espaço de cor através de suas primárias danifica demais a faixa de baixa saturação que estava perfeitamente válida. Então, havia necessidade de afetar as cores primárias e secundárias (nos vértices do cubo de gamut) de uma forma que excluísse o centro do gamut, mas ainda mesclando os efeitos suavemente entre ambas as regiões e preservando os gradientes da imagem.

Isso foi alcançado ao construir uma LUT RGB em um novo módulo : primárias de cor.

After After
Before Before
© Andrea (fonte )

Este exemplo foi concebido para tornar o vermelho e o laranja menos avassaladores, mas aprofundar dramaticamente os azuis, para demonstrar quão estável é a transformação de cor ao longo das bordas entre superfícies de cores diferentes.

Como, internamente, o módulo constrói dinamicamente uma LUT deslocando a cor de nós de controle, os usuários ganham a possibilidade de decidir a que distância dos vértices do cubo RGB os nós de controle ficam, através do controle deslizante de cobertura de gamut. Depois, 3 parâmetros de suavização permitem mesclar mais ou menos intensamente os deslocamentos de cor em RGB, e proteger mais ou menos as cores neutras do deslocamento. Por fim, o módulo tem um visualizador de LUT 3D:

image

O visualizador de LUT mostra os deslocamentos de cor por todo o cubo RGB, da origem ao destino. Ele pode ser girado em torno do eixo acromático (azimute), ou colocado em uma visão de plano de cromaticidade (inclinação do eixo = 90°). Pode ser ampliado, deslocado e girado em 3D a partir de eventos do mouse, e fatiado para obter uma melhor visão em uma certa profundidade. Por fim, a LUT 3D gerada pode ser exportada como um arquivo cLUT .cube para ser reutilizada em qualquer software que os suporte. Para mais detalhes, veja a documentação.

Equalizador de cor

A “equipe” do Darktable pegou meu segundo protótipo (que não funcionava)  do equalizador de cor, não entendeu por que não estava funcionando, adicionou etapas de pós-filtragem para esconder os problemas, e o lançou como se fosse trabalho próprio, sem sequer me creditar. Podem ficar com ele : é uma merda. E eu não assino meu nome em merda, de qualquer forma.

Veja, o problema daquele protótipo é que ele aplicava o deslocamento de saturação no espaço de cor dt UCS 22 HSB, que eu projetei em 2021 . Esse espaço de cor já é usado no color balance RGB para saturação, e visava encontrar a quantidade certa de escurecimento que deveria ser aplicada a uma cor ao aumentar sua “saturação” (na verdade, seu croma, em termos rigorosos de ciência das cores), de modo a evitar degradar em cores fluorescentes e neon não naturais, que são as armadilhas típicas ao adicionar muita “saturação”. Então, em vez do ajuste típico de croma que reduz o colorido a luminância ou luminosidade constante, essa fórmula de saturação também escurece. E embora isso funcione muito bem em manchas de cor lisas, o problema é que as imagens não são superfícies de cor lisas, mas têm gradientes.

Foi relatado a mim por volta de 2022 que a saturação dt UCS HSB do color balance RGB criava uma estranha franja acromática brilhante entre folhas de outono amarelas, brilhantes e saturadas, e o céu azul profundo por trás delas. O problema era que, na borda, a luz amarela das folhas e a luz azul do céu se misturavam em acromático (como deveriam, sendo cores complementares) devido a uma lente ligeiramente suave ou a névoa atmosférica. O algoritmo de saturação escurecia o amarelo e o azul de cada lado da franja acromática, mas não a própria franja, que agora se destacava mais brilhante. E não há correção para isso; não é um bug algorítmico: o problema é o modelo de cor, que leva em conta a percepção, mas não a mistura de luz. Então eu era mais um autor de mais um espaço de cor quebrado que levei meses para desenvolver e 20 horas de computação para ajustar numericamente os parâmetros do modelo.

Tentar implementar um equalizador de cor reutilizando aquele mesmo espaço de cor tornou esses problemas ainda piores, porque agora o efeito era conduzido em termos de matiz, o que significava problemas em duas dimensões em vez de uma. Para aliviar o problema, tentei suavizar as coisas usando filtros guiados RGB. Mas eu não conseguia bem encontrar a fórmula mágica para ter uma mesclagem adequada e robusta. Foi quando a equipe do Darktable decidiu catar a novidade brilhante da prateleira, e quando entendi que isso só poderia acontecer em RGB se fosse para mesclar adequadamente e preservar os gradientes.

After After
Before Before
© baongoc124 (fonte )

O equalizador de cor herda o mesmo cursor interativo do equalizador de tons, para edição direta na imagem amostrando o matiz do pixel sob o cursor, e rolar atualizará automaticamente o gráfico. Nós podem ser livremente adicionados em qualquer lugar, e a partir do cursor interativo, adicionar um nó no matiz atual é feito com o clique direito.

O equalizador de cor permite definir um deslocamento de cor em termos de matiz para sombras, meios-tons e realces. O conta-gotas de cor permite ver onde uma região se situa entre os controles tonais. Isso permite um controle muito refinado que, junto com a mesma suavização 3D das primárias de cor, fornece uma forma muito robusta de mesclar deslocamentos de cor. O ruído de croma que era o principal problema, ao definir deslocamentos de cor dramáticos, com o legado zonas de cor do Darktable (que funciona no CIE Lab 1976) ou com o protótipo anterior do equalizador de cor, não aparece mais.

Assim como nas primárias de cor, este módulo cria dinamicamente uma LUT RGB 3D que pode ser visualizada e salva em arquivos .cube da mesma forma. Para mais detalhes, veja a documentação.

Desenho

image

Preciso dizer mais ?

O Ansel agora implementa um módulo de desenho protótipo que permite que você desenhe imagens raster em um pipeline referente à cena a partir de pincéis de 32 bits que suportam cores HDR (>100%). Os pincéis suportam opacidade e fluxo (o mesmo que no Photoshop), respingos aleatórios, suavização de traçado, esmaecimento de bordas, e podem ser usados nos modos de pintura, apagamento, borrão e desfoque. O tamanho, a opacidade, o fluxo e a dureza do pincel podem ser mapeados para a pressão e a inclinação da caneta Wacom, ou para a aceleração genérica do cursor. Eles usam o alfa pré-multiplicado adequado e salvam camadas em arquivos sidecar TIFF de ponto flutuante de 16 bits que podem ser editados na maioria dos principais aplicativos de desenho.

Várias camadas podem ser usadas instanciando múltiplas instâncias do módulo desenho e compostas na imagem usando as opções genéricas de mesclagem e mascaramento do Ansel. Também pode ser usado para compor qualquer tipo de camada arbitrária vinda de qualquer software, desde que seja salva em ponto flutuante de 16 bits como uma camada no arquivo sidecar TIFF do Ansel. A imagem de fundo (antes do módulo) pode ser exportada como uma camada de fundo se você precisar de uma imagem de referência para desenhar em outro software e importar o resultado de volta.

Isso foi possibilitado pela nova arquitetura de pipeline que habilitou um modo em tempo real. É certo que ainda não é tão rápido quanto o Photoshop porque, a cada atualização de traçado de pincel, há outros módulos rodando depois do desenho no pipeline.

Essa é a liberdade definitiva de conseguir tudo o que botões e controles deslizantes nunca lhe darão, seja para clarear e escurecer (dodge and burn), consertar partes danificadas (realces recortadas, áreas faltantes) ou simplesmente misturar fotografia e pintura. Para mais detalhes, veja a documentação.

Granulação fotográfica

O módulo legado grain do Darktable era realmente insatisfatório, pois permitia apenas granulação de luminância e era aplicado no canal de luminosidade do espaço de cor CIE Lab 1976. Os resultados eram estranhos, sem se assemelhar de forma alguma ao haleto de prata. Finalmente implementei a síntese estocástica de granulação  que desenvolvi em 2023 em um novo módulo: granulação fotográfica. Ela divide o campo de luz em cristais virtuais de haleto de prata e simula sensores de grão empilhados em camadas. Funciona tanto para granulação P&B quanto colorida, embora eu tenha tido que tomar certa distância do meu artigo inicial para lidar com a cor.

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

Filmic

Durante vários anos, as pessoas têm me dito que os estúpidos módulos sigmoid e o mais recente AgX do Darktable lhes davam um pouco mais de controle. E nenhuma delas foi capaz de me dizer exatamente controle sobre o quê. Então levei muito tempo para descobrir.

Sigmoid e AgX não são revoluções, são outros filmics :

  1. você converte as cores usando um moldador logarítmico ou de potência,
  2. você joga alguma curva em forma de S por cima,
  3. depois você faz o seu melhor para desfazer a bagunça que a curva de tons fez com o croma ao longo do processo,
  4. e finalmente você desfaz o moldador.

Sigmoid e AgX poderiam ter sido modos alternativos dentro do filmic : todos eles passam pelas mesmas etapas com prioridades e estratégias ligeiramente diferentes. Fazer isso teria fornecido um único módulo para compressão de faixa dinâmica, com diferentes modos dependendo de quanto controle refinado os usuários quisessem. Em vez disso, duplicaram a funcionalidade e adicionaram inchaço na interface gráfica, então os usuários agora têm que escolher entre base curve (que já era uma variante duplicada e especializada da própria tone curve), filmic, sigmoid e AgX para realizar a mesma tarefa, enquanto nenhum deles de fato declara a funcionalidade que fornece.

A única coisa que o filmic faz melhor é lidar explicitamente com os limites da faixa dinâmica, o que permite usá-lo para compensação de ponto preto ao imprimir. Os outros dois os tratam como um subproduto do ajuste de contraste. Como os desenvolvedores dos outros dois não se importam com impressões, você pode apostar que isso alivia algumas restrições no design, e remove alguns controles deslizantes na interface gráfica. A única coisa que os outros dois fazem melhor é fornecer controles manuais de cor para desfazer a bagunça de problemas de saturação e deslocamento de matiz através do mapeamento de tons, mas eu realmente não acho que esse nível de granularidade de cor pertença a um recurso de mapeamento de tons : é um fluxo de trabalho e uma divisão de recursos completamente falhos.

De qualquer forma, finalmente descobri que o controle mais fino de contraste vinha do fato de o sigmoid fornecer diretamente controles de nós de e ombro, enquanto o filmic usa uma latitude e um deslocamento globais que são incômodos de usar, já que vinculam ambos. Isso foi originalmente projetado para mapeá-lo às fichas técnicas de filmes reais, porque a latitude é uma coisa real de filme, a fim de talvez emular filmes reais um dia. Esse dia nunca chegou.

Então resolvi o problema na camada de interface gráfica adicionando uma conversão entre latitude/deslocamento e ajustes de realces/sombras, e agora o filmic RGB permite que você manipule diretamente a posição dos nós de pé/ombro :

image

Nenhuma matemática de pixel foi alterada no processo, os parâmetros do módulo ainda são os mesmos de antes, nenhum novo módulo foi criado, é apenas uma etapa intermediária de conversão na interface gráfica.

Conclusão

Todos os novos módulos suportam descarregamento na GPU através do OpenCL. Foram projetados para robustez, e acho que essa meta foi alcançada. Eles substituíram módulos anteriores piores, que funcionavam no CIE Lab 1976, e que mostraram seus limites e falhas por muito tempo. Você agora roda um pipeline RGB completo no Ansel. Os módulos legados ainda estão no programa e continuarão rodando para edições antigas. Além disso, os controles deslizantes coloridos e os gráficos de matiz são gerenciados por cor usando o perfil de cor da tela.

Os módulos que introduzi recentemente não são brinquedos novos e brilhantes para nos empolgarmos. São a conclusão de anos pensando em uma divisão de recursos consistente e coerente que ajuda o fluxo de trabalho referente à cena. Esse fluxo de trabalho referente à cena é mais complexo do que o anterior referente à tela, mesmo que só seja porque precisamos normalizar o “branco” antes de entrar em qualquer LUT ou espaço de cor perceptual, mas é a única forma de lidar com imagens HDR, mesclagem alfa adequada para máscaras, e filtros de pixel fisicamente precisos que simulam a mistura de luz. Filtros fisicamente precisos são robustos e produzem resultados orgânicos, mesmo empurrados a ajustes dramáticos. Mas costumam ser menos acessíveis para iniciantes e perturbadores para retocadores experientes acostumados ao Lightroom e afins.

Este será meu último post neste site porque me aposento do desenvolvimento. Custou-me caro demais : estresse demais, burn-outs demais, anos demais gastos consertando a merda dos outros e sofrendo com suas más decisões. Estou cansado além do que você pode imaginar. Eu odeio programar e odeio programadores. Conheço muito poucos deles que programam para construir coisas ou resolver problemas, a maioria apenas gosta demais de passar bons momentos com um computador, e se transformam em bombeiros piromaníacos em quem você não pode confiar para projetar coisas. Eu odeio tecnologia e a chamada “inovação”: tudo isso é apenas um golpe capitalista projetado para o crescimento infinito em um mundo onde os recursos são limitados, e fingimos resolver problemas criados pela tecnologia com ainda mais tecnologia. Isso é insano. O mundo do código aberto herda a mesma mentalidade, incluindo o tecnossolucionismo , porque é esse o tipo de podridão cerebral que 350 anos de capitalismo produzem, mesmo que o FLOSS não tenha os lucros para justificá-lo. Está cheio de mentiras e cheio de merda, porque libre significa liberdade apenas para engenheiros, e os usuários que se danem. O problema é que eu costumava acreditar nessas mentiras, nesses valores : eles eram (e ainda são) os meus. Mas perceber que são apenas palavras vazias repetidas em “comunidades” tóxicas de homens brancos de meia-idade com B.Eng, M.Sc e Ph.D foi um despertar brutal. O que de fato fazemos para empoderar os usuários que de fato precisam disso ? Em que ponto exigir casualmente o uso da CLI empodera alguém que não sabe ler código ? Estamos apenas contribuindo para aprofundar a divisão entre as elites alfabetizadas em computação e os camponeses. Lembre-se, estamos fazendo software de fotografia aqui, não uma biblioteca de backend, não uma infraestrutura de servidor, mas um aplicativo de desktop para o usuário final.

Esvaziei meu cérebro aqui, para registrar tudo o que aprendi sobre design de processamento de imagens, como fiz, e por quê. É importante entender que os usuários, e a maioria dos desenvolvedores, sabem apenas como um aplicativo se comporta em suas próprias imagens. Durante 8 anos, recebi muitas imagens patológicas que as pessoas me enviaram, exibindo falhas e limitações das ferramentas. Tenho cerca de 45 GB dessas imagens no meu disco rígido, agora mesmo. Isso dá uma perspectiva completamente diferente sobre os problemas reais do que aquela que todos os campistas felizes possam ter : eu sou o cara que sabe o que quebra e quando. Eu sou o cara que os problemas encontram. Eu sou a Cassandra  do projeto. E é irritante ter que justificar o tempo todo, a pessoas que não veem os problemas, por que aquela coisa que poderia ser muito mais simples não pode ser muito mais simples porque há casos patológicos em que precisamos nos adaptar à variabilidade da entrada. Para se adaptar à variabilidade da entrada, você precisa de parâmetros do usuário em vez de constantes fixas no código. Daí o inchaço da interface gráfica. O tipo de inchaço de interface gráfica que você não pode evitar sem prejudicar a usabilidade.

Você não pode avaliar a qualidade de um design se não conhece seus requisitos. “Eu curto” ou “eu não curto” é irrelevante. Ninguém gosta de usar cinto de segurança, ainda assim é um bom design se você considerar quantas vidas ele salvou. Qualquer crítica real só pode ser sobre como a solução proposta atingiu a meta, o que só pode acontecer se você conhece a meta. No processamento de imagens, a natureza mista dos requisitos torna difícil evitar mergulhar na matemática e em seus hieróglifos em algum momento, que é onde você perde as pessoas. Mas isso ainda não as impede de dar sua opinião inútil, começando por “eu não sou programador”/“eu não sou matemático”/“eu não sou cientista de cores”… “MAS”… [entra algum ruído cerebral aleatório]. Fazer código aberto, onde tudo é público, permite esse tipo de ruído por toda parte : é realmente cansativo, e há muitas vezes em que eu gostaria que o código-fonte fosse fechado, só para poder trabalhar em paz. A maioria desses caras tem boas intenções e apenas quer fazer parte de algo, mas contribuir para a sobrecarga de informação não ajuda e apenas contribui para criar fadiga. A comunicação é onde todo trabalho em equipe perde produtividade

Design não se trata de ouvir o que as pessoas gostam. Se 65% do seu painel de teste gosta de texto escrito em vermelho, e 72% gosta de texto escrito sobre fundo vermelho, você escreve texto vermelho sobre fundo vermelho ? Isso não faz sentido. Não estamos fazendo política e tentando agradar eleitores durante uma campanha, estamos buscando soluções de longo prazo/à prova de futuro para problemas. Design se trata de ouvir o que as pessoas precisam, o que elas raramente conseguem expressar claramente, e encontrar formas de fatorar essas necessidades. Então as únicas estatísticas que vale a pena computar são sobre os casos de uso : como o software é usado, quais são os pontos de dor mais comuns, e qual é sua causa raiz. Depois conserte a causa raiz, que pode estar bem longe da manifestação real do problema. Isso também é uma habilidade real e preciosa : seguir o fio do problema, através de pistas e sinais, para descobrir a verdadeira origem, e não apenas remendar o problema final ou contorná-lo. “Ouvir os usuários” não significa ouvir cada indivíduo e dar-lhe o que ele individualmente quer : não estamos fornecendo terapia. Significa ouvir toda a base de usuários, e identificar as necessidades e pontos de dor comumente compartilhados de modo a conceber uma solução fatorada que cobrirá o máximo de necessidades com a menor quantidade de tecnologia. Isso não implica descartar qualquer pessoa que se desvie da média por mais de um desvio padrão, mas essas pessoas podem ter que recorrer a métodos que não são feitos sob medida e otimizados para suas necessidades.

O design não existe em uma ilha : há outros aplicativos de edição de imagem por aí. É novamente difícil avaliar quando seu design deve copiar os outros porque os usuários estarão acostumados à semântica de interface deles, e quando você deve se afastar porque o problema que está tentando resolver é diferente demais do que a concorrência faz, ou seu usuário típico é diferente demais. O código aberto está constantemente dividido entre a tentação de copiar 1:1 os líderes comerciais que tanto odeiam (mas a que silenciosamente aspiram ser), e o desejo de ser mais esperto que todo mundo enquanto reinventa a roda (frequentemente de uma forma pior). Em tudo isso, sua Estrela Polar é se perguntar, a cada hora de cada dia : qual é o problema que estamos tentando resolver, e quem são as pessoas que o enfrentam ? É assim que você pode adaptar as coisas ao seu público, em vez de cair em cultos à carga  e adotar soluções porque elas foram bem-sucedidas em um contexto que você não entende realmente e que não é necessariamente o seu.

Minha principal lição de todos esses anos é que aplicar transformações de cor a pixels em qualquer outro espaço que não o RGB está fadado ao fracasso, como mostra o exemplo do colorbalance RGB : embora possa soar como uma ótima ideia descorrelacionar o trabalho de “cor” (no sentido de matiz/croma) do trabalho tonal, isso nunca será mais do que uma questão de escolher sua dor. Aumentar o croma a luminosidade constante degrada as cores em fluorescente, aumentar a saturação a brilho constante (portanto escurecendo tudo) não respeita a teoria da mistura de luz, e ambos produzem ruído de croma devido à natureza instável dos ângulos de matiz. Mas então o RGB não é perceptualmente uniforme, e a faixa esverdeada de qualquer escala de matiz HSL/HSV ocupa cerca de 30 % do espaço, enquanto o verde é apenas 1/6 do anel de matiz perceptual. A única solução é lidar com a interface gráfica em modelos de cor perceptuais, e converter, de uma forma ou de outra, para RGB antes de aplicar aos pixels. O que requer ginástica de abstração adicional para os desenvolvedores. E isso claramente não é o forte deles, já que o nível de matemática é bastante baixo.

Eu já tenho um sucessor, mas o futuro do Ansel terá que ser uma cooperativa onde os usuários garantam aos desenvolvedores condições justas de trabalho, e os desenvolvedores garantam aos usuários que suas necessidades serão atendidas, reciprocando responsabilidades mútuas. Não podemos continuar assim, não é saudável. E, por “assim”, quero dizer, de um lado, o “desenvolvedor hobbista” com zero prestação de contas, e, do outro, o dev solitário em burn-out vivendo abaixo da linha da pobreza para meio que fazer as coisas acontecerem. Esse paradigma entregou tudo o que podia, não pode ser ajustado. As mesmas causas só levarão às consequências que já conhecemos : código aberto é uma droga. Se você quer mais, esse paradigma terá que mudar. O código aberto, de um lado, é uma ditadura dos desenvolvedores (aqueles que sabem e podem) sobre os usuários (aqueles que precisam), mas, do outro lado, é a exploração daqueles que trabalham por aqueles que tomam. Isso só alimenta ressentimento mútuo, desprezo velado e paternalismo. Todo mundo perde.

A alternativa é a atual enshitification das plataformas corporativas e o tecnofascismo que ela está atualmente habilitando. Você foi avisado.


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  ↩︎