Risolto - Acquisire dati exif da 'C' o "C++"

di il
8 risposte

Risolto - Acquisire dati exif da 'C' o "C++"

Salve
da buon programmatore "giocattolo" finora ho sempre giocherellato con Arduino, ma ora ho un problemino di ordine più generale, e quindi vi chiedo una indicazione
Ho una grossa quantità di fotografie digitali, e vorrei potermele ordinare su disco, il problema è che hanno tutte le stesso nome
una cosa tipo "dcim0001.jpg" "dcim0002.jpg" "dcim0003.jpg" "dcim0004.jpg" ...........
e nella cartella dopo ancora......e nella cartella dopo ancora......e nella cartella dopo ancora......
insomma è escluso metterli tutti assieme in una sola cartella (ops directory, ho Linux)
pensavo quindi di cogliere la palla al balzo e leggere data/ora di creazione dai dati EXIF della foto stessa, per usarli per rinominare i file in automatico e concentrarli in una unica directory "cicciona" e ingestibile (questo lo ho già preventivato)
anche le collisioni tra nomi le ho già preventivate, ok
quindi ecco la mia domanda:
conoscete mica qualche "tecnica" per leggere da un file .jpg i dati exif ed estrarne data ed ora?
preferibilmente in 'C', ma anche "C++" è accettato

