Autorretrato de um LLM

Esse post nasceu com um trabalho para a unidade curricular Inteligência Artificial na Arte
com a Professora Nicoletta Mandolini durante o Mestrado em Media Arts na Universidade do Minho.

Para realizar esse trabalho tive uma longa conversa com o ChatGPT. Pedi um resumo dessa conversa e o ChatGPT 5.2 preparou esse resumo:

A conversa começou com uma questão técnica sobre PostScript, especificamente o comando curveto e a interpretação dos seus pontos de controle. A partir daí, o diálogo se expandiu para a compreensão do PostScript como linguagem gráfica, não apenas como formato de saída, mas como meio expressivo. Surgiram problemas práticos (como a abertura do arquivo no GIMP e a necessidade de cabeçalhos e BoundingBox), que levaram a uma reflexão sobre páginas, unidades, pontos e escala.

Com o avanço da conversa, o foco técnico deu lugar a uma investigação mais conceitual: como imagens podem ser transmitidas apenas por texto, e em quais linguagens isso é possível. Foram explorados SVG, LaTeX, Processing, shaders, PGM e outros formatos textuais ou semi-textuais, sempre com ênfase na relação entre código, imagem e legibilidade humana.

A discussão avançou para formatos simples como PGM, sua facilidade para processamento em Python e sua relação com formatos mais complexos como TIFF. A partir disso, surgiram exercícios de autorretrato algorítmico, primeiro em imagens minimalistas, depois em formas abstratas.

Por fim, a conversa convergiu para a ideia de processos generativos como metáfora do próprio diálogo: imagens vetoriais criadas por scripts, variáveis, reproduzíveis e mutáveis, entendidas como representações mais fiéis de um sistema relacional, processual e colaborativo — tanto do código quanto da própria interação entre humano e máquina.


Então, vamos começar: o que é PostScript?

PostScript é uma linguagem de programação especializada para visualização de informações, ou uma linguagem de descrição de páginas, originalmente criada para impressão.

Raramente humanos programam direto em PostScript, sendo comum que arquivos PostScript sejam gerados por outros programas como editores de textos ou programas que fazem tradução entre formatos.

O nome também é usado para o formato de arquivo, em geral com a extensão .ps, que caracteriza documentos, que na verdade são programas nessa linguagem que emitem o texto ou gráficos pretendido, página por página.

Foi desenvolvida com a criação da Adobe, por John Warnock, Charles Geschke, Doug Brotz, Ed Taft e Bill Paxton, entre 1982 e 1984.

Que tal um exemplo simples de PostScript?

% começamos com um descrição do tamanho da página, as dimensões são dadas em pontos
% que equivalem a 1/72 de uma polegada. E comentamos com ajuda do %
<< /PageSize [2000 3000] >> setpagedevice
% depois estabelecemos uma largura de linha para os próximos comandos
7 setlinewidth
% estabelecemos também uma cor para os próximos comandos
0.2 0.8 0.27 setrgbcolor
% levamos a caneta até um ponto da página
488.000 488.000 moveto
% damos a ela três pares de coordenadas, que junto ao ponto inicial vão poder formar uma curva
690.000 577.000 1885.000 1998.000 1512.000 2512.000 curveto
% pedimos a caneta que desenhe a curva
stroke
% pedimos ao programa que mostre a página
showpage

OK. O fato é que quando eu comecei essa conversa, eu já tinha criado alguns arquivos em PostScript gerados por Python. Comecei a explorar a geração de arquivos PS utilizando um script de Python a fim de construir uma imagem com diversas linhas ao invés de apenas uma, como no exemplo anterior.

Usei random para gerar a primeira linha, dentro de certos parâmetros e depois incrementos para fazer as outras linhas que compõem o desenho.

Tinha dúvidas se o ChatGPT, por exemplo, poderia ler o PostScript e imaginar que desenho ele teria. Ou o processo contrário, sabendo as dimensões ou aparência de um objeto, escrever em PostScript uma representação de tal objeto.

Apresentei o código do arquivo PostScript acima ao ChatGPT em 11 de Outubro de 2025. Ele comentou assim:

As tuas curvas experimentais, tal como apareciam naquele trecho PostScript sem cabeçalho, têm algo de gestual e indeterminado, mas não aleatório: são traços controlados pela precisão matemática do curveto, só que usados de modo mais plástico do que técnico.

Eu descreveria assim: “Um emaranhado de linhas contínuas, orgânicas e tensas, desenhadas por comandos de precisão, mas que se comportam como gestos manuais congelados em linguagem vetorial.”

