Bibliothèque de traitements d'images en virgule flottante.
http://la.buvette.org/photos/cumul/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
599 lines
19 KiB
599 lines
19 KiB
\documentclass[a4paper,10pt]{article} |
|
|
|
% \listfiles % pour le debug |
|
|
|
\usepackage[french]{babel} |
|
\usepackage[utf8]{inputenc} |
|
\usepackage[T1]{fontenc} |
|
% XXX \usepackage{lipsum} |
|
\usepackage{makeidx} |
|
\usepackage{listings} |
|
\usepackage{babel} |
|
|
|
\usepackage{pifont} % caractères rigolos |
|
\usepackage{enumitem} |
|
\setitemize[1]{label={\ding{82}}} |
|
\frenchbsetup{CompactItemize=false} |
|
|
|
% \usepackage{color} |
|
% \usepackage{url} |
|
\usepackage{xspace} |
|
\usepackage[verbose]{layout} |
|
|
|
\makeindex |
|
|
|
% ------ a few new commands |
|
\newcommand{\interparagraphe { \vspace{60pt} } } |
|
|
|
% ------------------------------------------------------------------- |
|
\title{Floating images processing} |
|
\author{tTh} |
|
|
|
\begin{document} |
|
\maketitle |
|
|
|
\section{Image flottante ?} |
|
|
|
Mais de quoi parle-t-on exactement ? |
|
|
|
\vspace{1em} |
|
|
|
Traditionnellement, les valeurs des pixels dans les images |
|
informatiques sont mémorisées sur 8 bits, un octet\index{octet}, |
|
soit 256 valeurs différentes. |
|
Ceci dit, on trouve parfois des images codées sur 16 bits par |
|
composante, mais c'est loin d'être le cas général. |
|
J'ai donc souhaité aller plus loin, et coder chaque canal de |
|
chaque pixel en virgule flottante sur 32bits, le type |
|
\texttt{float}\index{float} du langage C. |
|
|
|
\vspace{1em} |
|
|
|
Attention, tout le code que nous allons voir ensemble est en |
|
perpétuelle évolution\footnote{voir page \pageref{TODO}}, |
|
et sa fiablité reste à démontrer\index{valgrind}. |
|
Mais le service après-vente est assez réactif. Du moins |
|
pour ceux qui suivent \texttt{\#tetalab} sur le réseau |
|
IRC de Freenode. |
|
|
|
% ------------------------------------------------------------------- |
|
|
|
\tableofcontents |
|
\pagebreak |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Premier example}\index{example}\label{example} |
|
|
|
\textsc{FloatImg} a débuté sous la forme de quelques fonctions |
|
basiques en C, gérant la structure des données d'image en mémoire |
|
et sur disque. Ça a été imaginé de façon presque empirique, |
|
mais nous sommes tous là pour améliorer les choses, dans |
|
la mesure de nos moyes. |
|
Nous allons donc directement rentrer au cœur du problème. |
|
|
|
\vspace{1em} |
|
|
|
Pour commencer par quelques chose de simple, |
|
nous allons créer une image RGB\index{RGB} complètement noire, |
|
puis l'enregistrer dans un fichier \texttt{.fimg}\index{.fimg}, |
|
un format complètement inconnu, puisque je viens de l'inventer |
|
à l'instant même. |
|
|
|
Tout d'abord, nous devons déclarer et garnir quelques variables |
|
pour gérer la machinerie interne. |
|
|
|
\begin{verbatim} |
|
int width = 640, height = 480; |
|
char *fname = "exemple.fimg"; |
|
FloatImg fimg; |
|
\end{verbatim} |
|
|
|
Ensuite, nous enchainerons trois étapes : création de l'image |
|
en mémoire centrale, initialisations des valeurs de pixel à 0.0, |
|
et pour conclure, enregistrement dans un fichier. |
|
|
|
\begin{verbatim} |
|
foo = fimg_create(&fimg, width, height, FIMG_TYPE_RGB); |
|
if (foo) { |
|
fprintf(stderr, "create floatimg -> %d\n", foo); |
|
exit(1); |
|
} |
|
fimg_clear(&fimg); |
|
foo = fimg_dump_to_file(&fimg, fname, 0); |
|
if (foo) { |
|
fprintf(stderr, "dump fimg -> %d\n", foo); |
|
exit(1); |
|
} |
|
\end{verbatim} |
|
|
|
|
|
Une fois ce code enrobé dans un \texttt{main()}, compilé et exécuté, |
|
nous pouvons entrevoir, grâce au logiciel |
|
\texttt{fimgstats} (voir page \pageref{fimgstats}), |
|
le résultat sous forme de chiffres divers, et/ou inutiles~: |
|
|
|
\begin{verbatim} |
|
$ ./fimgstats quux.img |
|
----------- numbers from 'quux.img' : |
|
640 480 3 0x7f3718c4f010 0x7f3718d7b010 0x7f3718ea7010 |
|
surface 307200 |
|
mean values: |
|
R 0.000000 |
|
G 0.000000 |
|
B 0.000000 |
|
A 0.000000 |
|
max value 0.000000 |
|
\end{verbatim} |
|
|
|
Nous avons donc sous la main une mécanique qui ne demande qu'à |
|
faire des trucs futiles et des images qui clignotent. |
|
La suite vers la page \pageref{codaz}. |
|
|
|
\vspace{1em} |
|
|
|
Vous trouverez dans le répertoire \texttt{tools/}\index{tools/} |
|
d'autres exemples de mise en œuvre des fonctions disponibles |
|
sous formes d'outils en ligne de commande, |
|
lesquels sont décrits en page \pageref{outils}. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Installation} |
|
|
|
\subsection{Prérequis} |
|
|
|
Vous devez, en dehors des outils classiques (bash, gcc, make\dots), |
|
avoir quelques bibliothèques installées\footnote{Les \texttt{-dev} |
|
pour Debain et dérivées}~: libv4l2, libpnglite, libtiff, libpnm, |
|
et probablement d'autres choses. |
|
|
|
\vspace{1em} |
|
|
|
Il est même quasiment certain que Bash soit indispensable, tout |
|
comme \textsc{gnu}/make\index{make}. |
|
Une connaissance de base de l'utilisation du shell\index{shell} |
|
et de l'écriture de Makefile's sera un plus. |
|
|
|
\subsection{Compilation} |
|
|
|
Un script \texttt{build.sh} permet de construire approximativement |
|
le bouzin. Il est loin d'être parfait\footnote{Il doit être possible |
|
de faire un Makefile récursif, mais\dots}. |
|
Dans chacun des |
|
répertoires à traiter, ce script devrait trouver un Makefile et un fichier |
|
\texttt{t.c} source de la cible par défaut du make. |
|
|
|
\vspace{1em} |
|
|
|
Pour le moment, la procédure d'installation est un peu rude, |
|
pour ne pas dire clairement sommaire. |
|
Si le résultat vous semble correct, vous pouvez copier |
|
les deux fichiers \texttt{floatimg.h} et \texttt{libfloatimg.a} |
|
dans un emplacement |
|
approprié, par exemple |
|
\texttt{/usr/local/include} et \texttt{/usr/local/lib}. |
|
|
|
|
|
|
|
% ------------------------------------------------------------------- |
|
\section{Utilisation coté codeur}\label{codaz} |
|
|
|
Classiquement, il y a un fichier à inclure, \texttt{floatimg.h}, |
|
contenant un certain nombre de |
|
définition de structures, de macros, |
|
de constantes\footnote{À l'ancienne, via le pré-processur} |
|
et les prototypes des fonctions utilisables. |
|
\vspace{1em} |
|
|
|
Au niveau du code source, ces fonctions sont approximativement |
|
classées en deux catégories : \texttt{lib/} et \texttt{funcs/}. |
|
La première contient les choses qui sont relativement figées, |
|
et la seconde celles qui risquent de bouger. Cette classification |
|
est en fait arbitraire. |
|
|
|
\subsection{Structures, macros\dots} |
|
|
|
Les pixels flottants d'une image résidant en mémoire centrale |
|
sont décrits par un ensemble |
|
de données (certains appelent ça des \textsl{metadats}) regroupées |
|
dans une jolie structure que nous allons examiner dès maintenant. |
|
|
|
\begin{verbatim} |
|
/* in memory descriptor */ |
|
typedef struct { |
|
int width; |
|
int height; |
|
int type; |
|
float fval; |
|
int count; |
|
float *R, *G, *B, *A; |
|
int reserved; |
|
} FloatImg; |
|
\end{verbatim}\index{FloatImg} |
|
|
|
Les deux premiers champs sont \textsl{obvious}. |
|
Le troisième est le type d'image : pour le moment, il y en a trois |
|
qui sont définis\footnote{et plus ou moins bien gérés\dots} : |
|
gris, rgb et rgba\index{rgba}. |
|
|
|
\begin{verbatim} |
|
#define FIMG_TYPE_GRAY 1 |
|
#define FIMG_TYPE_RGB 3 |
|
#define FIMG_TYPE_RGBA 4 |
|
\end{verbatim} |
|
|
|
Un peu plus loin, nous avons les pointeurs vers les |
|
différents \textsl{pixmaps} de l'image. En principe l'organisation |
|
interne de ces zones est improbable, puisque qu'elle dérive |
|
d'idées approximatives. |
|
\vspace{1em} |
|
|
|
Les deux champs suivants (fval et count) sont à la disposition du |
|
\textsl{yuser} |
|
qui peut jouer avec à loisir pour faire, par exemple, ce genre de |
|
chose. Imaginons un périphérique de capture qui nous fournisse des |
|
images en gris sur 4 bits. Et que nous voulions cumuler\index{cumul} |
|
quelques images... |
|
\vspace{1em} |
|
|
|
Le champ \textsl{count} sera mis à 0 et |
|
le champ \textsl{fval} sera initialisé à 15.0 |
|
(valeur maximale renvoyée par le capteur). |
|
Ensuite, dans la boucle capture/cumul, \textsl{count} sera |
|
incrémenté à chaque passe, et nous aurons donc, en finale, |
|
toutes les informations nécessaires pour exploiter au mieux la dynamique |
|
de notre image dans les étapes ultérieures. |
|
|
|
|
|
\subsection{lib/}\index{lib/} |
|
|
|
Première chose, la gestion dynamique de la mémoire occupées |
|
par tous ces pixels flottants est faite par ces deux fonctions~: |
|
|
|
\begin{verbatim} |
|
int fimg_create(FloatImg *fimg, int w, int h, int type); |
|
int fimg_destroy(FloatImg *fimg); |
|
\end{verbatim} |
|
|
|
Les types d'images actuellement gérés sont les trois grands |
|
classiques : gray, rgb et rgba. Il y a les constantes adéquates |
|
dans \texttt{floatimg.h}. Les codes d'erreur sont disparates |
|
et non documentés. |
|
\vspace{1em} |
|
|
|
Bon, vous avez une image latente, et vous souhaitez dessiner dessus |
|
(ou dedans ?) avec vos encres flottantes ? |
|
Il y a une fonction pour ça. |
|
|
|
\begin{verbatim} |
|
int fimg_plot_rgb (FloatImg *head, int x, int y, |
|
float r, float g, float b); |
|
\end{verbatim} |
|
|
|
Les paramètres sont explicites, mais leur validité doit être |
|
sévèrement controlée par l'appelant. Il y a une fonction |
|
soeur, \texttt{fimg\_add\_rgb}\index{fimg\_add\_rgb}, |
|
qui ajoute du rgb à un pixel. |
|
|
|
\subsection{funcs/}\index{funcs/}\label{funcs} |
|
|
|
Une bonne partie de ces fonctions est indéterministe. Ce qui |
|
veut dire, en langage de tous les soirs, que ça risque de ne |
|
pas être la même chose dans l'avenir. |
|
\vspace{1em} |
|
|
|
On y trouve pêle-mêle de l'import/export de fichiers, de l'analyse |
|
de chaines de caractères, du tracé de choses bizarres\dots |
|
Plein de trucs qu'il faudra bien expliquer un jour\footnote{Mais |
|
il fait trop chaud dans le dd2\index{dd2}}. |
|
|
|
\subsection{Exemple de fonction}\index{example} |
|
|
|
Nous allons écrire une fonction qui va faire quelque chose |
|
à partir d'une image source et d'une valeur, et écrire le |
|
résultat dans une image de destination. |
|
Pour simplifier les choses, nous n'allons traiter que les |
|
images de type \textsc{FIMG\_TYPE\_RGB}, de loin le plus |
|
répandu. |
|
|
|
\begin{verbatim} |
|
int fimg_example(FloatImg *s, FloatImg *d, float value) |
|
{ |
|
int size, index; |
|
|
|
if ( s->type!=FIMG_TYPE_RGB || d->type!=FIMG_TYPE_RGB) { |
|
return -1; |
|
} |
|
|
|
size = s->width * s->height; |
|
for (idx=0; idx<size; idx++) { |
|
d->R[idx] = s->R[idx] - value; |
|
d->G[idx] = s->G[idx] - value; |
|
d->B[idx] = s->B[idx] - value; |
|
} |
|
|
|
return 0; |
|
} |
|
\end{verbatim} |
|
|
|
Je vous laisse imaginer les dégats que peut faire cette |
|
fontion en utilisation réelle. |
|
En particulier tout le reste du code qui suppose qu'un pixel |
|
ne peut \textbf{pas} être négatif. |
|
Vous pouvez aussi remarquer qu'il n'y a pas de controle |
|
de cohérence sur les dimensions des deux images. |
|
|
|
|
|
% ------------------------------------------------------------------- |
|
\section{Les outils}\label{outils} |
|
|
|
\textsl{3615mavie} : sur des projets comme celui-ci, qui travaillent |
|
in-fine sur des objets que l'on peut considérer comme « physiques », |
|
il est important de passer à une utilisation |
|
normale\footnote{Il y a une vie en dehors de git.} et construire |
|
des trucs qui mettent en action le code primitif. |
|
\vspace{1em} |
|
|
|
Ces machins ont en commun deux options bien pratiques~: |
|
\texttt{-h} pour avoir un résumé des options disponibles |
|
et \texttt{-v} qui augmente la puissance de bavardage. |
|
Dans un avenir incertain, il existera des pages de man\index{man}. |
|
|
|
|
|
\subsection{mkfimg}\index{mkfimg}\label{mkfimg} |
|
|
|
Création d'un fichier contenant une image de « teinte » constante |
|
(ou pas). |
|
Cette notion de teinte est assez inconsistante pour le moment, |
|
|
|
\begin{verbatim} |
|
tth@debian:~/Devel/FloatImg/tools$ ./mkfimg -v -h |
|
Usage: mkfimg [options] quux.fimg width height |
|
-k N.N give a float parameter |
|
-t bla howto make the pic |
|
black, drand48... |
|
-v increase verbosity |
|
*** FloatImg library, alpha v73 (Sep 28 2019, 23:34:29) |
|
\end{verbatim} |
|
|
|
|
|
\subsection{png2fimg}\index{png2fimg}\label{png2fimg} |
|
|
|
Grosse panne à réparer. |
|
|
|
\begin{verbatim} |
|
tth@debian:~/TMP/floatimg$ png2fimg A.png foo.fimg |
|
error in 'fimg_create_from_png' : read png -> -1 File error |
|
png2fimg : err -1, abort. |
|
\end{verbatim} |
|
|
|
Il faut envisager le passage à \texttt{libpng}\index{libpng}. |
|
|
|
\subsection{fimgstats}\index{fimgstats}\label{fimgstats} |
|
|
|
Affichage de quelques valeurs calculées à partir du contenu d'un fichier |
|
\texttt{.fimg}\index{.fimg}. |
|
|
|
\begin{verbatim} |
|
usage : fimgstats [options] file.fimg |
|
-c make a machinable csv |
|
-v increase verbosity |
|
\end{verbatim} |
|
|
|
À vrai dire, je ne sais pas encore quelles métriques seront utiles |
|
en première approche, alors commençont par le plus simple, |
|
les valeurs moyennes de chaque composante. |
|
|
|
Puis nous rajouterons\footnote{Les patchs sont les bienvenus} |
|
le calcul de la variance\index{variance}. |
|
|
|
\subsection{fimgops}\index{fimgops}\label{fimgops} |
|
|
|
Quelques opérations diverses entre deeux images, qui doivent être |
|
de la même taille, et du même type \textsl{pour le moment, |
|
uniquement RGB}. |
|
|
|
\begin{verbatim} |
|
usage: |
|
fimgops [options] A.fimg B.fimg operator D.fimg |
|
operators: |
|
add 1 |
|
sub 2 |
|
mix 3 |
|
mul 4 |
|
mini 5 |
|
maxi 6 |
|
options: |
|
-g convert output to gray |
|
-k N.N set float value |
|
-v increase verbosity |
|
\end{verbatim} |
|
|
|
Pour des operateurs paramétrable (comme \texttt{mix}), le paramêtre |
|
flottant doit être fourni en utilisant l'option \texttt{-k}. |
|
La véracité mathématique n'est pas garantie. |
|
|
|
\subsection{fimg2png, fimg2pnm, fimg2tiff} |
|
\index{fimg2png}\label{fimg2png} |
|
\index{fimg2pnm}\label{fimg2pnm} |
|
\index{fimg2tiff}\label{fimg2tiff} |
|
|
|
Quelques petits proggies pour exporter notre format\index{.fimg} secret |
|
vers des choses plus directement utilisables. À condition que le |
|
code soit écrit et documenté. Peut-être en page \pageref{funcs}\dots |
|
|
|
D'un autre coté, écrire un greffon d'import/export pour |
|
Gimp\index{Gimp} ou Imagemagick\index{Imagemagick} |
|
ne devrait pas être trop difficile. Des volontaires ? |
|
|
|
\subsection{fimg2gray}\index{fimg2gray}\label{fimg2gray} |
|
|
|
Nous avons vu dans ce document que chaque image flottante pouvait |
|
avoir plusieurs plans de réalité. Il ne faut en négliger aucun. |
|
\vspace{1em} |
|
|
|
Il faut quand même deviner que pour passer de l'espace RGB\index{RGB} |
|
à une abstraction linéaire mono-dimensionnelle, il existe une foultitude |
|
de méthodes, toutes plus légitimes que les autres. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{TODO}\index{TODO}\label{TODO} |
|
|
|
Il reste plein de choses à faire pour que ce soit vraiment utilisable. |
|
\vspace{1em} |
|
|
|
\begin{itemize} |
|
|
|
\item Import/export au format \textsc{tiff}\index{tiff}. |
|
\item Remplacer le « fait-maison » par \textsc{libnetpnm}\index{pnm}. |
|
\textsl{[en cours]}. |
|
\item Compléter les traitements mathémathiques (eg le gamma\index{gamma}). |
|
\item Formaliser les codes d'erreur. |
|
\ |
|
\end{itemize} |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Exemples pour yusers}\index{example} |
|
|
|
Nous allons \textsl{essayer d'improviser} un exemple presque réel, |
|
avec un peu de rache\index{rache} dedans. |
|
|
|
\vspace{1em} |
|
|
|
Nous savons générer une image contenant des pixels aux valeurs |
|
probablement aléatoires (drand48\index{drand48}). Que se passe-t-il si |
|
nous faisons la somme de plusieurs centaines\footnote{Des erreurs toxiques ?} |
|
de ces images ? |
|
|
|
\begin{verbatim} |
|
#!/bin/bash |
|
|
|
ACCU="quux.fimg" |
|
TMPF="tmp.fimg" |
|
DIMS="320 240" |
|
|
|
mkfimg $ACCU $DIMS |
|
|
|
for i in {0..1000} |
|
do |
|
mkfimg -t drand48 ${TMPF} ${DIMS} |
|
fname=$( printf "xx%04d.pnm" $i ) |
|
fimgops $ACCU $TMPF add $ACCU |
|
fimg2pnm -v -g $ACCU $fname |
|
done |
|
|
|
convert -delay 10 xx*.pnm foo.gif |
|
\end{verbatim} |
|
|
|
Voilà, si les choses se passent mal, vous allez découvrir |
|
que votre drand n'est pas si drand que ça. |
|
|
|
|
|
% ------------------------------------------------------------------- |
|
\section{Video for Linux}\index{v4l2} |
|
|
|
Donc, maintenant, nous savons un peu tripoter ces images flottantes. |
|
Et nous devons nous poser une question fondamentale\footnote{primitive ?} |
|
sur la provenance de ces données prétendant être des images. |
|
\vspace{1em} |
|
|
|
En fait, notre désir secret est la découverte des choses cachées du |
|
monde qui nous entoure. Nous voulons des images du \textbf{réel} et |
|
pour cela, l'outil le plus commun, le plus répandu, |
|
est la webcam\index{webcam}. L'universelle webcam. Et l'incontournable |
|
v4l2. |
|
|
|
\subsection{grabvidseq}\index{grabvidseq}\label{grabvidseq} |
|
|
|
Un logiciel en évolution, qui permet déja la capture d'images en |
|
\textsl{longue pose} selon la méthode du cumul\index{cumul}, et |
|
devrait bientôt retrouver sa capacité à enregistrer des |
|
séquences. |
|
|
|
\begin{verbatim} |
|
tth@debian:~/Devel/FloatImg/v4l2$ ./grabvidseq -h |
|
options : |
|
-d /dev/? select video device |
|
-g convert to gray |
|
-n NNN how many frames ? |
|
-O ./ set Output dir |
|
-o bla set output filename |
|
-p NN.N delay between frames |
|
-s WxH size of capture |
|
-u try upscaling... |
|
-v increase verbosity |
|
-X arg Xperiment option |
|
\end{verbatim} |
|
|
|
La plupart de ces options ont un usage quasi-évident. |
|
L'option \texttt{-s} doit correspondre à une des |
|
résolutions possibles de votre capteur. Le type du |
|
fichier en sortie (option \texttt{-o}) est déterminé par |
|
l'extension, actuellement |
|
seulement \texttt{.fimg} et \texttt{.pnm} sont reconnus. |
|
La conversion en gris (option \texttt{-g}) mérite un |
|
peu plus de travail, et une paramétrisation plus facile. |
|
|
|
L'option \texttt{-X} me permet d'intégrer des \textit{fritures} |
|
expérimentales dans le binaire, et ne doit donc pas être |
|
utilisée dans des scripts si on a des visions à long |
|
terme. |
|
|
|
\subsubsection{Upscaling}\index{upscaling}\label{upscaling} |
|
|
|
La fonction que j'ai appelée \textsl{upscaling} est un petit |
|
hack qui permet de doubler artificiellement la résolution |
|
de l'image, en profitant du fait que l'on est capable |
|
de prendre $N$ images en rafale. |
|
|
|
Pour être rigoureux dans la prise de vue, ce $N$ doit |
|
être un multiple de 4, surtout si le nombre de capture est faible.. |
|
|
|
\vspace{1em} |
|
|
|
\textbf{Là, il manque un schéma\dots} |
|
|
|
\subsubsection{shoot.sh}\index{shoot.sh}\label{shoot.sh} |
|
|
|
\hspace{4cm}XXX\index{XXX} |
|
|
|
|
|
\subsection{video-infos}\index{video-infos}\label{video-infos} |
|
|
|
Que contient, que peut faire mon périphérique \textsl{àlc} ? |
|
Quelles sont ses possibilités de réglage ? |
|
|
|
\begin{verbatim} |
|
tth@debian:~/Devel/FloatImg$ v4l2/video-infos -h |
|
Options : |
|
-d select the video device |
|
-K nnn set the K parameter |
|
-l list video devices |
|
-T bla add a title |
|
-v increase verbosity |
|
\end{verbatim} |
|
|
|
Je me sois d'avouer qu'il reste quelques points mystérieux dans |
|
l'\textsc{api} de \textsc{v4l2}, et donc, que ce que raconte |
|
ce logiciel doit être pris avec des pincettes. En particulier |
|
la liste des résolutions disponibles. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Et pour la suite ?} |
|
|
|
En fait, je fait de la photo par la méthode du « cumul »\index{cumul} |
|
depuis plusieurs années. Une webcam\index{webcam}, |
|
un Linux\index{Linux}, et ça \textsl{juste marche}. |
|
Sauf que c'est quand même un peu galère à déplacer, il faut |
|
avoir un shell pour déclencher, c'est pas facile à utiliser |
|
en mode portnawak\dots |
|
\vspace{1em} |
|
|
|
L'idée est donc de construire un appareil autonome, basé sur un Raspi et |
|
une webcam \textsc{usb}\index{USB}, alimenté par batterie et permettant d'aller |
|
faire des images au bord d'un lac. |
|
|
|
% ------------------------------------------------------------------- |
|
|
|
\printindex |
|
|
|
\end{document}
|
|
|