Como converter imagem para código ASCII

@Daigo Tem uma ferramenta chamada jp2a que transforma imagens (jpg ou jpeg) em ASCII, olha uma com a sua logo:

Acho que esse é o tamanho adequado pro neofetch:

6 curtidas

Tentarei fazer isso agora a tarde.

1 curtida

Isso fica salvo em algum lugar pra poder usar?

2 curtidas

É um pacote, então é só instalar pelo apt e pronto.

Instalei e funcionou, minha dúvida é se ele salva a img gerada.

A imagem não, pra colocar no neofetch que criei tive que copiar dentro de aspas, mas é kinda confuso. Tem que criar uma variável com a imagem copiada (pq é texto) dentro de aspas e embaixo colocar a imagem pra iniciar com o script, mas tem uma solução mais simples: criar um arquivo e colar a imagem dentro, depois rodar o neofetch com o parâmetro --ascii e depois coloca o nome do arquivo que aí a imagem criada sai automaticamente no Neofetch, exemplo:

neofetch --ascii nomedoarquivo.txt

Tem outra ainda mais simples na verdade:

jp2a … | tee /caminho/pro/arquivo.txt

1 curtida

Alguns outros pacotes que transformam imagens em ascii:

aalib (b&w), libcaca (colour)
img2txt (from libcaca), cacaviewer, aatest, aview, jp2a, pixterm
usage: CACA_DRIVER=[aalib|libcaca|chafa|curses]

Fogo em ascii:

$ CACA_DRIVER=ncurses cacafire

bbb

Para transformar um texto em ascii, tem o figlet.

3 curtidas

Esses aí eu não conhecia. :thinking:

Com certeza Não sei se outro script assim circula pela internet, mas fiz scripts que convertem a saída do jp2a em um formato que pode ser utilizado no neofetch:

jp2nf.pl
#!/usr/bin/env perl

open $jp2a,'-|','jp2a','--color','--color-depth=4',@ARGV;

# Array com as cores usadas.
@colors = ();
# Lookup table cor → ordem de aparecimento
%cind = ();
# Cor sendo usada agora.
$cc = 1;
$i = 1;