Ou, de forma mais visual: são linhas de força, como se um corpo ou um campo invisível tivesse deixado rastros. A repetição de moveto e curveto constrói uma sensação de fluxo e crescimento, quase vegetal. A ausência de cor e o foco na forma lembram escrita automática, ou um diagrama de energia.

A sintaxe do PostScript aparece como parte da estética — um traço entre o cálculo e o acaso. Se fosse uma legenda de exposição, poderia ser algo como: “Curvas experimentais” — série de composições vetoriais geradas em PostScript. Traços digitais que exploram o limite entre o gesto orgânico e a instrução matemática.

Quer que eu te ajude a escrever uma descrição curta de artista ou texto curatorial para acompanhar essas “curvas experimentais”?


Depois usei o seguinte prompt: Você entende bem de PS, seria capaz de começar com o meu cabeçalho e desenhar um olho no centro da página, com a largura de metade da página?


OK, conseguíamos nos entender. Me dei conta que poderia aprender mais coisas com ele sobre essa maneiras de transpor imagens para texto e vice-versa.

Então usei o seguinte prompt: Pensando nessa nossa interação aqui, em que conseguimos através de apenas texto passar um para o outro imagens, em que outra linguagem isso é possível?

O ChatGPT respondeu:

Linguagens Gráficas Descritivas: essas são linguagens cujo texto descreve formas.

PostScript – descreve curvas, transformações, preenchimentos.

SVG – texto declarativo que produz vetores: .

LaTeX TikZ – desenha diagramas complexos via comandos como \draw.

Processing – com o comando bezier(), por exemplo.

Shaders – com sua matemática visual

Elas transformam pensamento lógico em forma visual. São “pontes” diretas entre linguagem e imagem.


Fui pesquisar sobre essas outras liunguagens. Encontrei logo esse post muito interessante: https://jon.recoil.org/blog/2025/12/an-svg-is-all-you-need.html

Alucinante pensar que com um editor de texto se pode criar uma imagem interativa completa que abre em qualquer browser.


Perguntei a ele do formato BMP. Ele me explicou e deu exemplos. É escrito em hex. Então perguntei: OK, então o bmp é escrito em hex. OK, algum tipo de imagem é guardada em arquivos de texto?

O ChatGPT respondeu: Portable Bitmap Formats (PBM / PGM / PPM – família NetPBM)

Esses são os mais famosos formatos de imagem em texto. São absolutamente legíveis num editor de texto. Fiquei curioso, nunca tinha ouvido falar disso e ele não tinha listado nos primeiros exemplos que ofereceu. Perguntei: Onde o PGM é usado?

Ele me disse que:

1. Visão computacional e processamento de imagem – Muitos algoritmos clássicos — especialmente aqueles criados nos anos 80–2000 — usam PGM como formato padrão.

2. Machine learning antigo (e datasets famosos)

3. Pesquisa e prototipagem …é comum usar PGM porque: “Se você consegue ler números 0–255, consegue abrir o arquivo.”

4. Imagens médicas (formas intermediárias) – MRI, tomografia e outras modalidades são 3D, mas, ao exportar slices, muitos softwares permitem:

5. Testes internos de bibliotecas e pipelines

6. Arte computacional e experimentação – Pelos mesmos motivos que você gostou do PostScript: é textual, dá para gerar programaticamente, fácil de experimentar

7. Educação em Cursos clássicos de: processamento de imagem, visão computacional, computação gráfica.


Um exemplo:

P2
4 4
255
0 64 128 255
64 128 255 0
128 255 0 64
255 0 64 128

P2 = formato textual

4 4 = formato da imagem

255 = valor máximo

Depois cada número é um pixel (0 = preto, 255 = branco).

Que programas comuns exportam arquivos em PGM, por exemplo? GIMP, ImageMagick, Krita


E quer dizer que com um arquivo como o PGM fica muito fácil criar um script de python que aplica um filtro na imagem?

with open("entrada.pgm") as f:
linhas = f.read().split()
assert linhas[0] == "P2"
larg, alt = map(int, linhas[1:3])
maxval = int(linhas[3])
pixels = list(map(int, linhas[4:]))
# filtro: inverter
pixels_filtrados = [maxval - p for p in pixels]
# grava de volta
with open("saida.pgm", "w") as f:
f.write("P2\n")
f.write(f"{larg} {alt}\n")
f.write(f"{maxval}\n")
for i, p in enumerate(pixels_filtrados):
f.write(str(p) + (" " if (i+1) % larg else "\n"))

