Agrupar lista de imagens com nome

3

Como criar um agrupamento de imagens no formato:

image_name_1 [IMAGE#1]
image_name_2 [IMAGE#2]
image_name_3 [IMAGE#3]
...

Usando o Imagemagick, posso dizer algo como:

montage -label '%f' -mode concatenate -tile 1x foo*.png out.png

Mas isso adiciona o nome do arquivo abaixo da imagem + não considera a largura do nome.

Onde o nome do arquivo é impresso (como no eixo y cartesiano convencional) não é uma preocupação, tanto quanto é à esquerda da imagem correta . / p>

Qual ferramenta não é preocupante, desde que esteja disponível para Linux de 32 bits.

    
por user129107 13.05.2016 / 02:37

2 respostas

2

Não sou especialista em ImageMagick, então provavelmente há uma maneira melhor de fazer isso, mas você pode fazer isso em duas etapas, primeiro adicionando o texto à esquerda de cada imagem em um arquivo intermediário e depois fazendo a montagem.

for file in foo*.png
do  convert "$file" -splice 100x0 -gravity west -annotate +10+0 '%f' /tmp/"$(basename "$file")"
done
montage -mode concatenate -tile 1x /tmp/*.png out.png

Você precisa ajustar o valor de emenda 100 para ter largura suficiente para seu rótulo de nome de arquivo mais amplo.

Uma alternativa interessante que usa um único comando é

convert \
 $(for file in foo*.png
   do echo '(' label:"$(basename "$file")" -gravity center "$file" +append ')'
   done) -gravity west -append out.png

em que você usa +append para unir o rótulo e a imagem juntos horizontalmente e, em seguida, -append para unir os resultados verticalmente. Não é exatamente o que você precisa, mas pode ser um ponto de partida para novas experiências.

    
por 13.05.2016 / 09:44
2

Se alguém quiser hackear mais isso, aqui está uma bagunça, mas talvez algumas dicas ou ajuda que atraiam interesse.

O procedimento solicita altura e largura máximas dos nomes dos arquivos para gerar rótulos adequados. Uma característica que falta é a centralização vertical do texto (que, TBH, parece melhor).

Para obter largura + altura para um texto (como inteiro) é uma maneira de fazer:

convert -debug annotate  xc: -font Arial -pointsize 24 \
-annotate 0 'Test' null: 2>&1 | \
awk -vRS='[;.]' -F': ' '/width|height/{print $2}'

mas fazer isso para cada nome de arquivo em um loop adiciona um grande aumento no tempo / recurso ao ter moderadamente muitos arquivos +.

No script abaixo, portanto, gero dois arquivos temporários com todos os nomes de arquivos. Um para obter a altura máxima e outro para obter a largura máxima.

O procedimento seria interrompido se os nomes dos arquivos tivessem nova linha.

#!/bin/bash

# Default Options
font=Arial
font_size=12
pad=20

usage()
{
    cat <<EOF_USAGE
Usage: $0 [OPTION] <images>

  -f | --font       <font>
  -z | --font_size  <N>
  -h | --help       [f|font]
EOF_USAGE
    exit 1
}

# Check for user-options
while [[ "$1" ]]
do
    case "$1" in
    --font|-f)font=$2; shift;;
    --help|-h)
        if [[ "$2" = "f" || "$2" = "font" ]]
        then
            convert -list font
            printf "\nCMD: convert -list font\n"
        fi
        usage
        exit 1
        ;;
    --font_size|-z)font_size=$2; shift;;
    --pad|-p)pad=$2; shift;;
    --)shift; break;;
    *)break;;
    esac
    shift
done

# Shallow Next option check (is it a file at all?)
! [[ -f "$1" ]] && printf "Not a file: %s\n" "$1" && exit 2

printf "Processing %d files ...\n" "$#"

txt_w=0
txt_h=0
tmp_dir=$(mktemp -d)

printf "tmp dir : %s\n" "$tmp_dir"

images=("$@")

printf "Calculating max width / height ..."

# Find max width from file names using font + font-size
txt_w=$(convert \
    -debug annotate  xc: \
    -font "$font" \
    -pointsize "$font_size" \
    -annotate 0 "\"$(printf "%s\n" "${images[@]}")\"" null: 2>&1 | \
    sed -n 's/.*Metrics:.* width: \([^.;]*\)[;.].*//p' | sort -n | tail -n1)

# Find max height from file names using font + font-size
txt_h=$(convert \
    -debug annotate  xc: \
    -font "$font" \
    -pointsize "$font_size" \
    -annotate 0 "\"$(printf "%s" "${images[@]}")\"" null: 2>&1 | \
    sed -n 's/.*Metrics:.* height: \([^.;]*\)[;.].*//p')

printf "\r3[KWidth   : %d\n" "$txt_w"
printf "Height  : %d\n" "$txt_h"

# Add padding pixels
(( txt_w+=pad*2 ))

# Create the labeled images
for img in "${images[@]}"
do
    printf "\r3[KCreating label for \'%s'" "$img"
    convert "$img" \
        -splice ${txt_w}x$txt_h \
        -gravity west \
        -font "$font" \
        -pointsize $font_size \
        -annotate +$pad+0 '%f' \
        "$tmp_dir"/"$(basename "$img")"
done

printf "\r3[KMontage ...\n"

# Combine / Collate / Montage
montage -mode concatenate -tile 1x $(printf "$tmp_dir/%s " "${images[@]}") out.png

printf "Done!\n"

# Clean up
rm -r "$tmp_dir"
    
por 15.05.2016 / 04:50