Agregar texto a imagen desde terminal

[Bash] [Script] [Imagemagick]

En los últimos días me surgió la necesidad de agregarle texto a unas imágenes en forma secuencial desde una base de datos. Esto no es muy complicado, pero no disponía de mucho tiempo para sacar ese trabajo y tuve que hacerlo con GIMP . Soy muy perezoso y lo primero que se me vino a la mente fue hacer un script para llenar estos datos, pero era bastante información y, al ser un trabajo de urgencia, no podía arriesgarme a no entregar a tiempo las cosas. El trabajo ya está entregado y todo fue bien, pero me quedé con esa idea en la mente y no quiero volver a pasar por algo similar, así que el día de hoy te voy a mostrar la primer parte de un script para automatizar el proceso.

Texto a imagen

Lo primero que hice fue buscar entre la documentación de una herramienta que ya había usado anteriormente con excelentes resultados: Imagemagick . Al ponerme a leer sobre la sintaxis para “hablar” con esta aplicación por terminal, noté que son muchos los parámetros y tenía mucha “paja” entre las opciones para sobreponer simplemente un texto. Si quiero automatizar el proceso sería más óptimo algo como $comando imagen.png texto fuente color posicion y se acabó. Pero al tener tantas opciones se complican las cosas, así que la primer tarea fue hacer un script para simplificar la forma de procesar estos datos, intentando no limitar las posibilidades que ofrece Imagemagick, y poder utilizar el script para muchas más tareas cuándo se requiera.

Para fines prácticos pensaba hacer los ejemplos con boletos de rifa pero, como no encontré imágenes libres y con permiso para modificar, opté por personalizar la imagen de una tarjeta de crédito y agregar un nombre en ella.

Credit Card

Imagen original de: freesvg.org

Entre los ejemplos para trabajar con texto en esta herramienta, el que elegí para iniciar fue este:

convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \
	-fill black -draw "text 28,68 'Anthony'" \
	-fill white -draw "text 25,65 'Anthony'" \
	font_shadow.jpg

En esta parte es donde considero que “hay mucha paja” y es poco práctico para comenzar a automatizar cosas. Pero primero me centré en poder modificar una imagen, ya que el ejemplo de arriba esta generando nada más un archivo desde el texto que se introduzca como parámetro. Después de leer un poco y entender como hacer las cosas quedó así:

convert "CreditCard.png" -gravity Center -font Ubuntu -pointsize 45 \
	-fill white -draw "text 55,-50 'Mark Zuckerberg" \
	CreditCart_Zukerberg.png

Credit Card Zukerberg

El script de arriba ya genera la imagen que puse enseguida y conseguimos una hermosa tarjeta para el señor Zukerberg (que seguro no le faltan, pero fue el nombre que me vino a la mente) el problema es que sigue siendo poco intuitivo (tal vez los señores Gates, Wozniak, y Musk también quieren su tarjeta) y como la idea era simplificarlo para posteriormente automatizarlo lo modifiqué de la siguiente forma:

#!/bin/bash

id="$1"
img="$2"
string="$3"
font="$4"
size="$5"
color="$6"
align="$7"
posx="$8"
posy="$9"

ext=`echo "$img" | cut -d'.' -f2`

convert "$img" \
	-gravity $align \
	-font "$font" \
	-pointsize "$size" \
	-fill "#$color" \
	-draw "text $posx,$posy '$string'" \
	$id"."$ext

El script de arriba lo único que hace realmente es permitir pasar los parámetros por variables para ejecutar un comando más “limpio” y preparar la automatización. Las variables son bastante fáciles de deducir, pero igual las explico por si hubiera alguna duda.

  • $id

    Esta variable es la que pone el nombre del archivo final, ya que no queremos dañar el archivo fuente.

    En este punto se podría usar el texto que queremos en la imagen, pero si pensamos en automatizar las cosas y generar después 100 archivos no es buena idea, porque el nombre podría contener caracteres extraños con los que no se podría generar la imagen final.

    Consideré poner la primer palabra del string, pero en caso de usar nombres y tener en la lista a “Michael Jackson” y “Michael Jordan” cuando pasara por el segundo en la lista este último sobrescribiría al primero y tendíamos la información incompleta.

    Lo más óptimo que se me ocurrió fue utilizar un ID único cada que se ejecute el comando. Especialmente si se va a usar en proceso automático. En resumen "1, 2, 3, 4, 5..."

    En caso de usar el script una sola vez, esta variable unicamente solicita el nombre del archivo final.

  • $img

    Esta variable “espera” el nombre del archivo (p./ej: imagen.png) del cuál se extrae la extensión del archivo final en la línea 13.

  • $string

    Aquí se pone el texto que se quiera poner en la imagen.

  • $font

    La fuente con la que se quiera trabajar.

  • $size

    Tamaño de fuente.

  • $color

    El color del texto (en notación hexadecimal)

  • $align

    En esta variable se pone la “referencia” de la cuál se quiere partir para posicionar el texto sobre la imagen. Por ejemplo si se utiliza North y en $posx y $posy se pone 0 el texto quedaría centrado en la parte superior, si se pone South saldría centrado en la parte inferior, con Center en medio de la imagen, etc. Se pueden ver todas las referencias ejecutando: $convert -list gravity

  • $posx y $posy

    Con estas dos variables modificamos la posición a partir de la referencia que estemos utilizando en la variable $align

El script yo lo llamé txTo y lo guardé en el directorio /usr/bin para poder ejecutarlo desde cualquier sitio y se puede generar la misma imagen de la tarjeta de Zukerberg con el siguiente comando:

txTo CreditCart_Zukerberg CreditCard.png "Mark Zuckerberg" Ubuntu 45 FFFFFF Center 55 -50

Podría parecer que tiene más variables de las que se necesitan para un proceso tan simple, pero como la idea es posteriormente automatizar la tarea de trabajar con N numero de archivos y al mismo tiempo no perder flexibilidad decidí hacerlo así. Lo siguiente es hacer otro script que mande ejecutar la línea de arriba las veces que sean necesarias para los archivos que se requieran, pero eso ya está en el siguiente post. Espero que les sea de utilidad y nos leemos pronto.

 
comments powered by Disqus