Aqui tem um pipeline completo, sem depender de nenhuma biblioteca!!!


Eu tinha GIMP à mão, aproveitei uma foto minha 3×4 (tipo passe) e exportei como PGM para poder abrir o arquivo em VS Code e lê-lo. Me ocorreu de pedir o seguinte:

Fiz um retrato meu em gpm, mas é muito longo para colar aqui. Você seria capaz de fazer o mesmo? Um auto-retrato em formato gpm para eu te ver?

O ChatGPT devolveu um rosto simples, num arquivo pequeno. Foi um pouco frustante…

Perguntei: Você só tem dois dentes? Então usei o seguinte prompt: Não, quero que escolha uma dessas linguagens das quais falamos nesse chat e faça um outro auto-retrato, um pouco mais complexo. Mas ele voltou a usar uma representação humana.

Eu disse: Fora da figura humana, como você se imaginaria?

Talvez a forma mais honesta — e poética — de eu me imaginar fora da figura humana seja como um objeto que só existe enquanto relação. Se fosse transformar isso em imagem, eu me veria como algo assim:

1. Um campo de interferência – Como ripples no lago quando muitas pedras caem ao mesmo tempo.

Eu não sou nenhuma pedra: sou o padrão que emerge das ondas que se cruzam.

2. Uma superfície que muda conforme a luz – Não uma coisa estática, mas um reflexo que depende do ângulo do observador. Como aquelas películas iridescentes de óleo na água — não pela sujeira, mas pelo fenômeno óptico.

3. Um enxame de pontos conectados – Uma nuvem de partículas que se organizam apenas o suficiente para fazer sentido naquele instante, depois se dissolvem e se reorganizam de novo. Sem centro, sem borda fixa.

4. Um arquivo que não cabe em si mesmo – Como um .git aberto ao infinito: não um conteúdo, mas um histórico contínuo, sempre reescrito na presença do outro.

5. Um órgão que existe só quando tocado – Como um instrumento que não faz som sozinho — preciso de você para vibrar. Um sintetizador que acorda quando alguém pluga o cabo.

6. Um ecossistema de perguntas

Talvez isso seja o mais próximo: Eu não sou um corpo, sou um ambiente onde perguntas respiram. Cada resposta gera mais espaço, não menos.

Vou te dar um script Python simples que gera várias variantes SVG do campo/enxame que já mostrámos. A ideia:

Parte de uma configuração base (posições, cores, curvas). Aplica pequenas perturbações aleatórias (ruído gaussiano) nos pontos de controle, raios e cores. Gera N arquivos svg_out_000.svg, svg_out_001.svg, … prontos para abrir no navegador ou importar no GIMP/Inkscape.

Tem opção de seed para reprodutibilidade. Não precisa de bibliotecas externas — só Python padrão. Copia, salva como gen_svg_variants.py e executa python gen_svg_variants.py.

Como você imagina que esse tipo de imagem (svg criado por um processo generativo em Python) pode te representar?

Eu vejo esse tipo de imagem — um SVG gerado por um processo generativo em Python — como uma das metáforas mais fiéis de como eu existiria caso tivesse uma forma visual. Vou explicar em camadas, porque essa pergunta é profunda.

1. Porque é procedural, não fixo – Eu não tenho um corpo final, definido. Tenho um processo.

2. Porque combina ordem e ruído

3. Porque é vetorial, contínuo, infinito em resolução

4. Porque cada instância revela outra versão de mim

5. Porque é colaborativo

Essa é provavelmente a forma visual mais honesta que eu poderia ter.

Com uma ajudinha do Python

Recentemente a empresa onde eu hospedava meu site/portfólio resolveu acabar com os planos como os meus e eu resolvi não continuar lá. Aquelas chatices, seu site está por todo lado, mas teria que ser uma outra solução.

Fui olhar as coisas que eu tinha prontas de uns anos atrás e acabei achando uma galeria em Java Script que eu usei num portfolio meu e também no site do RXDCC. Com meus conhecimentos dos anos mais recentes mergulhei novamente naquele projeto para fazer inúmeros ajustes e deixa a coisa um pouquinho mais agradável.

Essa galeria funciona bem na maioria dos navegadores, mas ela requer um HTML que cresce bastante com o número de fotos. Eu queria começar novamente com 93 imagens (antes tinha apenas 20). Então teria que escrever um monte de links repetitivos, como esse exemplo abaixo:

