25 de fev de 2014

Colocar data automaticamente em arquivos de fotos (Linux)

Fiz um programa em bash para colocar aquela estampa de data (timestamp) em arquivos com base na última modificação do arquivo. Muitas vezes acontece de você ter a foto em si, mas não ter programado a câmera para gerar automaticamente esse carimbo na foto. Ou, como foi meu caso, achar que não tinha importância a data e, depois, começar a querer colocar, além de que os aplicativos padrão de Câmera de celular não terem essa funcionalidade (pelo menos eu nunca tive contato com um que tivesse, somente aplicativos instalados a mais, como o Camera360).


Para quem quiser pegar o programa, pode fazer o download, mas, aqui, vou explicar o que fiz, deixando o código   e que referências de consulta usei. É bom para aprender um pouquinho de Bash e alguns comandos de Linux e, para quem quiser, modificar o programa para outros propósitos (Filosofia do Código Aberto ;) ).

O primeiro passo do programa é testar a entrada do programa. Eu quero que o programa receba apenas uma entrada, portanto, se a chamada ao programa for diferente de 1 argumento, devo dar uma mensagem de erro e sair.

Para obter a data da última modificação do arquivo, usamos o comando stat. Consultando o manual, vemos que a opção -c corresponde a: "use the specified FORMAT instead of the default; output a newline after each use of FORMAT". Ou seja, se usarmos o stat sozinho, ele dará uma série de informações sobre o arquivo, mas só nos interessa a data da modificação, então usamos a opção -c e pedimos o formato que queremos, que é obtido usando %y.

    %y     Time of last modification, human-readable
Trecho do manual sobre a opção %y

Usando o comando stat -c %y [referência], obteremos algo do tipo:

2014-02-25 15:37:46.000000000 -0300

Mas só nos interessa a data, que vem no formato yyyy-mm-dd. Então, usando uma manipulação de string, localizamos o espaço e pegamos o conteúdo até onde ele ocorrer. Usamos o operador %% seguido do caracter desejado, no caso, o espaço e um asterisco ($string=${string%%-*} - substituí o espaço por um traço para ficar mais palpável). Note que o comando verificará a primeira ocorrência do marcador, mesmo que a string pode tenha o mesmo marcador depois. Entretanto, se usarmos o operador % (simples), ele localizará a última ocorrência, que é o que queremos nesse instante: separar a substring que vem antes do espaço. 

O operador ##, por outro lado obtém o que estiver depois do marcador, sendo que a ordem entre o marcador e o asterisco se inverte ($string=${string##*-}). Servirá para obter a extensão do arquivo, como será visto ao longo deste texto. Não quis me alongar muito nessa explicação para não perder o objetivo principal do post, mas tem exemplos aqui, aqui e o meu exemplo (link no GitHub).

Voltando à data, vamos usar o operador "%% *" para obter o pedaço "2014-02-25" da saída obtida com o comando stat. Segue o trecho do código responsável:

  1. #obtem data de ultima modificacao do arquivo
  2. data=$(stat -c %$1)
  3. data=${data%% *}

No programa, eu gerei um nome de saída para o arquivo com a data com base no nome de entrada, adicionando a ele a data e hora em que foi gerado. Para isso, temos que pegar o nome do arquivo (que é dado pelo usuário ao rodar o programa, ou seja, é o argumento 1 - $1 - da chamada via linha de comando, por exemplo ./datarFoto lago.jpg), obter todo o nome até o último ponto (usando o tratamento de substrings que eu expliquei acima) e também guardar a extensão, que usará o operador ## para guardar a substring depois do marcador. Para concatenar duas strings, basta colocá-las lado a lado depois do sinal de =, como na última linha do trecho abaixo:

  1. #gerar nome do arquivo de saida
  2. nomeSaida=$1
  3. extensao=${nomeSaida##*.}
  4. nomeSaida=${nomeSaida%.*}
  5. nomeSaida=$nomeSaida$(date +"_%y%m%d_%H%M")

Faltou explicar o funcionamento do date [referência]. O sinal de + indica o formato que eu quero que a data seja exibido. O comando date sozinho dá a data atual, usando os operadores +"_%y%m%d_%H%M", a data será exibida no tipo _140131_1251, onde 14 é o ano (2014), 01, o mês e 31 o dia. Os sublinhados foram escolha minha, você podia botar outros caracteres para separar, mas , como estamos lidando com nome de arquivo, não seria legal colocar certos caracteres como barra e dois pontos.

Para mudar o formato da data (a ser carimbada na foto e não no nome do arquivo de saída) para o nosso formato tradicional (dd/mm/yyyy), também usamos o comando date. Mas, dessa vez, damos como entrada a data obtida pelo stat. Para isto, usamos a opção --date= que indica ao date que é para usar determinada data e não a do dia de hoje.

  1. #converte o formato da data de yyyy-mm-dd para dd/mm/yyyy
  2. texto=$(date --date=$data +"%d/%m/%y")

Por fim, vamos carimbar a foto. Usamos o comando convert. Como não consegui rodar o comando de uma vez, coloquei o comando numa string e mandei a string ser rodada, através do eval. As opções do convert que merecem destaque são a gravity (mais informações aqui), que serve para mudar a origem das coordenadas. A opção draw diz em que posições vertical e horizontal vai ser colocado o texto. Usando a opção gravity Southeast, essas posições são dadas com relação à ponta inferior direita, sendo assim, independente do tamanho, o carimbo sempre vai ser dado neste canto.

  1. #usar o formato para usar o comando convert
  2. executar="convert -pointsize 20 -fill yellow -gravity Southeast -draw 'text 20,20 \"$texto\"' $1 $nomeSaida.$extensao"
  3. eval $executar

Referências:
http://www.instructables.com/id/Add-text-to-images-with-Linux-convert-command/2/?lang=pt
http://www.linuxquestions.org/questions/programming-9/get-file-modification-date-time-in-bash-script-163731/
http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/
http://www.win.tue.nl/~aeb/linux/misc/convert/convert-draw-text.html
http://tldp.org/LDP/abs/html/string-manipulation.html

Nenhum comentário:

Quem sou eu

Raphael Fernandes
Carioca, Brasileiro, Estudante de Robótica
Hiperativo, Imperativo
Gosto de tecnologia, de transporte, de Rock, de reclamar e de propagandas criativas (e outras coisas que posso ter falado em um post ou não)
Musicalmente falando, sou assim.

Related Posts Plugin for WordPress, Blogger...

Veja também...