8 Risposte

  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    https://libexif.github.io/
    Dal sito:

    The libexif C EXIF library
    • is a library written in pure portable C.
    • reads and writes EXIF metainformation from and to image files.
    • is licensed under the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 (LGPL).
    • runs under POSIX systems (e.g. GNU/Linux, xBSD, MacOS X, Windows, etc.).
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    Grazie, molto gentile
    ci guardo adesso
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    Garzie per la dritta, è esattamente quello che speravo
    ma....
    adesso farò una ben meschina figura, mi spiace ma devo bere l'amaro calice
    non so installarla.....
    datemi un indizio e non sparatemi troppo addosso, grazie
    sono ai primi passi con 'C' fuori dal "giocattolo"

    una descrizione dell'ambiente:
    IDE Geany 1.3.2
    OS ubuntu 18.04 LTS X64 Mate
    altre esperienze in 'C' -> nulla (o molto poco)
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    Se usi ubuntu, dovrebbe essere disponibile tra i pacchetti installabili (tramite apt o tool equivalente). Devi installare due librerie:
    • libexif12
    • libexif-dev
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    Purtroppo erano già installate
    messaggio ricevuto da sudo apt install:
    libexif12 è già alla versione più recente (0.6.21-4).
    libexif-dev è già alla versione più recente (0.6.21-4).

    in effetti l'errore che ho è:
    
    exiffile.c:(.text+0x92): riferimento non definito a "exif_content_get_entry"
    
    e poi altri per altre funzioni successive, ma tutte la stessa minestra
    quindi non è che non trova i file.h
    la pura compilazione è OK
    credo che sia un problema di linking, non trova il "compilato" della libreria, che in effetti non trovo nemmeno io con una ricerca
    e io qui ho finito le mie conoscenze
    anche il (puerile) tentativo di includere i file puntoc al posto dei puntoh mi ha dato buca, non trova un file config.h che non esiste, non trovo da nessuna parte

    vabbe' dai, adesso pranzo domenicale, grazie per il tuo interessamento

    PS ho Geany in italiano e non so rimetterlo in inglese
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    Prova a compilare con il flag -lexif (il linker interno di gcc non cerca la libreria statica libexif.a se non glielo dici):
    gcc exiffile.c -o exiffile -lexif
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    Buona, grazie
    naturalmente funziona
    ho fatto tanto la figura dello sprovveduto?
  • Re: Risolto - Acquisire dati exif da 'C' o "C++"

    OK, grazie a Andrea Qauglia sono riuscito a fare quello che volevo
    pubblico il programma, anche se essendo molto personalizzato per le mie esigenze, anche usarlo per ispirazione non è scritto molto bene, in proporzione alla mia esperienza
    comunque pubblico volentieri, si tratta fondamentalmente di pezzi raccattati in giro
    
    
    #include <stdio.h>
    #include <string.h>
    #include <libexif/exif-data.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    #define EXT "JPG"
    #define nome entry->d_name
    #define LEXT ".jpg"
    #define INGRESSO "/home/max/foto/input"
    #define USCITA "/home/max/foto/out"
    
    
    int esistefile(char * filename)
    {
       struct stat sb;
    
       if(stat(filename, &sb) == -1)
       {
          return 0;
       }
    
       return 1;
    }
    
    
    
    /* Remove spaces on the right of the string */
    static void trim_spaces(char *buf)
    {
       char *s = buf - 1;
    
       for(; *buf; ++buf)
       {
          if(*buf != ' ')
             s = buf;
       }
    
       *++s = 0; /* nul terminate the string on the first of the final spaces */
    }
    
    
    
    int tratta(char * nomefile, char * destino)
    {
       ExifData *ed;
       // ExifEntry *entry;
       /* Load an ExifData object from an EXIF file */
       ed = exif_data_new_from_file(nomefile);
    
       if(!ed)
       {
          //   printf("File non leggibile o dati Exif assenti in: %s\n", nomefile);
          return 2;
       }
    
       // creo il nomefilefuturo
       char futuro[250] = {0};
       // leggo la data
       char dataora[250] = {0};
       trim_spaces(dataora);
       {
          ExifEntry *punta = exif_content_get_entry(ed->ifd[0], 306);
    
          if(punta)
          {
             // recupero il valore,
             exif_entry_get_value(punta, dataora, sizeof(dataora));
             trim_spaces(dataora);
          }
       }
    
       // ora delle due l'una
       // ho una data, oppure no
       if(!(*dataora))
       {
          //non ho una data
          //ripeto per un altro tag
          ExifEntry *punta = exif_content_get_entry(ed->ifd[2], 36867);
    
          if(punta)
          {
             // recupero il valore,
             exif_entry_get_value(punta, dataora, sizeof(dataora));
             trim_spaces(dataora);
          }
       }
    
       if(!(*dataora))
       {
          //non ho una data
          //ripeto per un altro tag
          ExifEntry  *punta = exif_content_get_entry(ed->ifd[2], 36868);
    
          if(punta)
          {
             // recupero il valore,
             exif_entry_get_value(punta, dataora, sizeof(dataora));
             trim_spaces(dataora);
          }
       }
    
       char marca[250] = {0};
       {
          ExifEntry *punta = exif_content_get_entry(ed->ifd[0], 271);
    
          if(punta)
          {
             // marca esiste
             exif_entry_get_value(punta, marca, sizeof(marca));
             trim_spaces(marca);
          }
       }
       char modello[250] = {0};
       {
          ExifEntry *punta = exif_content_get_entry(ed->ifd[0], 272);
    
          if(punta)
          {
             // modello esiste
             exif_entry_get_value(punta, modello, sizeof(modello));
             trim_spaces(modello);
          }
       }
       /* Free the EXIF data */
       exif_data_unref(ed);
    
       // tratto la data
       for(int i = 0; dataora[i]; i++)
       {
          if(dataora[i] == ':')
          {
             dataora[i] = '-';
          }
    
          if(dataora[i] == ' ')
          {
             dataora[i] = 'H';
          }
       }
    
       // tratto il modello
       for(int i = 0; modello[i]; i++)
       {
          if(modello[i] == ',')
          {
             modello[i] = 0;
             break;
          }
       }
    
       if(0)
       {
          // a questo punto se ho una data la elaboro, altrimenti ignoro
          if(!(*dataora))
          {
             printf("File privo di tag data");
             printf("\n");
          }
    
          else
          {
             printf("data e ora della foto: ");
             printf("%s\n", dataora);
          }
    
          if(!(*marca))
          {
             printf("File privo di tag marca");
             printf("\n");
          }
    
          else
          {
             printf("marca della fotocamera: ");
             printf("%s\n", marca);
          }
    
          if(!(*modello))
          {
             printf("File privo di tag modello");
             printf("\n");
          }
    
          else
          {
             printf("modello della fotocamera: ");
             printf("%s\n", modello);
          }
       }
    
       strcpy(futuro, destino);
       strcat(futuro, "/");
       strcat(futuro, dataora);
       strcat(futuro, "_");
       strcat(futuro, marca);
       strcat(futuro, "_");
       strcat(futuro, modello);
       strcat(futuro, "-a");
       strcat(futuro, LEXT);
       //   printf("%c\n", futuro[strlen(futuro) - 5]);
    
       for(int i = 0; i < 25; i++)
       {
          if(esistefile(futuro))
          {
             // errore, non posso rinominarlo, destinazione esistente
             futuro[strlen(futuro) - 5]++;
          }
    
          else
          {
             printf("vecchio nome del file: ");
             printf("%s\n", nomefile);
             printf("nuovo nome del file: ");
             printf("%s\n", futuro);
             // non esiste, lo posso rinominare
             rename(nomefile, futuro);
             break;
          }
       }
    
       return 0;
    }
    
    
    void list_dir(char * path, char * destino)
    {
       u_int8_t lenext = strlen(EXT);
       struct dirent *entry;
       DIR * dir = opendir(path);
    
       if(dir == NULL)
       {
          return;
       }
    
       while((entry = readdir(dir)) != NULL)
          if(nome [0] != '.')
          {
             {
                if(entry->d_type == DT_REG)
                {
                   if(!strcmp(&nome[strlen(nome) - lenext], EXT))
                   {
                      char vecchio[250] = {0};
                      strcpy(vecchio, path);
                      strcat(vecchio, "/");
                      strcat(vecchio, nome);
                      tratta(vecchio, destino);
                   }
                }
    
                if(entry->d_type == DT_DIR)
                {
                   char newpath[250] = {0};
                   strcpy(newpath, path);
                   strcat(newpath, "/");
                   strcat(newpath, nome);
                   list_dir(newpath, destino);
                }
             }
          }
    
       closedir(dir);
    }
    
    
    int main(int argc, char ** argv)
    {
       list_dir(INGRESSO, USCITA);
    }
    
    
    
    fondamentalmente scorro ricorsivamente le sotto cartelle di una cartella base
    se trovo file .jpg estraggo i tag exif che mi interessano e li uso per creare un nuovo file-name
    che uso per fare un rename() su una cartella di uscita.....
    per gli esperti sarà una banalità, ne convengo
    e potevo fare di meglio, ma ho soddisfatto le mie esigenze: in pochi secondi di runtime mi ha messo a posto 18000 file "dcim001.jpg"
    grazie
Devi accedere o registrarti per scrivere nel forum
8 risposte