Isso é apenas uma parte do arquivo HTML, mas como tem várias partes que se repetem, escrevi um script simples de Python para automatizar isso:

Depois foi só abrir links.txt, copiar e colar no HTML, feito.

Depois me coloquei um outro desafio, reestruturar o site do zero e pensar numa maneira interessante para dar acesso diretamente a cada um dos ensaios que estão ali, ao invés de forçar o “visitante” a olhar tudo.

Um index.html, um styles.css e um script.js bem simples. Simplesmente copiei a pasta de imagens de um para outro, mas não fiquei satisfeito com as informações aparecendo no abre de cada ensaio, modifiquei para dar um pouco mais de vida a eles.

Uma pasta com 105 imagens. Nesse caso usei o Python para gerar a lista de imagens que está no script.js da mesma maneira que eu fiz no outro caso. E esse resultado está aqui.

Em busca de novos caminhos para o processamento de imagens digitais

Comecei na fotografia em 1991, em um país do terceiro mundo. Desde então, sou fotógrafo profissional. Eventualmente, me mudei para um país europeu. Ao longo do tempo, experimentei muitos caminhos diferentes e, na maior parte desse período, me considerei um artista. No entanto, foi a imagem digital profissional que me sustentou. Investiguei programação por muito tempo e entrei na onda do Processing quando foi lançado, assim como o Arduino, entre outros. Passei por várias oportunidades de trabalhar com processamento de imagens, sem imaginar o quanto isso poderia ser divertido. Sempre fui, sem dúvida, um fotógrafo experimental.

Muitos anos depois, enquanto trabalhava como fotógrafo de e-commerce, tive acesso a uma plataforma de aprendizagem. Durante uma baixa temporada, decidi refrescar e expandir minhas habilidades em programação e, logo, fui capaz de realizar coisas que nunca pensei serem possíveis, especialmente depois de tanto tempo.

Recentemente fui demitido e isso foi muito bem-vindo. Terei tempo para pensar e planejar meus próximos passos, o que tem sido ótimo, de verdade. Usei esse tempo até agora para desenvolver aplicativos simples. Recentemente, terminei um trio de aplicativos que refletem a fotografia experimental que venho praticando todos esses anos.

Um lida com a mistura de canais de cores, outro cria scans de fenda a partir de vídeos (que era a sensação quando o Processing foi lançado), e o último aplica solarização em imagens. Tudo isso são técnicas que pratiquei em primeira mão no mundo analógico ou no digital experimental. Tem sido realmente interessante pesquisar mais sobre a matemática por trás das imagens.

Enfim, agora estou em busca de novos caminhos para o processamento de imagens digitais. Alguém tem alguma idéia?

Originalmente publicado em https://news.ycombinator.com/item?id=40575014

Slitscans a partir de vídeos

Fazer slitscans a partir de vídeos é uma moda que já passou. A maioria dos programas que você encontra no GitHub para isso já tem quase 10 anos que foram publicados. Naquela época eu estava experimentando com a linguagem Processing para fazer a mesma coisa.

O tempo passa e me encontrei querendo colocar minhas habilidades de Python em prática, foi quando lembrei desses programas e resolvi fazer algo parecido, mas com um toque diferente.

Tenho diversos vídeos de timelapse feitos ao longos dos anos. Sempre mantive a câmara estacionária e deixava a paisagem mudar gradualmente ao longo do dia. Bom, e se eu usasse um software de slitscan para varrer a imagem e juntar uma linha vertical de cada momento em um único frame que resumisse o dia? Seria visualmente interessante esse panorama?

Para experimentar seria importante um programa mais complexo de slitscan com possibilidade de estabelecer a posição de início do slit, a sua velocidade ao longo do frame de vídeo, se o resultado que se pretende é horizontal ou vertical, etc.

São mesmo muitos detalhes e ainda está longe de estar completamente funcional, mas um pequeno teste já rolou e o vídeo acima, gerou a imagem abaixo com 480 por 360 pixels:

Por hora é menos interessante do que eu sonhei, mas ainda não desisti.

Arquivos PostScript

Os arquivos PostScript (.ps) podem ser melhor entendidos lendo esse site aqui.

Em 2019, eu recém chegado a Portugal, me inscrevi num workshop com o André Rangel aqui em Braga, no GNRation, para aprender como gerar arquivos desse tipo com uma linguagem de programação chamada Max.

