3 pontos por GN⁺ 2024-06-08 | 1 comentários | Compartilhar no WhatsApp
  • ASCII Silhouettify é um app para navegador e linha de comando que transforma gráficos planos e de alto contraste, como logos, banners e pixel art, em arte ASCII de silhueta preenchida usando apenas 95 caracteres ASCII imprimíveis
  • Aceita png, svg, jpg, webp, gif, tif, heif, avif e pdf como entrada, mas como não renderiza sombreamento, realces, sombras ou gradientes, não é adequado para converter fotos
  • A saída oferece suporte a texto colorido com ANSI, texto simples, HTML e formato de arte ASCII customizada do Neofetch; o formato do Neofetch é limitado a 6 cores da paleta ANSI estendida de 256 cores
  • O algoritmo de conversão divide a imagem em planos de cor e, em cada área de 9×19 pixels, escolhe o maior caractere ASCII que não invade o contorno da silhueta
  • Para desempenho, usa um acumulador de 95 bits, 171 bitmasks, cálculo de leading zeros e processamento paralelo em processadores lógicos; para correspondência de paleta, aplica a fórmula de diferença perceptual de cor CIEDE2000, computacionalmente custosa

App de conversão para silhueta ASCII

  • ASCII Silhouettify é um app que transforma imagens em silhuetas ASCII
    • Silhueta ASCII é um estilo de arte ASCII em que formas geométricas preenchidas de maneira uniforme se destacam mais do que linhas ou texturas
    • Funciona bem com gráficos planos minimalistas, de alto contraste e sem profundidade tridimensional, como logos, banners e pixel art
    • Como não renderiza sombreamento, realces, sombras nem gradientes, não é adequado para fotos
  • O conjunto de caracteres é limitado aos 95 caracteres ASCII imprimíveis, o meio tradicional dos artistas de ASCII
    • Não usa caracteres de linha/bloco comuns em arte ANSI nem muitos caracteres Unicode usados em kaomoji
  • O formato de saída varia conforme a configuração
    • Texto simples monocromático
    • Texto com cores usando sequências de escape ANSI
    • HTML com ou sem cor
    • Formato de arte ASCII do Neofetch
  • É um aplicativo de desktop que pode ser usado no navegador e na linha de comando

Exemplo com o logo do Ubuntu e Neofetch

  • O exemplo mostra o fluxo de uso do resultado do ASCII Silhouettify na saída do Neofetch em uma instância Ubuntu
  • Para obter a melhor arte ASCII, a imagem do logo do Ubuntu em alta resolução é buscada na web e primeiro redimensionada para o tamanho em que aparecerá no console
  • Ao converter a imagem com a versão de linha de comando, o padrão é gerar texto colorido com sequências de escape ANSI
  • Com a flag -o, é possível enviar a saída para o arquivo que o Neofetch exibirá
  • Como o Neofetch insere um espaço grande entre a arte ANSI e os indicadores do sistema, o exemplo usa o formato de arquivo de arte ASCII customizada do Neofetch
    • A primeira linha do arquivo de saída é uma lista de índices de cor
    • As linhas seguintes contêm a imagem codificada
    • A primeira linha é copiada para a área de transferência em um editor de texto e depois removida
    • Ao executar o Neofetch, o valor salvo na área de transferência é colado para uso
    • Para aplicar de forma permanente, parte do script bash do Neofetch é substituída pelo mesmo valor
  • Ao sobrepor o logo original ao resultado gerado para comparação, fica claro que o algoritmo escolhe o maior caractere que cabe dentro do contorno de cada região de cor

Instalação e remoção

  • A versão de linha de comando é uma aplicação Node.js
  • Se você não tiver Node.js, é preciso seguir primeiro o processo de instalação do Node.js
  • No macOS e no Linux, é necessário configurar o npm para permitir instalação global sem o usuário root
  • Comando de instalação:
    • npm install -g ascii-silhouettify
  • Comando de remoção:
    • npm uninstall -g ascii-silhouettify

Opções de entrada e saída

  • A versão para navegador e a versão de linha de comando oferecem o mesmo conjunto de opções
    • A flag -h da versão de linha de comando mostra uma mensagem resumindo as opções
  • É possível converter várias imagens de uma vez
    • Os formatos suportados são png, svg, jpg, webp, gif, tif, heif, avif e pdf
    • A flag -i da versão de linha de comando aceita várias regras de correspondência de padrões de nomes de arquivo
    • As imagens de entrada devem ter fundo preto ou transparente
  • A saída é dividida em quatro categorias
    • Texto simples ou texto colorido com ANSI
    • Texto monoespaçado em formato HTML
    • Formato de arte ASCII customizada do Neofetch
    • O formato do Neofetch é limitado a 6 cores da paleta ANSI estendida de 256 cores
  • O valor padrão da paleta é de 240 cores, excluindo a paleta ANSI padrão de 16 cores da paleta ANSI estendida de 256 cores
    • As 16 cores da paleta ANSI padrão ficam de fora por padrão porque costumam ser redefinidas em emuladores de terminal modernos
    • O usuário pode escolher as 8 primeiras cores da paleta ANSI padrão, as 16 cores ANSI padrão completas, as 256 cores ANSI estendidas completas ou a paleta padrão de 240 cores
  • É possível definir o número máximo de cores que aparecerão na saída
    • Cores consideradas fundo preto não entram na contagem
    • O padrão é 255
    • O modo monocromático, na prática, define esse valor como 1
    • No formato de arte ASCII customizada do Neofetch, o padrão é 6, que é o máximo desse formato

