Fonctions communes pour générer
les bargraphes et les graphiques
Cette page décrit les 2 bibliothèques de fonctions qui sont utilisées
à la fois pour générer les bargraphes et pour générer les graphiques du
site.
Accès aux champs d'un fichier CSV local
Une première bibliothèque de fonctions permet d'extraire les données d'un
fichier CSV local préalablement ouvert en écriture.
Elle est composé de 3 fonctions :
La fonction
recupchamp permet de récupérer le contenu du champ
du fichier CSV sur lequel on est positionné.
Elle accepte 2 paramètres :
- descfic : descripteur du fichier à lire
- champ : adresse mémoire du tableau de caractères qui
contiendra le champ lu
Après avoir lu un premier caractère à partir de l'endroit du fichier où
on s'était arrêté la fois précédente (début du fichier la toute première
fois), on mémorise ce caractère dans la variable
champ et on
lit le caractère suivant.
On continue le traitement jusqu'à ce que le dernier caractère lu indique
une fin de champ (caractère
; ou passage à la ligne).
A chaque lecture, on teste également si on est arrivé en fin de fichier.
Comme les valeurs du fichier CSV qui nous intéressent pour réaliser des
bargraphes et graphiques sont des pourcentages, la longueur des champs
attendus est limitée à 5 caractères. Si un champ lu venait à être plus
long, les caractères au delà du cinquième ne seront pas mémorisés.
Une fois le contenu du champ récupéré, on le complète d'un octet à 0
qui indique une fin de chaine de caractères en langage C.
// récupérer le début d'un champ (tronqué à 5 caractères)
void recupchamp (FILE *descfic, char *champ)
{
int car; // caractère lu
int i; // position dans le tableau champ
// initialisation
i = 0;
// lire le premier caractère du champ
car = getc (descfic);
// tant que ni fin de champ, ni fin de ligne, ni fin de fichier
while (car != ';' && car != '\n' && car != EOF)
{
// s'il y a de la place dans champ pour rajouter ce caractère
if (i < 5)
// le faire
champ [i++] = car;
// lire le caractère suivant
car = getc (descfic);
}
// terminer la chaine de caratères champ
champ [i] = '\0';
}
Une deuxième fonction
sautechamp permet d'avancer dans le
fichier CSV local en lisant sans mémoriser son contenu un champ dont
on n'a pas besoin.
Elle accepte comme unique paramètres
descfic qui est le
descripteur du fichier csv local ouvert en lecture.
Le traitement qu'elle fait consiste à lire les caractères du fichier
CSV local un par un jusqu'à ce qu'on trouve un caractère de fin de
champ
; , une fin de ligne ou une fin de fichier.
// sauter un champ dans la ligne sans le récupérer
void sautechamp (FILE *descfic)
{
int car; // caractère lu
// répéter
do
// lire le caractère suivant
car = getc (descfic);
// jusque fin de champ, de ligne ou de fichier
while (car != ';' && car != '\n' && car != EOF);
}
Une troisième fonction
finligne fonctionne presque comme
sautechamp mais elle s'arrête de lire seulement en fin de
ligne ou en fin de fichier. Elle permet donc d'ignorer les derniers
champs de la ligne sans avoir à les sauter un par un.
// sauter le reste de la ligne sans rien récupérer
void finligne (FILE *descfic)
{
int car; // caractère lu
// répéter
do
// lire le caractère suivant
car = getc (descfic);
// jusque fin ligne ou de fichier
while (car != '\n' && car != EOF);
}
Initialisation de l'entête d'un fichier image bmp
Comme pour les autres formats d'image, les fichiers bmp commencent par
une entête qui décrit les caractéristiques de l'image.
L'entête bmp commence par 2 caractères, puis la quasi totalité des
données qui suivent sont des nombres sur 4 octets.
Cela pose un problème de gestion de la mémoire car sur un ordinateur,
notamment sur un PC, les valeurs numériques sur 4 octets commencent
à des adresses mémoire multiples de 4.
Ici, à cause des 2 premiers octets du début, ces nombres commencent à
des adresses paires non multiples de 4.
Toutefois pour les images qu'on aura à générer, les valeurs à mettre
dans les champs de l'entête sont petites (inférieures à
2
16 = 65536).
Pour les bargraphes, toutes les valeurs sont et resteront inférieures
à cette limite. Pour les graphiques d'évolution de la vaccination, fin
2022, cette limite sera dépassée pour la taille de l'image et celle du
fichier s'il n'est pas encore compressé à ce moment là.
On simplifie la gestion de la mémoire en mémorisant les différentes
valeurs de l'entête dans un tableau d'entiers sur 16 bits (2 octets).
Les valeurs numériques sur 4 octets sont pour l'instant toutes composées
d'un entier sur 2 octets suivi de 2 octets à 0.
Avec le compilateur
gcc pour microprocesseur de type Intel,
les entiers sur 2 octets sont de type
short (ou
unsigned
short) aussi bien avec des microprocesseurs 32 bits qu'avec des
microprocesseurs 64 bits.
L'entête de l'image bmp sera donc mémorisée dans un tableau d'entiers
de type
short et un faisant un pré-remplissage des champs de
l'entête qui indiquent des caractéristiques de l'image identiques pour
les bargraphes et les graphiques, à savoir :
- image contenant entre 3 et 16 couleurs,
- chaque octet de l'image concerne 2 pixels,
- image non compressée (pour l'instant),
- image imprimable à raison de 10000 pixels par mètres soit 100
pixels par centimètre.
on obtiendra ceci :
// entête bmp partiellement pré-calculée
short entete [] = {0x4D42, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 1,
4, 0, 0, 0, 0, 10000, 0, 10000, 0, 0, 0, 0, 0};
Il faudra compléter cette entête avec des valeurs qui ne sont pas les
mêmes pour les bargraphes et le graphique. Pour cela, on définit une
fonction
gen_entete_bmp qui permettra de compléter l'entête
ci dessus. Cette fonction a besoin de 3 paramètres&npsp;:
- la largeur de l'image en pixels,
- sa hauteur en pixels,
- le nombre de couleurs utilisées.
// initialisation de l'entête d'une image bmp 3 à 16 couleurs
void gen_entete_bmp (int largeur, int hauteur, int nb_coul)
Le format d'images bmp impose comme contrainte que chaque ligne de
l'image occupe dans le fichier un multiple de 4 octets (utilisées ou
non pour les derniers). Il va falloir en tenir compte pour calculer
cette longueur et à partir de là, la taille de l'image.
// variables locales pour des calculs
short szimage, deplacement, larg2, manque;
// calcul des valeurs de certains champs de l'entête bmp
// pixels en largeur utilisés ou non (doit être multiple de 8)
manque = largeur % 8;
if (manque)
larg2 = largeur + 8 - manque;
else
larg2 = largeur;
// taille de la partie image du fichier
szimage = larg2 * hauteur / 2;
Il faut aussi calculer à partir de quel endroit du fichier bmp commence
l'image. Pour ça, (dans les images bmp utilisant jusqu'à 256 couleurs),
chaque couleur doit être définie sur une valeur de 4 octets. La taille
de la palette de couleurs s'ajoute à cette de l'entête.
// position du premier octet de la partie image du fichier
deplacement = sizeof (entete) + (nb_coul * 4);
À présent, on a calculé tout ce qu'il faut pour compléter l'entête du
fichier bmp. Il suffit de mettre les valeurs récupérées ou calculées
aux bons endroits dans le tableau d'entiers 16 bits.
// mise à jour des parties variables de l'entête
// taille du fichier
entete [1] = szimage + deplacement;
// position du début de la partie image
entete [5] = deplacement;
// pixels en largeur
entete [9] = largeur;
// pixels en hauteur
entete [11] = hauteur;
// nombre d'octets de la zone image
entete [17] = szimage;
// nombre de couleurs
entete [23] = nb_coul;
entete [25] = nb_coul;
}
Remarque :
Plutôt que de manipuler des indices de tableaux peu parlants, dans le
projet
Cyloop
(logiciel libre), l'entête bmp est définie
sous
la forme d'une structure.
On peut constater que celle-ci commence par 2 octets de remplissage qui
ne devront pas être recopiés dans le fichier mais qui permettent d'avoir
les données qui suivent (un mélange de caractères et d'entiers de 16 et
de 32 bits) bien positionnées les unes par rapport aux autres.