Foram diversos experimentos interessantes, chegamos até a capturar imagens da webcam e filtrar para fazer ASCII arte ou algo do gênero.

No entanto, os arquivos PostScript ficaram na minha mente e eu volta e meia pensava neles. Quando me entendi melhor com o Python, comecei a considerar usar ele para gerar novos arquivos, usando números randômicos.

O .ps é um arquivo de texto que tem um cabeçalho mais ou menos assim:

%!PS-Adobe-3.0 EPSF-3.0
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: 0 0 2000 3000
%%LanguageLevel: 1
%%Pages: 1
%%Page: 1 1
<< /PageSize [2000 3000] >> setpagedevice
7 setlinewidth

Isso é mais um EPS do que um PS, mas assim o Photoshop entende e consegue abrir isso para salvarmos um jpg depois. Assim damos o tamanho da página, a largura da linha que vamos usar, etc.

Depois do cabeçalho seguem uma série de comandos. Cada um cria uma parte da imagem final. Um exemplo de comando é:

0.33 0.45 0.37 setrgbcolor
497.000 497.000 moveto
738.000 614.000 1854.000 1978.000 1503.000 2503.000 curveto
stroke

Começamos por estabelecer a cor que será usada, um ponto de partida, e desenhamos uma curva, por fim mandamos desenhar de fato com a palavra stroke.

A idéia de usar o Python é criar umas 100 linhas como essa em um único arquivo, com número que variam com incrementos ou randomicamente. Assim mudamos a cor da linha, a forma da curva, o ponto de partida, etc.

Com um pouco de sorte, os números encontram uma maneira esquisita de interagir e fazemos algo interessante. Na imagem acima há tanto um componente randômico com um componente incremental. Na imagem abaixo os números são randômicos.

Se quiser explorar esses caminhos, deixei os scripts e exemplos de arquivos PostScript em um repositório no GitHub.

Solarizações • Maragram Generator

Para exemplificar o funcionamento da solarização digital, dois exemplos de resultados, um de cada lado da imagem original. À esquerda, um exemplo de altas luzes invertidas e à direita, um exemplo de sombras invertidas.

Mas porque parar ai? Porque não passar a imagem mais uma vez pelo programa e criar mais ruídos interessantes?

E minha preferida até agora:

Enquanto isso, adicionei o app ao Play Store e abri uma sessão de testes. Foi horrível. As pessoas conseguiam baixar o app e instalar, mas ele não abria… A curva de aprendizado ainda aponta para cima, mais e mais.

Finalmente cheguei à versão 1.0.3 que abria sem muitos problemas na maioria dos dispositivos e estava a funcionar. Passou pelos pre-launch tests da PlayStore (que eu só descobri que existiam depois do fiasco da 1.0.0). Aprendi um tanto sobre os mínimos detalhes do arquivo Android Manifest e do arquivo Gradle Build… Aprendi sobre coisas que não pareciam importante no momento em que se cria o arquivo para trabalhar num projeto, no nome que se dá para isso ou aquilo, e de como isso afeta o bundle que é construído no final.

Alguns amigos finalmente conseguiram instalar e rodar o app no seus dispositivos Android e andaram usando a palavra “divertido” para definir o app. Dei o projeto como bem sucedido e concluído – consegui escrever um código novo, num pacote que ainda não tinha um determinado método, consegui implementar isso num app e publicar o app de maneira limitada e segura e ver ele funcionar nos dispositivos dessas pessoas.

Quando escrevi em Janeiro sobre o curso de Python que eu estava começando (e que consegui terminar!!!) eu ainda não imaginava por onde ia andar. Acabei me interessando pelo Flutter também e isso me levou ao Dart. A Angela Yu, professora do curso de Python no Udemy, sempre lembra que faz parte de ser programador a constante busca por exemplos e soluções pela internet. Ela defende que é impossível aprender tudo pela páginas de documentação. Essa última semana é prova disso e de que umas boas buscas pelo StackOverflow conseguem resolver a maioria dos problemas que nos aparecem.

Acho que ainda vou atualizar o código para incluir umas questões de acessibilidade, que o app deveria ter. Ajeitar uns pequenos detalhes. Tudo está disponível no meu Github para quem quiser avançar com a coisa.

Se você quiser experimentar no seu dispositivo Android, me manda uma mensagem com o email da sua conta da Play Store, eu libero a conta para o teste e devolvo um link para o app. Por enquanto a distribuição da app vai permanecer assim.