Ajuste do tamanho de exibição e da qualidade da conversão

  • A proporção da arte ASCII gerada em um emulador de terminal varia conforme a fonte, o tamanho da fonte, a altura da linha e as regras de arredondamento do tamanho dos caracteres
  • Para otimização, a imagem de texto do terminal é capturada, e o tamanho em pixels de cada caractere monoespaçado, incluindo o espaço entre linhas, é medido
  • Os exemplos de medição no desktop Windows do desenvolvedor são os seguintes
    • IntelliJ Terminal: caractere 8×22, tamanho da fonte 10, altura da linha 1.65
    • Putty: caractere 8×16, tamanho da fonte 10, altura da linha 1.2
    • Notepad: caractere 10×18, tamanho da fonte 13, altura da linha 1.04
    • Notepad++: caractere 9×19, tamanho da fonte 12, altura da linha 1.2
    • Windows Command Prompt: caractere 8×16, tamanho da fonte 10, altura da linha 1.2
    • Windows Console Host: caractere 9×20, tamanho da fonte 12, altura da linha 1.25
    • Windows Terminal: caractere 9×19, tamanho da fonte 12, altura da linha 1.2
  • O ideal é redimensionar previamente a imagem de entrada em um programa de edição para o tamanho desejado de exibição no terminal
    • Para pequenos ajustes, o ASCII Silhouettify aceita um fator de escala da imagem
    • O padrão é 1
  • O algoritmo de conversão transforma áreas com brilho inferior a 5% em caracteres de espaço para revelar completamente o fundo preto
    • O usuário pode ajustar esse limiar de escuridão
  • Por padrão, o trabalho é distribuído entre todos os processadores lógicos disponíveis
    • O usuário pode reduzir o número de processadores alocados até 1
    • Reduzir o número de processadores aumenta o tempo de processamento

Algoritmo de conversão

  • No desktop Windows em que o desenvolvedor criou o ASCII Silhouettify, o Terminal renderiza cada caractere monoespaçado dentro de um retângulo de 9×19 pixels usando a configuração padrão de Cascadia Mono em 12 pontos e 1.2em
  • O algoritmo captura imagens dos 95 caracteres ASCII imprimíveis e aplica limiar em 50% de intensidade para criar imagens de caracteres com apenas pixels pretos e brancos
  • A imagem de origem é separada em planos de cores únicos
    • Cada plano é uma silhueta branca sobre fundo preto
  • Cada plano de cor é dividido em uma matriz de regiões retangulares de 9×19 pixels
    • Cada região é substituída por um único caractere ASCII
  • O caractere ideal é escolhido comparando, pixel a pixel, a região com todas as imagens de caracteres ASCII
    • Se os pixels brancos da imagem do caractere se sobrepõem aos pixels pretos da região, esse caractere é descartado para não distorcer o contorno da silhueta
    • Entre os caracteres restantes, escolhe-se aquele com o maior número de correspondências de pixels brancos
  • Ao substituir a região por um caractere, o número de pixels brancos correspondentes é registrado
    • Depois de converter todos os planos, eles são combinados escolhendo o caractere com o maior número de pixels brancos correspondentes
    • O caractere final recebe a cor do plano do qual ele veio

Aceleração baseada em bitmask

  • Antes da conversão, as imagens dos caracteres ASCII são ordenadas pelo número de pixels brancos
    • O caractere de espaço tem 0 pixels brancos, o menor valor
    • O caractere @ tem o maior número de pixels brancos
  • O algoritmo compara cada região com as imagens de caracteres começando por @ e descendo
    • Assim que encontra um caractere que cabe completamente dentro da silhueta, substitui a região por esse caractere
    • Graças à ordenação, esse é o candidato com mais pixels brancos
  • Para aumentar muito a velocidade, são preparados 171 bitmasks para cada pixel de uma região de 9×19
    • Cada bitmask representa o conjunto de imagens de caracteres ASCII que têm um pixel preto naquela coordenada
    • Cada bitmask contém 95 bits
    • O bit-0 corresponde ao caractere de espaço, e o bit-94 ao caractere @
  • Durante a conversão da região, um acumulador de 95 bits vai reduzindo gradualmente o conjunto de candidatos ASCII disponíveis
    • No início, o acumulador é inicializado com todos os bits em 1
    • Para cada pixel preto da região, é feito um bitwise AND entre o acumulador atual e o bitmask correspondente àquele pixel
    • Essa operação elimina imagens de caracteres que tenham pixels brancos nas posições de pixels pretos da região
  • Após processar toda a região, os bits ligados no acumulador representam os candidatos que podem substituir a região
    • Como os caracteres estão ordenados, a quantidade de leading zeros no acumulador vira o índice da imagem do caractere ASCII com mais pixels brancos que cabe totalmente dentro da silhueta
    • Com ajuda de biblioteca, é chamada a instrução de cálculo de leading zeros do microprocessador para obter esse valor rapidamente

