Script shell et mmap
Ce TP commence par l'écriture d'un petit script shell manipulant des images jpeg à l'aide du programme
exif. Ensuite nous ferrons un exercice sur
mmap, le reste du TP vous permettant d'avancer sur le projet.
Script shell et entêtes d'images JPEG
Les photos actuellement prises par les appareils de photos numériques sont généralement au format JPEG. Ces fichiers images, en plus de l'information visuelle, contiennent un certain nombre d'informations telles que le modèle de l'appareil photo, la date et l'heure de la prise, l'orientation de l'appareil ... Ces informations sont mémorisées dans une partie spéciale du fichier JPEG: la section
exif (Exchangeable Image File Format). Les programmes
exif, exiftags, exifcom et
exiftran permettent d'extraire et de manipuler ces informations pour une image JPEG.
Télécharger l'archive
exif.tgz sur votre compte. Créer un répertoire
images puis décompresser l'archive dans ce répertoire (
cd images ; tar -zxf ../exif.tgz). Tester la commande
exif sur ces images.
Le programme
zenity permet à partir du shell d'intéragir avec l'utilisateur de façon graphique et conviviale. Tester les exemples suivants:
-
zenity --entry --text="Ancien commentaire: blablabla" --entry-text="blablabla"
-
zenity --file-selection --multiple --title="Choisissez des images"
- lisez la doc (
man zenity) pour en savoir plus :)
Extrait de la manpage du bash:
Substitution de commandes
La substitution de commandes permet de remplacer le nom d'une commande par son résultat. Il en existe deux
formes :
$(commande)
ou
`commande`
Bash effectue la substitution en exécutant la commande et en la remplaçant par sa sortie standard, dont les
derniers sauts de lignes sont supprimés. Les sauts de lignes internes ne sont pas supprimés mais peuvent
disparaître lors du découpage en mots. La substitution de commande $(cat fichier) peut être remplacée par
l'équivalent plus rapide $(< fichier).
Quand l'ancienne forme de substitution avec les backquotes ` est utilisée, le caractère antislash garde sa
signification littérale, sauf s'il est suivi de $, `, ou \. La première backquote non protégée par un anti-
slash termine la substitution de commande. Quand on utilise la forme $(commande), tous les caractères entre
parenthèses gardent leurs valeurs littérales. Aucun n'est traité spécialement.
Les substitutions de commandes peuvent être imbriquées. Avec l'ancienne forme, il faut protéger les back-
quotes internes avec un backslash.
Si la substitution apparaît entre guillemets, le découpage des mots, et l'expansion des noms de fichiers ne
sont pas effectués.
Votre objectif maintenant est d'écrire un script shell qui prend en argument une liste d'image et qui va successivement les afficher et proposer de changer le commentaire utilisateur de la section exif de l'image. Dans le cas où le script est appelé sans argument, vous lancerez un selecteur de fichier à l'aide de
zenity. Ensuite pour chaque image vous devez:
- afficher celle-ci avec
feh ou encore
display.
- ouvrir une boite de dialogue avec une zone texte contenant le commentaire de
exif (
commentaire=$(exifcom pic1.jpg)) de la photo et une zone d'édition permettant de modifier ce commentaire.
- si l'utilisateur a cliqué sur OK (valeur de retour
$? =
= 0) alors vous devez mettre à jour ce commentaire (si vous écrivez
new=$(zenity --entry) alors la variable
new contiendra le texte affiché par le programme).
Pour ceux qui vous très vite vous pouvez essayer de modifier votre script pour qu'il accomplisse d'autre chose comme proposer une rotation ou encore mettre à jour la miniature à l'aide de
exif -n ... (pour créer la miniature on utilisera
convert).
mmap
Le but de cet exercice est d'écrire un tout petit programme utilisant
mmap pour projeter un fichier en mémoire puis permettant à l'utilisateur de lire/modifier des données dans cette zone.
Commencer par ouvrir le fichier passer en argument (
argv[1]) au programme en utilisant la fonction
open comme suit:
fd=open(argv[1],O_RDWR) et n'oublier de tester que la valeur de retour (un entier) n'est pas
-1.
Récuperer la taille du fichier en faisant un
fd_size=lseek(fd,0,SEEK_END) puis projeter le fichier en mémoire à l'aide de
mmap:
memory=mmap(0,fd_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0). Tester bien que la valeur de retour n'est pas égale à
MAP_FAILED.
Enfin écrire un petit menu permettant de
- quitter le programme (n'oublier l'appel à
munmap).
- lire une partie de la zone mémoire (demande à l'utilisateur le début et la taille de la zone à afficher).
- écrire un texte saisi par l'utilisateur à une certaine position de la zone (demande le texte puis la position où le copier).
Tester votre programme en le lançant plusieur fois et en même temps sur le même fichier.
Continuer votre projet ...