Compor imagens remotas com cURL e ImageMagick
Use o cURL para baixar uma imagem de fundo e uma sobreposição, depois o ImageMagick para redimensioná-las e salvar um único JPEG. O script Bash abaixo verifica as duas transferências HTTPS e remove seus arquivos parciais se um download ou uma etapa de processamento de imagens falhar.
Verificar as ferramentas
Esta receita foi testada no Linux com Bash 5.3.15, cURL 8.22.0 e ImageMagick 7.1.2-31 com suporte a
JPEG e PNG. Essas são as versões testadas, não versões de correção obrigatórias. Use versões com
manutenção ativa do cURL e do ImageMagick 7.
A versão do cURL deve ser pelo menos 8.4: versões anteriores não conseguem impor o limite de
--max-filesize quando o tamanho da resposta é desconhecido.
Verifique bash --version, curl --disable --version e magick -version antes de salvar o script.
Use imagens RGB de um único quadro com fundo opaco; a sobreposição PNG pode ter transparência.
O exemplo usa uma foto JPEG e um logotipo PNG da NASA. Siga as
orientações da NASA para o uso de imagens e mídia,
incluindo suas restrições sobre a insígnia e o endosso.
Salvar o script de composição
Cada imagem de origem é baixada para um novo diretório privado. Passar <(curl ...) diretamente ao
ImageMagick dificultaria a verificação do status de saída da transferência da imagem de fundo.
Salvar e verificar as entradas reais também evita testar uma URL com uma requisição e processar
uma segunda resposta sem verificá-la.
Salve este script como compose.sh. Ele recebe duas URLs HTTPS confiáveis e um novo diretório de saída cujo diretório pai
já existe:
#!/bin/bash
set -euo pipefail
if [ "$#" -ne 3 ]; then
echo "Usage: $0 <background-https-url> <overlay-https-url> <new-output-directory>" >&2
exit 1
fi
background_url=$1
overlay_url=$2
output_dir=$3
if ! command -v curl >/dev/null || ! command -v magick >/dev/null; then
echo "Install cURL and ImageMagick 7 before running this script" >&2
exit 1
fi
[[ $output_dir = /* ]] || output_dir=$PWD/$output_dir
if ! mkdir -m 700 -- "$output_dir"; then
echo "Use a new output directory" >&2
exit 1
fi
cleanup() {
local status=$?
rm -f -- "$output_dir/background.image" "$output_dir/overlay.image" "$output_dir/magick.log"
if [ "$status" -ne 0 ]; then
rm -f -- "$output_dir/result.jpg"
rmdir -- "$output_dir"
fi
}
trap cleanup EXIT
fetch_image() {
curl --disable --globoff --fail --silent --show-error --location \
--proto '=https' --proto-redir '=https' --max-redirs 3 \
--connect-timeout 10 --max-time 30 --retry 2 --retry-max-time 60 \
--max-filesize 10485760 --output "$2" --url "$1"
}
fetch_image "$background_url" "$output_dir/background.image"
fetch_image "$overlay_url" "$output_dir/overlay.image"
cd -P -- "$output_dir"
output_dir=$PWD
if ! magick -limit memory 256MiB -limit map 512MiB -limit disk 1GiB \
-limit width 10000 -limit height 10000 \
background.image -resize '1600x1600>' \
\( overlay.image -resize '300x300>' \) \
-gravity southeast -geometry +20+20 -composite result.jpg 2>magick.log ||
[ -s magick.log ]; then
cat magick.log >&2
echo "ImageMagick reported a failure or diagnostic" >&2
exit 1
fi
[ -s result.jpg ] || { echo "No image produced" >&2; exit 1; }
echo "Composite saved: $output_dir/result.jpg"
Executar o exemplo
Execute o script salvo a partir do diretório que contém compose.sh:
bash compose.sh \
'https://images-assets.nasa.gov/image/as11-40-5874/as11-40-5874~orig.jpg' \
'https://www.nasa.gov/wp-content/uploads/2023/04/nasa-logo-web-rgb.png' \
nasa-composite
Abra nasa-composite/result.jpg: ele deve mostrar a foto do pouso na Lua com o logotipo da NASA no
canto inferior direito. O retângulo branco do logotipo faz parte do PNG de origem.
A imagem de fundo cabe em 1600 × 1600 pixels e a sobreposição em 300 × 300, preservando as
proporções. O > entre aspas em cada geometria de redimensionamento
impede a ampliação. -gravity southeast -geometry +20+20 posiciona a área de desenho da sobreposição a 20 pixels
das bordas direita e inferior. Se você substituir as imagens por outras menores, deixe espaço
suficiente para a sobreposição e as duas margens; o script não reduz uma sobreposição grande demais
para que caiba na imagem de fundo.
Uma tarefa bem-sucedida imprime Composite saved: seguido do caminho absoluto e deixa apenas
result.jpg no novo diretório. Executar o script novamente com o mesmo diretório falha antes de baixar
qualquer coisa e preserva o resultado anterior. Mantenha outros processos fora do diretório da
tarefa enquanto o script estiver em execução.
Tratar falhas e novas tentativas
Erros HTTP, transferências que excedem 10 MiB por imagem de origem e imagens que não podem ser decodificadas resultam em um status de saída diferente de zero e na remoção do novo diretório da tarefa. Corrija a URL ou a entrada e tente novamente com o mesmo nome de diretório. Um diretório existente ou a ausência do diretório pai é uma falha de configuração; o script não altera o que já está armazenado.
Uma transferência abortada pode gravar brevemente mais dados que o limite; a limpeza remove esse arquivo temporário.
O ImageMagick pode recuperar pixels de um JPEG danificado enquanto emite avisos e retorna sucesso. Aqui, qualquer diagnóstico gravado em stderr também faz a tarefa falhar, imprime o diagnóstico e aciona a limpeza. Isso rejeita deliberadamente tanto avisos quanto erros. Não é possível detectar danos que um decodificador aceita silenciosamente, então inspecione a imagem final antes de publicá-la.
A função auxiliar de download permite três redirecionamentos HTTPS e duas novas tentativas para falhas que o cURL considera passíveis de nova tentativa. Cada tentativa tem um tempo limite de 30 segundos. A janela de 60 segundos para novas tentativas controla se outra tentativa pode começar; uma tentativa já em execução pode terminar após essa janela.
Definir limites para entradas confiáveis
Um arquivo comprimido pequeno pode ser decodificado em uma imagem grande. O script limita as dimensões das entradas e os recursos do cache de pixels do ImageMagick, que pode recorrer ao disco. Essas configurações não limitam a memória total do processo nem o tempo de processamento. Use a política de segurança do ImageMagick e os limites do sistema operacional ao executar processos de trabalho em produção.
Requisições restritas a HTTPS ainda permitem URLs e redirecionamentos para serviços de rede privada.
Use fontes confiáveis; um serviço público de busca de URLs sem restrições precisa de controles
separados de rede e de origem. Mantenha a verificação TLS ativada. --disable, colocado primeiro, impede o cURL de carregar um arquivo de configuração padrão que
poderia alterar essas opções de download.
Para fluxos de trabalho gerenciados de redimensionamento e composição, conheça o serviço de processamento de imagens da Transloadit.
