Adicionar registro de data e hora à imagem na linha de comando do Linux

9

Eu tenho uma pasta cheia de imagens. Estou tentando adicionar um carimbo de data / hora à própria imagem, para cada imagem, com base na data em que o arquivo foi criado. Isso é possível? Eu li este post aqui , mas ele usa dados exif. Minhas imagens não possuem dados exif.

Posso adicionar diretamente um carimbo de data / hora usando a data criada? Ou tenho que usar dados exif? Se eu tiver que usar dados exif, como eu os escreveria usando a data criada?

Estou usando o Ubuntu Server sem GUI, então precisarei de uma solução de linha de comando. Alguém pode ajudar? Obrigado!

Andrew
fonte

Respostas:

18

Se você quiser escrever a data da criação do arquivo de imagem na própria imagem (se não é isso que você deseja, edite sua pergunta), você pode usá-lo imagemagick.

  1. Instale o ImageMagick se ainda não estiver instalado:

    sudo apt-get install imagemagick
    
  2. Execute um loop bash que obtenha a data de criação de cada foto e use a convertpartir do imagemagickconjunto para editar a imagem:

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

    Para cada imagem nomeada foo.jpg, isso criará uma cópia chamada time_foo.jpgcom o carimbo de hora no canto inferior direito. Você pode fazer isso de maneira mais elegante, para vários tipos de arquivos e nomes de saída agradáveis, mas a sintaxe é um pouco mais complexa:

OK, essa era a versão simples. Escrevi um script que pode lidar com situações mais complexas, arquivos em subdiretórios, nomes de arquivos estranhos etc. Até onde eu sei, apenas imagens .png e .tif podem conter dados EXIF, portanto, não há sentido em executá-lo em outros formatos. . No entanto, como uma possível solução alternativa, você pode usar a data de criação do arquivo em vez dos dados do EIF. Provavelmente, isso não é o mesmo que a data em que a imagem foi tirada; portanto, o script abaixo tem a seção relevante comentada. Remova os comentários se você quiser processar dessa maneira.

Salve este script como add_watermark.she execute-o no diretório que contém seus arquivos:

bash /path/to/add_watermark.sh

Ele usa os exiv2quais você pode precisar instalar ( sudo apt-get install exiv2). O script:

#!/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
fonte
É exatamente isso que estou procurando! No entanto, estou obtendo a seguinte saída: 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.Além disso, ainda não decidi se ainda quero usar subdiretórios; você poderia mostrar como usar findtambém? Obrigado!
Andrew
@ Andrew, existem dois problemas possíveis, um é que eu não havia citado as variáveis ​​corretamente e, portanto, espaços nos nomes dos arquivos causariam problemas. Experimente o script na resposta atualizada. Se ainda assim falhar, suas imagens provavelmente não contêm os dados EXIF ​​necessários, incluí uma solução alternativa (ruim) para isso.
terdon
Já faz um tempo, mas você pode explicar o que "$path"/"${name/%.*/.time.$ext}"faz? Em particular, a /%.*/parte. Além disso, se eu quisesse colocar a parte "time" na frente, por exemplo, time.a.jpg em vez de a.time.jpg, como eu poderia fazer isso?
Andrew
@ Andrew, isso é apenas substituição de string, veja aqui . Ele substituirá tudo após o último .caractere por .time.$ext( $exté a extensão capturada anteriormente). Para entrar time.a.jpg, mude para ${name/#/time.}.
terdon
-pointsize 48 ou -pointsize 72 é certamente mais legível. :-)
Corey S.
0

Verifique http://jambula.sourceforge.net/ para inserir em lote a data / hora / comentário da gravação em uma imagem jpeg em diferentes formatos e idiomas. Uma característica especial é que o carimbo de data é sem perdas. É suportado no Linux e Mac também.

Suresh Mahalingam
fonte
0

Basta plotar os arquivos no diretório vazio e canalizar o AWK para o shell. Talvez um pouco velho, mas muito menos fantasia, muito menos caracteres para digitar também, por exemplo:

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