dimanche 26 janvier 2020
Pense-bête pour l'utilisation de exiv2, Image magick et d'autres manipulations de photos
Si on veut afficher une image en grandeur réelle à partir de la ligne de commande:
$ display img095.jpg
Notes : Si le fichier image n'est pas dans le répertoire courant, indiquer le chemin. Pour plus d'informations voir le man de display.
$ exiv2 img.jpg
Nom du fichier : img.jpg
Taille du fichier: 1752151 Octets
Type MIME : image/jpeg
Taille de l'image: 1944 x 2592
Marque de l'appareil: WIKO
Modèle de l'appareil: Sunny3
Horodatage de l'image: 2020:01:24 16:31:18
Numéro de l'image:
Temps d'exposition: 1/491 s
Ouverture : F2.2
Correction d'exposition:
Flash : Pas de flash
Biais flash :
Distance focale : 2.3 mm
Distance du sujet:
Sensibilité ISO : 50
Mode d'exposition:
Mode de mesure :
Mode macro :
Qualité de l'image:
Résolution Exif : 1944 x 2592
Balance des blancs: Automatique
Miniature : image/jpeg, 8628 Octets
Droit d'auteur : Copyright,Spreadtrum,2011
Commentaire Exif: Test un commentaire exiv2
Si on ne veut que DateTimeOriginal on peut utiliser l'option -g (grep)
$ exiv2 -g DateTimeOriginal img.jpg
Exif.Photo.DateTimeOriginal Ascii 20 2020:01:24 16:31:18
Pour plus d'options voir le man de exiv2se dans l'article Album photos. Il permet d'extraire d'une photo l'une des métadonnées : le commentaire, la date de prise de la photo ou l'heure. C'est parce que exiv2 ou image magick ne me donnaient pas ces données sous une forme simple.
g++ getexif.cc -o getexif -lexiv2
source: https://www.exiv2.org/doc/exifvalue_8cpp-example.html
Usage : getexif d|t|c file
Pour obtenir la date de prise d'une photo (Exif DateTimeOriginal) :
$ DT=identify -format %[Exif:DateTimeOriginal] img095.jpg
$ echo $DT
Note : Pour obtenir les données exif possibles :
$ identify -format '%[EXIF:*]' img095.jpg
exif:ApertureValue=11/5
exif:Artist=Artist-freed
exif:BrightnessValue=0/0
exif:ColorSpace=1
exif:ComponentsConfiguration=1, 2, 3, 0
exif:Contrast=0
exif:Copyright=Copyright,Spreadtrum,2011
exif:DateTime=2020:01:24 16:20:30
exif:DateTimeDigitized=2020:01:24 16:20:30
exif:DateTimeOriginal=2020:01:24 16:20:30
...
source : stackoverflow
$ exiv2 -r'%Y:%m:%d_%H:%m:%S' rename img.jpg
$ ls
2020:01:24_16:01:18.jpg
On suppose qu'on a un certain nombre de fichiers de photos, par exemple :
$ ls Camera
IMG_20191108_203655.JPG IMG_20200116_215146.JPG IMG_20200124_161610.JPG
IMG_20200116_215133.JPG IMG_20200124_161605.JPG IMG_20200124_161615.JPG
On suppose que les noms correspondent aux dates de prise des photos, et on veut les renommer dans cet ordre 1.jpg 2.jpg ... 6.jpg
.
$ ls *.JPG | cat -n | while read n f; do cp "$f" "$n.jpg"; done
$ ls
1.jpg 4.jpg IMG_20191108_203655.JPG IMG_20200124_161605.JPG
2.jpg 5.jpg IMG_20200116_215133.JPG IMG_20200124_161610.JPG
3.jpg 6.jpg IMG_20200116_215146.JPG IMG_20200124_161615.JPG
Source: stackoverflow. Aller à la deuxième réponse.
Admettons qu'on ait des doutes sur la fiablilté des noms d'origine. Par exemple on n'est pas sûr que l'appareil photo était mis à l'heure. C'est là qu'intervient Image Magick. Nous allons renommer d'abord ces fichiers avec la date de prise de la photo. (Cf. paragraphe précédent.)
On fait alors :
$ for f in *.JPG;
> do cp "$f" "identify -format %[Exif:DateTimeOriginal] $f".jpg;
> done
$ ls
'2019:11:08 20:36:56.jpg' '2020:01:24 16:16:10.jpg' IMG_20200116_215146.JPG
'2020:01:16 21:51:34.jpg' '2020:01:24 16:16:15.jpg' IMG_20200124_161605.JPG
'2020:01:16 21:51:47.jpg' IMG_20191108_203655.JPG IMG_20200124_161610.JPG
'2020:01:24 16:16:06.jpg' IMG_20200116_215133.JPG IMG_20200124_161615.JPG
Puis on procède comme ci-dessus en remplaçant cp
par mv
:
$ ls *.jpg | cat -n | while read n f; do mv "$f" $n.jpg; done
$ ls
1.jpg 4.jpg IMG_20191108_203655.JPG IMG_20200124_161605.JPG
2.jpg 5.jpg IMG_20200116_215133.JPG IMG_20200124_161610.JPG
3.jpg 6.jpg IMG_20200116_215146.JPG IMG_20200124_161615.JPG
Remarque : Il est impératif ici de protéger la variable $f
(après la commande mv
) par des guillemets, car elle contient un espace. Idem pour l'utilisation de identify
ci-dessus.
Connecter le mobile par un cable usb.
D'abord on fait reconnaître le mobile par adb
:
$ adb devices
List of devices attached
JADF1930008446 device
Ensuite, on exploite le shell
et sa complétion par Tab pour retrouver où sont stockées les photos. Je ne me le rappelle pas toujours, sauf que le chemin commence par storage
$ adb shell # pour trouver le chemin où il stocke les photos
MOBILE: $ ls storage/sdcard0/DCIM/
Camera
MOBILE:/ $ exit
Et enfin on peut les rapatrier.
$ adb pull storage/sdcard0/DCIM/Camera/
Voilà j'ai six photos, avec des noms à rallonge.
Je veux les renommer avec la date et l'heure de prise des photos.
$ for f in *.jpg;
> do cp "$f" "identify -format %[Exif:DateTimeOriginal] $f".img;
> done
$ ls
'2019:11:08 20:36:56.img' '2020:01:24 16:16:10.img' IMG_20200116_215146.jpg
'2020:01:16 21:51:34.img' '2020:01:24 16:16:15.img' IMG_20200124_161605.jpg
'2020:01:16 21:51:47.img' IMG_20191108_203655.jpg IMG_20200124_161610.jpg
'2020:01:24 16:16:06.img' IMG_20200116_215133.jpg IMG_20200124_161615.jpg
Maintenant on peut les renommer avec :
ls *.img | cat -n | while read n f; do mv "$f" "$n.img"; done
ou si on veut commencer à 13
ls *.img | cat -n | while read n f; do mv "$f" "$(($n + 13))".img; done
Notes :
J'ai pris l'extension .img pour distinguer les nouveaux fichiers des originaux.
Le passage par Exif n'est utile que si les noms des fichiers d'origine ne sont pas triés par date de façon certaine.
Voici un exemple de programme getexif que j'utilise dans l'article Album photos. Il permet d'extraire d'une photo l'une des métadonnées : le commentaire, la date de prise de la photo ou l'heure. C'est parce que exiv2 ou image magick ne me donnaient pas ces données sous une forme simple.
/*
g++ getexif.cc -o getexif -lexiv2
source: https://www.exiv2.org/doc/exifvalue_8cpp-example.html
Usage : getexif d|t|c file
Output on standard outpout date, time, or comment
getexif d file : outpout date (first part of DateTimeOriginal)
getexif t file : output time (second part)
getexif c file : output jpg comment
*/
#include <exiv2/exiv2.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
#include <string>
using namespace std;
string exifvalue(const char* key, const char* file)
{
string output("");
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
assert(image.get() != 0);
image->readMetadata();
Exiv2::ExifData &exifData = image->exifData();
if ( exifData.empty()) {
std::cerr << "no metadata found in file " << file << std::endl;
exit(2);
}
try {
output = exifData[key].toString();
} catch (Exiv2::AnyError& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'" << std::endl;
exit(3);
} catch ( ... ) {
std::cerr << "Caught a cold!" << std::endl;
exit(4);
}
return output;
}
int main(int argc, char* const argv[])
{
string output("");
bool c = argc == 3 && strcmp(argv[1], "c") == 0;
bool d = argc == 3 && strcmp(argv[1], "d") == 0;
bool t = argc == 3 && strcmp(argv[1], "t") == 0;
const char* file = argv[2];
if(!c && !d && !t ) {
std::cerr << "Usage: " << argv[0] << " c|d|t file\n";
std::cerr << " c: exif comment and not JPEG comment\n";
std::cerr << " d: date, first part of DateTimeOriginal\n";
std::cerr << " t: time, second part\n";
std::cout << endl;
return 1;
} else if(c) {
string comment = exifvalue("Exif.Photo.UserComment", file);
cout << comment.substr(comment.find(' ') + 1) << endl;
return 0;
}
else if( d || t) {
string datetime = exifvalue("Exif.Photo.DateTimeOriginal", file);
if(d) cout << datetime.substr(0, datetime.find(' ')) << endl;
if(t) cout << datetime.substr(datetime.find(' ') + 1) << endl;
return 0;
}
return 1;
}
Source : https://www.exiv2.org/doc/exifvalue_8cpp-example.html