Changes between Initial Version and Version 1 of 2009/CaoCourseTme1


Ignore:
Timestamp:
Jan 10, 2010, 11:38:18 PM (15 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • 2009/CaoCourseTme1

    v1 v1  
     1[[Include(TocTme)]]
     2{{{
     3#!html
     4<h1> TME1 : Outils de développement de programmes C </h1>
     5}}}
     6[[PageOutline]]
     7
     8= Objectifs =
     9
     10L'objectif de ce premier TME est de vous permettre de vérifier que vous maîtrisez les principaux outils de développement utilisés pour programmer efficacement en langage C sous UNIX.
     11Attention : Cette U.E. suppose que vous connaissez le langage C. Si vous ne le connaissez pas, ou si vous avez des lacunes, vous devez vous formez par vous même. Les bibliothèques sont faites pour cela, et vous pouvez utiliser les machines des salles de TP en libre service pour faire des exercices.
     12
     13[[Image(cflow.gif, right, nolink)]]
     14
     15Dans ce TME, on utilisera principalement les outils suivants:
     16 * vim ou emacs : éditeur de texte
     17 * gcc : préprocesseur, compilateur, éditeur de liens
     18 * make : génération automatique avec gestion des dépendances
     19
     20L'application logicielle proposée est une application de manipulation d'images au format pgm.
     21Il s'agit d'images de hauteur et largeur quelconques quelconque, ou chaque pixel est codé
     22sur un octet (256 niveaux de gris).
     23Les algorithmes réalisent fondamentalement des parcours de tableaux à 2 dimensions.
     24
     25Commencez par créer un répertoire tme1, qui contiendra tous les fichiers utilisés dans ce TME.
     26
     27= Etape 1 : programme principal =
     28
     29Commencez par créer un sous-répertoire tme1/etape1 dans le répertoire tme1, et placez-vous dans ce répertoire. Dans cette première étape, vous allez devoir écrire deux fichiers : un fichier "main.c" contenant la fonction main(), et un fichier "Makefile" permettant de compiler le programme et de générer un fichier exécutable "pgmg".
     30
     31Le fichier "Makefile" doit contenir deux règles :
     32{{{
     33pgmg : main.c
     34}}}
     35qui effectue la compilation ET l'édition de liens en une seule passe.
     36{{{
     37clean
     38}}}
     39qui efface les fichiers temporaires et un éventuel 'core', pour ne conserver que les fichiers sources.
     40
     41Le prototype de la fonction main() est défini comme suit:
     42{{{
     43int main(int argc, char *argv[])
     44}}}
     45Dans cette première étape, le tableau argv[] contient exactement 3 arguments:
     46nom du programme, nom du fichier d'entrée, nom du fichier de sortie.
     47
     48Le programme main() lit le fichier "input_file_name", en utilisant la fonction readpgm().
     49Il  recopie chaque octet dans un tampon que vous devez allouer. Il écrit le contenu de ce tampon dans un fichier "output_file_name", en utilisant la fonction writepgm().
     50
     51Pour pouvoir utiliser les fonctions readpgm() et writepgm() dans votre programme main(),
     52vous devez inclure le fichier "pgmio.h" dans le fichier main.c. Il se trouve dans:
     53{{{
     54/users/enseig/encadr/cao/include/pgmio.h
     55}}}
     56Les prototypes des fonctions de lecture et d'écriture du format pgm, ainsi que la structure de données permettant de représenter une image en mémoire sont définis dans le fichier "pgmio.h". Vous pouvez retrouver cette information dans la page PgmInputOutput.
     57
     58Pour ce qui concerne le Makefile, l'édition de liens doit se faire avec la bibliothèque C qui se trouve dans
     59{{{
     60/users/enseig/encadr/cao/lib/libpgmio.a
     61}}}
     62
     63Lorsque l'écriture du programme main.c et du makefile sont terminés, lancez la compilation et l'édition de lien avec la commande
     64{{{
     65$ make
     66}}}
     67Un programme exécutable pgmg doit être généré dans votre répertoire de travail.
     68Pour vérifier que le programme fonctionne, recopiez dans votre répertoire de travail
     69le fichier "Untitled" contenant une image au format pgm. Ce fichier se trouve dans:
     70{{{
     71/users/enseig/encadr/cao/tme1/Untitled.pgm
     72}}}
     73Ce fichier peut être visualisé en utilisant la commande
     74{{{
     75$ display Untitled.pgm
     76}}}
     77Lancez l'exécution du programme pgmg:
     78{{{
     79$ ./pgmg Untitled.pgm new.pgm
     80}}}
     81Vérifiez que le fichier de sortie contient bien l'image initiale.
     82
     83= Etape 2 : Analyse de la ligne de commande =
     84
     85Commencez par créer un second sous-répertoire tme1/etape2 dans votre répertoire tme1.
     86Recopiez les fichiers main.c  et Makefile de dans ce sous-répertoire. Dans cette seconde étape,
     87ce n'est plus le programme main() qui analyse la ligne de commande, car on souhaite introduire
     88des arguments optionnels dans la ligne de commande. La tâche d'analyse est effectuée par une
     89fonction getarg() contenue dans le fichier "getarg.c". Il faut donc modifier la fonction main(),
     90et écrire la fonction getarg(). 
     91
     92Le fichier "getarg.c" doit contenir aussi la déclaration de la variable globale mainarg,
     93de type 'mainarg_t', qui contient les valeurs de tous les paramètres lus par la fonction getarg().
     94
     95Le fichier "getarg.h" doit contenir la définition du type mainarg_t, et la déclaration du prototype
     96de la fonction getarg() :
     97{{{
     98typedef struct mainarg_t {
     99char     *InputFileName;
     100char     *OutputFileName;
     101char     *CommandFileName
     102char     verbose;
     103} mainarg_t;
     104
     105extern mainarg_t  mainarg;
     106
     107extern void getarg(int argc, char * argv[]);
     108}}}
     109Le programme 'pgmg' a maintenant deux arguments obligatoires et deux arguments optionnels:
     110{{{
     111pgmg [-c command_file_name] [-v] input_file_name output_file_name
     112}}}
     113Les deux arguments optionnels sont placés au début dans la ligne de commande mais dans n'importe quel ordre.
     114 * -v est un drapeau qui demande au programme d'afficher un message à chaque étape du traitement.
     115 * -c command_file_name permet de définir une série de traitement à appliquer à l'image, dans un fichier de commandes.
     116
     117On se contente dans cette étape d'analyser les arguments de la ligne de commande.
     118L'analyse des commandes contenues dans le fichier de commande sera réalisée
     119à l'étape suivante.
     120
     121La fonction getarg() doit traiter les cas d'erreurs. Une erreur possible est la détection
     122d'un argument optionnel de type non défini (par exemple "-t"). Une autre erreur possible est
     123la détection d'un nombre d'arguments supérieur à 4, ou inférieur à 2. En cas d'erreur,
     124la fonction getarg() doit afficher un message d'erreur rappelant le format de la ligne de commande,
     125et sortir du programme en utilisant l'appel système "exit".
     126
     127Après avoir modifié le fichier "main.c" (en particulier pour introduire l'affichage
     128des messages correspondant au mode 'verbose'), et après avoir écrit les fichiers "getarg.c" et "getarg.h",
     129il vous reste à modifier le fichier "Makefile", pour prendre en compte ces nouveaux fichiers.
     130
     131Compilez, puis exécutez le nouveau programme pgmg, en mode 'verbose', pour vérifier le bon fonctionnement.
     132
     133= Etape 3 : Exploitation du fichier de commandes =
     134
     135Commencez par créer un sous répertoire tme1/etape3, et recopiez vos fichiers source et
     136votre Makefile dans ce répertoire, pour conserver les états intermédiaires de votre travail.
     137Cette troisième étape consiste principalement à écrire un parseur élémentaire utilisant
     138les fonctions fgets() et sscanf().
     139Vous pouvez vous inspirez de l'exemple que vous trouverez dans ScanfExample.
     140
     141Le fichier de commandes contient une commande par ligne, et chaque commande déclenche
     142une transformation complête de tous les pixels de l'image.
     143 * S n : seuillage (si val > n, val = 255 / sinon val = 0)
     144 * X : symétrie suivant x (x devient -x)
     145 * Y : symétrie suivant y (y devient -y)
     146 * P : rotation positive de 90°
     147 * M : rotation négative de 90°
     148 * F C00 C10 C20 C01 C11 C21 C02 C02 C12 C22 : filtrage produit de convolution avec une matrice 3*3
     149
     150Voici un exemple de fichier de commandes:
     151{{{
     152# une ligne commencant par un # est un comentaire
     153X
     154Y
     155P
     156M
     157S 12
     158F 1 -1 1 2 10 2 1 -1 1
     159}}}
     160L'analyse du fichier de commande et l'exécution des transformations définies dans ce fichier
     161sont réalisées par la fonction operate().
     162Cette fonction prend en entrée un pointeur sur le fichier de commande, et un pointeur
     163sur une structure de donnée gmap contenant l'image initiale.
     164Elle applique séquenciellement les transformations définies dans le fichier de commandes,
     165et renvoie un pointeur sur la structure de donnée gmap contenant l'image résultante.
     166{{{
     167gmap *operate(FILE *commande, gmap *in);
     168}}} 
     169Ecrivez le fichier operate.c, qui contient la fonction operate(), ainsi que le fichier associé operate.h.
     170Cette fonction analyse le fichier de commande ligne par ligne, et exécute immédiatement la transformation
     171demandée. Pour cela, on définira une fonction par type de commande. Ces 6 fonctions réalisant les
     172transformations prennent pour nom le caractère définissant la commande, et possèdent au moins deux arguments: un pointeur sur l'image source, et un pointeur sur l'image résultat. Les deux structures de
     173données doivent donc avoir été allouées en mémoire préalablement : pas de malloc() dans ces fonctions.
     174Les 4 fonctions X(), Y(), P(), M() n'ont que 2 arguments, mais les deux fonctions S() et F() ont des arguments supplémentaires définissant les paramètres de la transformation:
     175{{{
     176void X(gmap *in, gmap *out);
     177void S(gmap *in, gmap *out, int n)
     178}}}
     179Pour cette étape, les fonctions de traitement n'exécutent pas réellement la transformation de
     180l'image. Elles se contentent de recopier l'image in dans l'image out, et d'afficher un message:
     181{{{
     182Operation XXX non implementee
     183}}}
     184Après avoir écrit les fichiers "operate.c" et "operate.h", et après avoir modifié le fichier "main.c"
     185pour prendre en compte le fichier de commandes, modifiez le fichier "Makefile", recompilez l'application
     186et exécutez le programme pgmg en mode 'verbose' pour le fichier de commande fourni en exemple.
     187
     188= Etape 4 : Exécution des transformations S,X,Y,P,M,F =
     189
     190Implémentez successivement les 6 fonctions S(), X(), Y() P(), M(), F() dans le fichier "operate.c".
     191Il faut calculer tous les pixels de l'image, en exécutant deux boucles for imbriquées
     192pour parcourir les lignes et les colonnes. Pour alléger l'écriture, on définira la macro
     193ELM(map,x,y) qui permet de désigner le pixel de coordonnées (x,y) dans l'image désignée
     194par le pointeur map.
     195{{{
     196#define ELM(map,x,y)  map->raster[(y)*map->width + (x)]
     197}}}
     198Le coeur de ces fonctions sera toujours de la forme :
     199{{{
     200for(y = 0 ; y < height ; y++) {
     201  for(x = 0 ; x < width ; x++) {
     202    ELM(out, U(x,y), V(x,y)) = ELM(in, x, y);
     203  }
     204}
     205}}}
     206La difficulté est évidemment de définir les expressions arithmétiques
     207U(x,y) et V(x,y) pour chacune des transformations à implémenter.
     208
     209L'opération de filtrage peut s'exprimer plus simplement avec le dessin suivant:
     210
     211[[Image(filtre.gif, nolink)]]
     212
     213= Compte-rendu =
     214
     215La note de TME compte dans la note de contrôle continu.
     216Vous n'avez pas de compte-rendu écrit à rendre, mais vous aurez à
     217faire une démonstration de votre programme et à présenter le code
     218au début de la séance de TME de la semaine suivante.
     219
     220N'oubliez pas de commenter votre programme...