Rotation JPEG vraiment sans perte
Par Olivier Mengué le dimanche 21 octobre 2007, 23:38 - Code - Lien permanent
Avez-vous déjà examiné en détail les méta-données EXIF d'une photo numérique après une rotation soit-disant « sans perte » ? Si vous l'avez fait avec un outil tel que exiftool
, vous avez sûrement du constaté la catastrophe. Certains outils de rotation perdent toutes les données EXIF, d'autres une partie des paramètres de prise de vue ou le champ Software... Et aucun ne fait la rotation des imagettes de prévisualisation, ni ne préserve la date de création originelle du fichier. J'ai essayé sous Ubuntu 7.10, F-Spot
, jpegtran
(paquet libjpeg-progs
) et exiftran
. Chacun a ses défauts.
Je vous propose donc ici la solution personnalisée que j'ai développée ce week-end en utilisant jpegtran
et exiftool
. Ce n'est pas forcément une solution universelle, mais elle est satisfaisante pour les photos issues de mon APN (sous réserve que mon outil d'observation
Une image JPEG issue de mon appareil photo numérique (Nikon Coolpix E995) contient les données suivantes :
- les données graphique de l'image principale (2048x1536 en compression FINE) ;
- les métadonnées EXIF ;
- l'image de prévisualisation (PreviewImage) au format 320x240, pour l'affichage sur l'écran de l'APN : c'est un fichier JPEG complet embarqué ;
- l'image de prévisualisation (ThumbnailImage) au format 160x120, pour l'affichage dans les logiviles de classement, dans Nautilus ou l'Explorateur Windows.
jpegtran
sait faire la rotation de l'image principale sans perte (c'est à dire, pas de décompression/compression) en préservant les données EXIF, mais il copie les imagettes telles quelles, sans les tourner. exiftran
tourne bien l'image principale et la ThumbnailImage
mais il corrompt (d'après exiftool) les MarkerNotes et la PreviewImage.
exiftool
, un outil très complet de modification des données EXIF, dispose d'une fonctionnalité permettant d'extraire les imagettes, et plus tard de les remplacer. Cette fonction est également utile pour vérifier que la rotation de l'imagette a bien été effectuée.
Exemple :
$ exiftool -b -ThumbnailImage DSCN4821.JPG | exiftool - ExifTool Version Number : 6.90 File Type : JPEG MIME Type : image/jpeg Image Width : 160 Image Height : 120 Image Size : 160x120 $ exiftool -b -PreviewImage DSCN4821.JPG | exiftool - ExifTool Version Number : 6.90 File Type : JPEG MIME Type : image/jpeg Image Width : 320 Image Height : 240 Image Size : 320x240
J'ai donc combiné jpegtran
et exiftool
en appliquant jpegtran
à l'image principale puis aux imagettes. Le fichier est converti en place (l'original est écrasé) et la date de création du fichier est définie comme la date de prise de vue extraite des informations EXIF. J'en ai aussi profité pour appliquer l'option -optimize
de jpegtran
pour gagner au passage quelques kilo-octets.
Voici le code :
#!/bin/bash # http://o.mengue.free.fr/ function _jpegrot { typeset angle="$1" typeset f="$2" [[ "x$2" = *.[jJ][pP]*[gG] ]] || return 0 typeset b=$(expr "x$f" : 'x\(.*\)\....$') typeset new="$b.tmp.JPG" typeset prv="$b.prv.JPG" typeset thb="$b.thb.JPG" exiftool -b -PreviewImage -w ".prv.JPG" -execute -b -ThumbnailImage -w ".thb.JPG" -common_args "$f" jpegtran -rotate "$angle" -optimize -perfect -copy all "$f" > "$new" mv -f -- "$new" "$f" jpegtran -rotate "$angle" -optimize -perfect -copy all "$prv" | exiftool -overwrite_original "$f" '-PreviewImage<=-' > /dev/null jpegtran -rotate "$angle" -optimize -perfect -copy all "$thb" | exiftool -overwrite_original "$f" '-ThumbnailImage<=-' '-DateTimeOriginal>FileModifyDate' > /dev/null rm -f -- "$prv" "$thb" } typeset angle="$1" shift for f in "$@" do _jpegrot "$angle" "$f" done
Exemple d'utilisation :
$ jpegrot 90 DSCN4821.JPG