Otimização da origem e correspondência de cores

  • Ao dividir a imagem de origem em uma matriz de regiões retangulares, a origem da matriz afeta o resultado
  • Para otimizar o resultado, o algoritmo repete a conversão da imagem inteira para todas as origens em coordenadas inteiras dentro da área de 9×19 pixels ao redor da origem da imagem
  • Para dar conta do grande volume de processamento, o trabalho é distribuído entre os processadores lógicos disponíveis
  • A paleta de cores pode ser limitada, conforme a configuração do usuário, desde as 8 primeiras cores da paleta ANSI padrão até o conjunto completo de 256 cores ANSI estendidas
  • Ao separar a imagem de origem em planos de cores únicos, é usada a fórmula computacionalmente custosa de diferença perceptual de cor CIEDE2000 para encontrar a cor mais próxima dentro da paleta

Código-fonte

1 comentários

 
GN⁺ 2024-06-08
Comentários no Hacker News
  • Acho que a página mais legal desse site é a galeria colorida: https://meatfighter.com/ascii-silhouettify/color-gallery.htm...

    • O logo da Wendy's é meio sinistro
    • Sem o logo do Mastodon, esta página é inválida
    • O logo do Z é realmente inteligente
      Dá a sensação de fazer você enxergar design gráfico de ícones por outro ângulo
  • Fiz uma ferramenta parecida para criar sprites de jogo que podem ser colocados direto no código: https://memalign.github.io/m/pceimage/index.html
    Roda na web, e também dá para editar a saída ASCII colorida
    Mas é um pouco chato porque, para o resultado ficar bom, é preciso desativar manualmente o Wobble e ajustar o tamanho da amostragem de pixels

    • É realmente divertido e gostei bastante
      Como sugestão, seria legal ter um modo que removesse a tremulação, mas mantivesse a fofura gerada por deixar mais grosso e arredondar os cantos
  • Se você gosta de arte relacionada a ASCII, provavelmente também vai gostar de uma ferramenta de ASCII animado que converte GIFs em ASCII: https://www.gifcii.fun
    Só para constar, fui eu que fiz

    • Para quem gosta de GIFs, isso é realmente divertido
      Seria bom se desse para salvar de algum jeito; por exemplo, exportar de volta como GIF ou vídeo seria bem legal
  • A versão web não termina em navegadores baseados em Chromium, mas a versão CLI funciona: https://meatfighter.com/ascii-silhouettify/spa/index.html#/
    De quebra, também fiz uma arte ASCII grande que parece o logo do HN

  • Trabalho legal, e me lembra o Telnet Matrix com cores :)
    Depois também descobri https://ascii.theater/
    Há alguns anos fiz algo parecido para um conversor de imagens de computadores retrô, usando a fonte monoespaçada fixa daquele computador, e também apliquei dithering antes da conversão de caracteres
    Porque isso gerava gradientes mais suaves a partir de fotos: https://github.com/KodeMunkie/imagetozxspec/blob/master/src/...

  • “O que foi é o que há de ser, e o que se fez isso se tornará a fazer; de modo que nada há novo debaixo do sol.”
    Ficou muito bem feito
    Antigamente, usando EBCDIC e ASCII, eu imprimia banners de aniversário e imagens de forma muito parecida em impressoras de linha com papel contínuo e, depois, em impressoras matriciais, aproveitando a densidade de impressão dos caracteres

  • Acho que hoje bastante gente vai acabar editando /etc/motd ou /etc/issue

  • Já tentei algo parecido com uma função oscilante em movimento em tempo real: https://piter-genuary2024.netlify.app/genuary9/

    • Fico pensando se daria para criar algo bizarro que começasse como uma saída padrão de tail de logs, fosse misturando padrões cada vez mais visíveis e, no fim, fizesse surgir um rosto assustador no meio do texto
  • npm de novo
    O projeto é excelente, mas não entendo por que isso precisa ser feito assim
    Fico pensando para onde foi o jeito normal de instalar as coisas

    • Fico curioso para saber que alternativa você sugere
      NPM funciona do mesmo jeito em todo lugar, e não existe gerenciador de pacotes tão amplamente usado em várias plataformas quanto o NPM
    • Se você disser que método é esse “jeito normal de instalar”, dá para explicar quais são os problemas dele
    • Nem precisa instalar
      É só executar com npx
    • Pois é, também não sei o que aconteceu com o jeito normal de instalar as coisas, ou se ele sequer já existiu
      Sempre que tento configurar de outro jeito, perco horas e vira uma bagunça, então acabo ligando meus repositórios de CLI aqui e ali com npm/yarn link
      Até scripts em Python eu desenvolvo com nodemon main.py, então às vezes parece que só o pessoal do Node sabe o que é necessário
  • Mesmo assim, provavelmente vou continuar usando https://asciiflow.com/# em vez do Figma