Fazer um panorama de imagens para carrossel de Instagram
Aqui um comando que parece meio mágico:
magick montage -background "#000000" -geometry +1 -resize "50%" -tile $(ls Feed-*.png | wc -l)x1 Feed-*.png panorama.pngMas o que cada parte dele faz?
magick- Invoca o programa.montage- Inicia o módulo do programa encarregado de fazer montagens.-background '#000000'- Define o fundo como preto.-geometry +1- Determina um offset de 1 pixel. Mais no link da documentação.-resize "50%"- Já que estamos juntando imagens de 1080 pixels de largura em um carrossel, os arquivos podem rapidamente ficar pesados demais para aprovação interna. Desta forma diminuímos as dimensões do arquivo pela metade para ficar mais leve.-tile $(ls Feed-*.png | wc -l)x1- Usamos uma combinação do parâmetrotilee um subshell para definir o arranjo das imagens. Do jeito que está escrito fará uma única fileira horizontal de imagens com o formato Feed-*.png como nome, formando um panorama. Por exemplo, Feed-1.png, Feed-2.png, Feed-3.png, e assim por diante. Caso o parâmetro tile seja omitido, imagemagick vai decidir sozinho as proporções do arranjo. Uma sequência de 6 imagens poderia ser arranjada, por exemplo, em um grid de 3x2. Mais informações aqui e na documentação oficial. Uma explicação mais detalhada pode ser encontrada abaixo.Feed-*.png- Usamos o asterisco para selecionar todas imagens neste formato de nome.panorama.png- Salvamos o arquivo como panorama.png
Sobre o comando de tile:
O parâmetro tile é responsável por definir o layout da nossa montagem de fotos. Ele aceita valores no formato larguraxaltura. Um conjunto de seis imagens, por exemplo, poderia ser arranjado em 2x3 ou 3x2. No nosso caso, um feed de seis imagens precisaria ser explicitado como 6x1. Carrosséis, porém, tem larguras que podem variar. A necessidade, portanto, é a de parametrizar o comando para que ele mesmo saiba quantas imagens devem ser processadas. Neste caso empregamos algo chamado subshell, que é basicamente uma maneira de rodar um comando dentro de outro. Foi usado porque queremos explicitar para o programa que queremos um panorama com exatamente o número de imagens que obedeçam a determinado requisito, neste caso ter o nome Feed-x.png, sendo x qualquer número. Assim temos:
$(ls Feed-*.png | wc -l)x1Aonde $ abre o subshell, que virá entre parênteses. Pedimos para listar com ls todos os arquivos no formato Feed-*.png. Encaminhamos esse output com o operador pipe | para o comando wc. Normalmente wc faz a contagem de palavras (wordcount), porém aqui especificamos com -l que queremos uma contagem de linhas. Ou seja: liste todos os arquivos com nome especificado, pegue esse output e conte quantas linhas são printadas. Dessa maneira conseguimos o número de imagens para o carrossel.
Um método alternativo para panoramas
Neste usamos o método convert para selecionar todos os arquivos no formato Feed-x.png, com o parâmetro +append para colar todas as imagens lado a lado. Finalmente damos o -resize para diminuir o tamanho do arquivo, e determinamos o nome do arquivo de saída como output.png.
convert Feed-*.png +append -resize "50%" output.pngEste método é mais legível e consideravelmente mais simples, porém não cria as linhas de divisórias entre as imagens. Deve-se avaliar qual o melhor método para diferentes usos.
Modificando o método acima para criar um mosaico de imagens
Utilizando uma estrutura de comando parecida com a de fazer panoramas, podemos utilizar o comando abaixo para criar um mosaico de imagens. Essa função pode ser muito útil para criar um painel de referências, por exemplo.
magick montage -background '#ffffff' -geometry 128x128+1+1 *.jpg *.png *.jpeg mosaico.pngJá destrinchamos o que cada parte dele faz lá em cima lá em cima, portanto, veremos somente os comandos que tiveram mudanças.
-geometry 128x128+1+1- O primeiro parâmetro128x128define o tamanho largura x altura do-tiledo nosso mosaico. Nesse exemplo, definimos um tamanho de tile pequeno para não gerar uma imagem final muito grande. É possível, utilizando por exemplo128xespecificar somente a largura oux128para somente a altura. A segunda parte+1+1define o espaçamento em pixels entre os tiles.*.jpg *.png *.jpeg- Nessa seção, delimitamos as extensões das imagens que o imagemagick buscará para fazer o mosaico. No nosso exemplo utilizamos três, mas você pode utilizar quantas quiser.
Note que, diferentemente do exemplo do carrossel, aqui não especificamos um tile. Isso se dá porque o imagemagick é bem espertinho para gerar mosaicos. Mais informações neste link.
Converter múltiplos arquivos de uma pasta
Para converter múltiplos arquivos de uma pasta é possível usar o comando mogrify. O comando a seguir, por exemplo, converte para .png todos os arquivos .HEIC e, em seguida, todos os arquivos .heic.
Importante
O parâmetro
-formaté necessário para que os arquivos não sejam substituídos após conversão:
mogrify -format png *.HEIC *.heicRemover o fundo branco de imagens
magick input.jpg -fuzz 20% -transparent white output.pngOnde o parâmetro -fuzz controla a precisão da seleção do branco. Quanto maior o valor mais “agressivo” será a remoção do branco e sua substituição pelo Alpha.
Trabalhando com GIFs
O comando básico para criar gifs a partir de imagens estáticas usando ImageMagick é o seguinte:
magick -delay 3 -loop 0 *.jpg output.gifOnde:
-delaydetermina o tempo entre uma imagem e outra. É medido e centésimos de segundos. Um vídeo de 30fps teria um valor de delay de aproximadamente 3.-loopdetermina quantas vezes o loop de imagens deve acontecer. Ao passar o número zero o loop acontece para sempre.*.jpgwildcard pega todos os jpgs presentes na pasd
Ainda é possível unir diferentes gifs em um só:
magick image1.gif image2.gif output.gifUm lembrete sobre otimização
No passado precisei juntar vídeos e imagens em um arquivo de gif só. O problema é que vídeos tem framerates altos, e uma sequência de imagens a 30fps, por exemplo, rapidamente geram um gif com tamanho imenso, normalmente na casa das dezenas de megabytes!
Porém, existem duas maneiras possíveis contornar o problema. Na primeira criamos diferentes gifs com diferentes framerates e juntamos todos com o comando citado acima. É um processo que funciona, mas fica rapidamente tedioso e que dificulta a alteração deles no futuro.
Na segunda lançamos mão de um fato interessante sobre a especificação do arquivo gif. Ao contrário de vídeos, que possuem framerates globais, no gif cada frame contém a informação de por quanto tempo deve ser visto. Assim, misturando imagens estáticas e vídeos, é possível usar uma função de otimização embutida no ImageMagick que remove frames idênticos.
magick input.gif -coalesce -layers RemoveDups output.gifIsso permitiria um processo mais flexível, com inclusive a possibilidade de usar editores de vídeo. O processo então seria:
- Editar o vídeo da maneira que preferir.https://www.youtube.com/watch?v=4JgTHz41KkQ
- Exportar o vídeo como sequência de frames. Nota: Tenho usado o formato jpg com qualidade média. O formato gif só suporta 256 cores, portanto a imagem será altamente comprimida e não faz sentido usar um pngs, por exemplo.
- Fundir os frames em um único gif usando ImageMagick. Nota: este processo pode demorar algum tempinho e usar bastante RAM.
- Passar o gif pela otimização acima para remover frames duplicados.
Com esse processo já consegui uma redução de até 20x no tamanho do gif final.