Agregar marca de tiempo a la imagen desde la línea de comandos de Linux

9

Tengo una carpeta llena de imágenes. Estoy tratando de agregar una marca de tiempo en la imagen en sí, para cada imagen, en función de la fecha en que se creó el archivo. es posible? He leído esta publicación aquí , pero usa datos exif. Mis imágenes no tienen datos exif.

¿Puedo agregar directamente una marca de tiempo usando la fecha de creación? ¿O tengo que usar datos exif? Si tengo que usar datos exif, ¿cómo los escribiría usando la fecha de creación?

Estoy usando Ubuntu Server sin GUI, por lo que necesitaré una solución de línea de comandos. ¿Alguien puede ayudar? ¡Gracias!

Andrés
fuente

Respuestas:

18

Si desea escribir la fecha de creación del archivo de imagen en la imagen misma (si eso no es lo que desea, edite su pregunta), puede usar imagemagick.

  1. Instale ImageMagick si aún no está instalado:

    sudo apt-get install imagemagick
    
  2. Ejecute un bucle bash que obtendrá la fecha de creación de cada foto y úsela convertdesde la imagemagicksuite para editar la imagen:

    for img in *jpg; do convert "$img" -gravity SouthEast -pointsize 22 \
       -fill white -annotate +30+30  %[exif:DateTimeOriginal] "time_""$img"; 
    done
    

    Para cada imagen nombrada foo.jpg, esto creará una copia llamada time_foo.jpgcon la marca de tiempo en la parte inferior derecha. Puede hacerlo de manera más elegante, para múltiples tipos de archivos y nombres de salida agradables, pero la sintaxis es un poco más compleja:

OK, esa era la versión simple. Escribí un script que puede tratar situaciones más complejas, archivos en subdirectorios, nombres de archivos extraños, etc. Hasta donde sé, solo las imágenes .png y .tif pueden contener datos EXIF, por lo que no tiene sentido ejecutar esto en otros formatos . Sin embargo, como una posible solución alternativa, puede usar la fecha de creación del archivo en lugar de los datos EIF. Es muy probable que esto no sea lo mismo que la fecha en que se tomó la imagen, por lo que el script a continuación tiene la sección relevante comentada. Elimine los comentarios si desea que se procesen de esta manera.

Guarde este script como add_watermark.shy ejecútelo en el directorio que contiene sus archivos:

bash /path/to/add_watermark.sh

Utiliza exiv2lo que puede necesitar instalar ( sudo apt-get install exiv2). La secuencia de comandos:

#!/usr/bin/env bash

## This command will find all image files, if you are using other
## extensions, you can add them: -o "*.foo"
find . -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.tif" -o \
 -iname "*.tiff" -o -iname "*.png" | 

## Go through the results, saving each as $img
while IFS= read -r img; do
    ## Find will return full paths, so an image in the current
    ## directory will be ./foo.jpg and the first dot screws up 
    ## bash's pattern matching. Use basename and dirname to extract
    ## the needed information.
    name=$(basename "$img")
    path=$(dirname "$img")
    ext="${name/#*./}"; 

    ## Check whether this file has exif data
    if exiv2 "$img" 2>&1 | grep timestamp >/dev/null 
    ## If it does, read it and add the water mark   
    then
    echo "Processing $img...";
    convert "$img" -gravity SouthEast  -pointsize 22 -fill white \
             -annotate +30+30  %[exif:DateTimeOriginal] \
             "$path"/"${name/%.*/.time.$ext}";
    ## If the image has no exif data, use the creation date of the
    ## file. CAREFUL: this is the date on which this particular file
    ## was created and it will often not be the same as the date the 
    ## photo was taken. This is probably not the desired behaviour so
    ## I have commented it out. To activate, just remove the # from
    ## the beginning of each line.

    # else
    #   date=$(stat "$img" | grep Modify | cut -d ' ' -f 2,3 | cut -d ':' -f1,2)
    #   convert "$img" -gravity SouthEast  -pointsize 22 -fill white \
    #          -annotate +30+30  "$date" \
    #          "$path"/"${name/%.*/.time.$ext}";
    fi 
done
terdon
fuente
¡Esto es exactamente lo que estoy buscando! Sin embargo, obtengo el siguiente resultado: convert.im6: unknown image property "%[exif:DateTimeOriginal]" @ warning/property.c/InterpretImageProperties/3245. convert.im6: unable to open image `{img/%.*/.time.jpg}': No such file or directory @ error/blob.c/OpenBlob/2638.Además, aún no he decidido si quiero usar subdirectorios; ¿podría mostrar cómo usar findtambién? ¡Gracias!
Andrew
@ Andrew hay dos posibles problemas, uno es que no había citado las variables correctamente y que los espacios en los nombres de los archivos podrían causar problemas. Pruebe el script en la respuesta actualizada. Si todavía falla, sus imágenes probablemente no contengan los datos EXIF ​​necesarios, he incluido una solución (mala) para eso.
terdon
Ha pasado un tiempo, pero ¿puedes explicar qué "$path"/"${name/%.*/.time.$ext}"hace? En particular, la /%.*/parte. Además, si quisiera poner la parte "tiempo" al frente, por ejemplo, time.a.jpg en lugar de a.time.jpg, ¿cómo podría hacerlo?
Andrew
@ Andrew eso es solo reemplazo de cadena, mira aquí . Reemplazará todo después del último .carácter con .time.$ext( $extes la extensión capturada anteriormente). Para hacerlo time.a.jpg, cambia eso a ${name/#/time.}.
Terdon
-pointsize 48 o -pointsize 72 es ciertamente más legible. :-)
Corey S.
0

Visite http://jambula.sourceforge.net/ para insertar por lotes la fecha / hora / comentario del disparo en una imagen jpeg en diferentes formatos e idiomas. Una característica especial es que el sello de fecha no tiene pérdidas. También es compatible con Linux y Mac.

Suresh Mahalingam
fuente
0

Simplemente trace los archivos en un directorio vacío y canalice AWK al shell. Tal vez un poco viejo pero mucho menos elegante, muchos menos caracteres para escribir también, por ejemplo:

ls | awk '{print "convert "$0" -gravity SouthEast -pointsize 22 -fill white -annotate +30+30 %[exif:DateTimeOriginal] dated"$0}' | sh
Pablo
fuente