while (<$jp2a>) {
        while (m{\e\[([0-9]+)m([[:print:]])}g) {
                $color = $1;
                $char = $2;
                if ( ($color != 0) && ($cc != $color) ) {
                        if (not exists($cind{$color})) {
                                push @colors, $color;
                                $cind{$color} = $i;
                                $i++;
                        }
                        $cc = $color;
                        print "\${c$cind{$cc}}";
                }
                print $char;
        }

        print "\n";
}

$msg="Use neofetch command line: --ascii_colors " .
        join(" ", map { substr($_,1,1); } @colors);

print STDERR "$msg\n";

Atualização: versão puro shell

jp2nf.sh
#!/bin/sh

# Cor atual
cc=1

# tr + sed = sed (?).
# Cortar a "primeira linha" sem nada no começo.
jp2a --color --color-depth=4 "$@" | sed "y/$(printf '%b' '\033')/\n/;1s/^\n//g" | {

	# Descartar parâmetros passados para o script inicial
	# Vamos usar o `set` como array de pobre.
	set --

	while IFS=m read -r COLOR CHAR; do
		# Vazio: estamos no final de uma linha.
		# Ecoar uma nova linha e nem se estressar em processar ela.
		if [ -z "$COLOR" ]; then
			echo
			continue
		fi

		# Obter o número da cor, cortando o [ inicial
		COLOR=${COLOR#'['}
		
		# Observer mudanças de cor
		# (menos o reset (0) que o jp2a faz a cada caractere)
		if [ "$COLOR" -ne 0 ] && [ "$cc" -ne "$COLOR" ]; then
			f='' # Variável vai ficar definida se a cor estiver na lista
			j=1  # Número X da cor (${cX} do neofetch)
			for arg; do
				if [ "$arg" = "$COLOR" ]; then 
					# Cor existe na array
					f=1
					break
				fi
				j=$((j+1))
			done
	
			if ! [ "$f" ]; then
				# Cor não está na lista, adicionar
				set -- "$@" "$COLOR"
			fi

			# Registar a mudança de cor
			cc=$COLOR
			printf '%s' "\${c${j}}"
		fi

		# Seja qual for a cor, ecoar o caracter
		printf '%s' "$CHAR"
	done

	echo # Evitar EOF (do último printf %s $CHAR)

	# Mostrar --ascii_colors do neofetch a ser usado
	msg='Use neofetch command line: --ascii_colors' 
	for arg; do
		msg="$msg ${arg#3}"
	done
	echo >&2 "$msg"
}

Exemplo:

$ chmod +x ./jp2nf.sh
$ ./jp2nf.sh avatar.png --width=45 > avatar.txt
Use neofetch command line: --ascii_colors 2 3 5 4
$ neofetch --ascii avatar.txt --asci_colors 2 3 5 4 # ou na config

O script em Perl exige Perl (evidentemente), e o script em puro shell requer apenas um sistema Linux com ferramentas de linhas de comando básicas.

Os dois apenas trabalham a saída do jp2a, é preciso tê-lo instalado para os scripts funcionarem.

2 curtidas

O “tee” não é built-in para usar o built-in do bash que tornaria a execução mais rápida seria:

$ jp2a … >/caminho/pro/arquivo.txt
Ou
$ jp2a … >>/caminho/pro/arquivo.txt
1 curtida

Nesse caso o tee é o mais indicado nesse caso, por partes:

O tee é o “conector T” ele recebe a saída, escreve ela no /dev/stdout e escreve num arquivo:

comando | tee arquivo | outro comando

E a principal vantagem:

Se você precisa escrever em pastas protegidas (nesse caso por exemplo) basta rodar o tee como root:

echo "Olá mundo" | sudo tee /usr/teste.txt
cat /usr/teste.txt

O equivalente usando apenas buit-in no bash seria:

sudo bash -c 'echo Olá mundo > /usr/teste.txt && cat /usr/teste.txt'

Bem mais complexo

Descobri agora sobre esse comando, foi uma grande ajuda.

Não pó o echo ai precisa ser executado com o “bash -c” porque o echo é built-in do bash.
O jp2a não é built-in se executar assim:

$ sudo jp2a … >/caminho/pro/arquivo.txt

Ele grava mesmo no /usr/teste.txt.
Só built-in do bash que precisa ser executado com o bash -c para funcionar.

Eu fiz um teste de performance do tee e olha só.

tee
real    1m23,039s
user    1m21,940s
sys     0m23,154s

built-in
real    0m3,500s
user    0m1,364s
sys     0m2,127s

O teste foi feito na minha maquina com o tee e o built-in sendo executado 100 mil vezes.
Eu tentei com eles sendo executado 30 milhões de vezes mais o tee é muito lento acabava nunca.

Para vocês poder reproduzir o teste na maquina de vocês é assim:

#!/usr/bin/env bash

echo "#!/usr/bin/env bash

# Teste de performance tee e built-in." >./test.sh

int=0
while [[ ! "${int}" == "100000" ]]
do
echo "echo 'Teste de performance do built-in do bash em comparação ao software tee.' >./tst.txt" >>./test.sh
int=$(((${int}+1)))
done

Executa este escript com o tanto de repetição do while que você desejar e então depois executa o script que foi gerado chamado “test.sh” com $ time bash test.sh e então vai aparecer o teste de performance.
Eu usei o

[[ ! "${int}" == "100000" ]]

Ao invés do

[[ ! "${int}" -eq "100000" ]]

Porque o primeiro “==” é mais rápido que o -eq ainda mais que seria executado em um while de 30 milhões de vezes.

Aproveitando o tópico, quais seriam as alternativas ao código ASCII?

1 curtida

Pra mostrar imagens no terminal tem também a gambiarra usada por w3m, imgcat e companhia que permite mostrar as próprias imagens direto do terminal. Tem uma explicação mais detalhada na wiki do Neofetch.

1 curtida

É só pra exemplo

Não salva em diretórios protegidos

Se o bash tiver executado como root (su ou sudo bash)

Sim, a principal vantagem universal do tee é sua maldição, essa diferença de performance tão gritante ocorre porque o o tee escreve duas vezes, além de ler o HD toda vez que é executado

Não nego que o tee é mais lento, porém pra esse caso em específico ele é mais indicado


Experimenta rodar o mesmo teste com dois echos um exibindo e outro escrevendo, da diferença cai significativamente

Do jeito que você disse fica.

real    0m4,184s
user    0m2,068s
sys     0m2,107s

O que faz o echo demorar não é o print na tela, o que faz ele demorar é a gravação no disco pelo atraso de gravação no SSD.
Built-in é muito mais rápido que não built-in.

Estranho aqui a diferença foi de 15s só para o echo

Foi por isso que eu parte na primeira tentativa com 30 milhões de vezes o tee, porque todas as outras vezes eu tinha feito o teste de performance só com built-in e nunca sem ser built-in e nunca tinha gravado a saida no armazenamento.
Então eu sempre fiz com milhões de repetições.