Como gerar certificados automaticamente no Linux com ImageMagick

Em eventos ou projetos colaborativos, é comum precisar criar dezenas de certificados de participação. Fazer isso manualmente é um trabalho cansativo e repetitivo, mas com um simples script em shell e o ImageMagick, é possível gerar tudo de forma automática e profissional.

Abaixo mostro como fiz para criar os certificados do Arte pela Paz 2025, mas você pode adaptar o mesmo processo para qualquer evento.


1. Preparando a arte do certificado

Crie seu modelo base no Canva (ou outro editor de imagem).
A ideia é deixar todo o visual pronto: logos, moldura, textos fixos, assinaturas, e reservar um espaço central para o nome da pessoa.

Ao finalizar:

  • Exporte a imagem como PNG de alta qualidade (A4, orientação horizontal é ideal).
  • Salve o arquivo com o nome: modelo-br.png ou modelo-en.png se quiser ter uma versão em inglês.

2. Criando a lista de nomes

Abra um editor de texto simples (como o Kate, Gedit ou o próprio nano) e insira um nome por linha:

Jurema Gonlçavez
Ricardo Duarte Pereira
Laura Silva e Souza
...

Salve o arquivo como:

nomes-br.txt

Se for criar certificados em outro idioma, você pode manter uma segunda lista:

nomes-en.txt

3. Instalando o ImageMagick

No Linux (Ubuntu, KDE Neon, Mint, etc.), instale com:

sudo apt install imagemagick -y

Você pode verificar se está funcionando com:

magick -version

Se o comando magick não existir, o script automaticamente usa convert, que também faz parte do ImageMagick.


4. O script para gerar os certificados

Crie um novo arquivo chamado gerar_certificados.sh e copie o código abaixo:

#!/usr/bin/env bash
set -euo pipefail

# ======== CONFIGURAÇÕES BÁSICAS ========

# Define o idioma: "br" ou "en"
IDIOMA="br"
# IDIOMA="en"

# Arquivo de modelo de fundo e lista de nomes dependem do idioma
TEMPLATE="modelo-${IDIOMA}.png"
NAMES_FILE="nomes-${IDIOMA}.txt"

# Fonte para o nome (troque para a que você tiver)
FONT_FILE="Anastasia-Script.ttf"

# Pasta de saída
OUT_DIR="saida"

# Gera em MAIÚSCULAS? 1 = sim, 0 = não
TO_UPPER=0

# Cor do nome (usei um dourado aproximado)
NAME_COLOR="#DAA520"

# Posição do nome: usamos -gravity Center + deslocamento vertical
GRAVITY="Center"
OFFSET_Y=-100  # negativo sobe, positivo desce

# Tamanho da fonte (ajuste automático por comprimento)
NAME_PT_MAX=50
NAME_PT_MIN=50
THRESHOLD=20

# Detecta o comando do ImageMagick (magick ou convert)
IM_CMD="magick"
command -v magick >/dev/null 2>&1 || IM_CMD="convert"

# ======== FUNÇÕES ========

sanitize_filename() {
  local s="$1"
  s=$(printf "%s" "$s" | iconv -f UTF-8 -t ASCII//TRANSLIT 2>/dev/null || printf "%s" "$s")
  s=$(printf "%s" "$s" | tr '[:upper:]' '[:lower:]')
  s=$(printf "%s" "$s" | sed 's/[^a-z0-9]/-/g; s/-\+/-/g; s/^-//; s/-$//')
  printf "%s" "$s"
}

calc_pointsize() {
  local name="$1"
  local len=${#name}
  local size=$NAME_PT_MAX
  if (( len > THRESHOLD )); then
    local drop=$(( (len - THRESHOLD) * 2 ))
    size=$(( NAME_PT_MAX - drop ))
    if (( size < NAME_PT_MIN )); then
      size=$NAME_PT_MIN
    fi
  fi
  printf "%s" "$size"
}

ensure_outdir() {
  mkdir -p "$OUT_DIR"
}

to_upper_smart() {
  local s="$1"
  if (( TO_UPPER == 1 )); then
    if command -v python3 >/dev/null 2>&1; then
      python3 - <<PY
s = "$s"
print(s.upper())
PY
    else
      printf "%s" "$s" | tr '[:lower:]' '[:upper:]'
    fi
  else
    printf "%s" "$s"
  fi
}

render_name() {
  local raw_name="$1"
  [[ -z "$raw_name" ]] && return 0

  local NAME
  NAME="$(to_upper_smart "$raw_name")"
  local PSIZE
  PSIZE="$(calc_pointsize "$NAME")"
  local SAFE
  SAFE="app2025-${IDIOMA}-$(sanitize_filename "$raw_name")"
  local OUTPNG="$OUT_DIR/${SAFE}.png"

  local cmd=("$IM_CMD" "$TEMPLATE")
  cmd+=(-gravity "$GRAVITY" -font "$FONT_FILE" -pointsize "$PSIZE" -fill "$NAME_COLOR" \
        -kerning 1 \
        -annotate +0+${OFFSET_Y} "$NAME" \
        "$OUTPNG")

  "${cmd[@]}"
  echo "OK: $OUTPNG"
}

# ======== MAIN ========
[[ -f "$TEMPLATE" ]] || { echo "ERRO: não encontrei $TEMPLATE"; exit 1; }
[[ -f "$FONT_FILE" ]] || { echo "ERRO: não encontrei $FONT_FILE"; exit 1; }
[[ -f "$NAMES_FILE" ]] || { echo "ERRO: não encontrei $NAMES_FILE"; exit 1; }

ensure_outdir

while IFS= read -r line || [[ -n "$line" ]]; do
  [[ -z "$line" ]] && continue
  render_name "$line"
done < "$NAMES_FILE"

echo "Concluído. Imagens geradas em: $OUT_DIR/"

5. Estrutura de pastas recomendada

certificados/
├─ modelo-br.png
├─ modelo-en.png
├─ nomes-br.txt
├─ nomes-en.txt
├─ Anastasia-Script.ttf
└─ gerar_certificados.sh

Baixe o arquivo da fonte usado neste exemplo, mas pode ser qualquer outra fonte, basta alterar no script.
https://www.dafont.com/pt/anastasia-script.font


6. Tornando o script executável

No terminal, dentro da pasta do projeto:

chmod +x gerar_certificados.sh

7. Gerando os certificados

Para gerar as versões em português:

./gerar_certificados.sh

Para gerar em inglês, edite o script e troque:

IDIOMA="en"

e execute novamente.

As imagens serão salvas na pasta:

saida/

Cada arquivo terá o nome automático com prefixo:

app2025-br-nome-do-participante.png

Resultado final:


8. Dica extra: converter tudo para PDF

Se quiser gerar PDFs a partir das imagens:

magick saida/*.png certificados-2025.pdf

Isso cria um único arquivo com todos os certificados.


9. Conclusão

Com esse método, é possível gerar dezenas (ou centenas) de certificados automaticamente, mantendo consistência visual e economia de tempo.