Présentation:

Bitmap est une représentation d’image. (plan de points)

Le format le plus populaire est le .bmp (bitmap) , qui est malheureusement la propriété de (c)microsoft.

https://fr.wikipedia.org/wiki/Windows_bitmap   (bien décris ici)

Ce dernier nous autorise malgré tout à l’utiliser.  Il reste un type de fichier un peu lourd et compliqué.

J’ai une préférence sur les formats libre pbm, pgm et ppm

Utilisable par gimp.

La réfèrence est sur wikipéedia:

https://fr.wikipedia.org/wiki/Portable_pixmap

les 3 formats étudiés:

pbm ,  binaire map , Noir&Blanc

pgm, nuance de gris.

ppm, en couleurs 24bits 

P1,P2,P3  sont de type ASCII complet. Le # signal un commentaire (dans l’entête)

Dans la wiki on nous conseille de ne jamais dépasser 70 caractères par ligne.

P4,P5,P6 seul l’entête est ASCII les données sont stockées  en bit .. ou octet , appelé mode RAW (BRUT)

pbm , P1 et P4

Noir et Blanc , 1 noir , 0 Blanc

Le format P1 (pbm ascii)

Exemple de fichier P1: (ASCII total) (le code ASCII n’est pas forcèment le meilleurs des codages pour une image mais ici pédagogiquement parlant ! c’est top ! ) , une belle croix (cross)

P1
8 8
0 0 0 1 1 0 0 0
0 0 0 1 1 0 0 0
0 0 0 1 1 0 0 0
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
0 0 0 1 1 0 0 0
0 0 0 1 1 0 0 0
0 0 0 1 1 0 0 0
work@bruno:~/work/croix$ hexdump -C croix.pbm 
00000000  50 31 0a 38 20 38 0a 30  20 30 20 30 20 31 20 31  |P1.8 8.0 0 0 1 1|
00000010  20 30 20 30 20 30 0a 30  20 30 20 30 20 31 20 31  | 0 0 0.0 0 0 1 1|
*
00000030  20 30 20 30 20 30 0a 31  20 31 20 31 20 31 20 31  | 0 0 0.1 1 1 1 1|
00000040  20 31 20 31 20 31 0a 31  20 31 20 31 20 31 20 31  | 1 1 1.1 1 1 1 1|
00000050  20 31 20 31 20 31 0a 30  20 30 20 30 20 31 20 31  | 1 1 1.0 0 0 1 1|
00000060  20 30 20 30 20 30 0a 30  20 30 20 30 20 31 20 31  | 0 0 0.0 0 0 1 1|
*
00000087

On constate que chaque pixel est séparé d’un espace ou un retour a la ligne. (0x20 espace , 0x0a LF , retour à la ligne)

P1
8 8
0
0
0
1
1
0
0
0
0
0
0
1
....etc 

Comme on ne peut pas dépasser  70 caractères par ligne on  va préférer  un seul et un LF (0x0a), retour à la ligne, Le fichier sera moins éditable mais plus simple à générer.

work@bruno:~/work/croix$ hexdump -C croix_lin.pbm 
00000000  50 31 0a 38 20 38 0a 30  0a 30 0a 30 0a 31 0a 31  |P1.8 8.0.0.0.1.1|
00000010  0a 30 0a 30 0a 30 0a 30  0a 30 0a 30 0a 31 0a 31  |.0.0.0.0.0.0.1.1|
*
00000030  0a 30 0a 30 0a 30 0a 31  0a 31 0a 31 0a 31 0a 31  |.0.0.0.1.1.1.1.1|
00000040  0a 31 0a 31 0a 31 0a 31  0a 31 0a 31 0a 31 0a 31  |.1.1.1.1.1.1.1.1|
00000050  0a 31 0a 31 0a 31 0a 30  0a 30 0a 30 0a 31 0a 31  |.1.1.1.0.0.0.1.1|
00000060  0a 30 0a 30 0a 30 0a 30  0a 30 0a 30 0a 31 0a 31  |.0.0.0.0.0.0.1.1|
*
00000087

Le format P4 (pbm binaire)

on remarque que ce format est bien moins gourmand en mémoires par rapport au P1 , pour un même résultat.

work@bruno:~/work/croix$ hexdump -C crx_raw.pbm 
00000000  50 34 0a 38 20 38 0a 18  18 18 ff ff 18 18 18     |P4.8 8.........|
0000000f

L’entête est la même (P1 devenu P4)

8 8 , largeur (espace) hauteur , suivi d’un retour a la ligne.

Et la les données ne sont plus écrites en ASCII mais on va appeler ça en binaire

0x18 =  0b00011000      

0xFF = 0b111111111    

On voit que ce format à l’avantage d’être moins gourmand en mémoire .

4 -rw-r--r-- 1 work work 135 févr.  4 16:14 croix.pbm
4 -rw-r--r-- 1 work work  15 févr.  4 16:26 crx_raw.pbm

Le premier est le P1 (croix.pbm)  , et le P4 (crx_raw.pbm)

Attention le format P4 :

  • Un fichier pbm binaire a pour nombre magique P4. Dans les données binaires de l’image, les bits sont regroupés par 8 pour former un octet, les bits excédentaires à la fin d’une ligne sont ignorés

pgm, P2 et P5

Nuance de Gris

Tout est dit sur wikipedia sur les formats P2/5 ( pareil que P1/4)

ppm, P3 et P6

Couleurs RVB

Pareil que P1/ P4

Tout est dit sur wikipedia sur les formats 

Sauvegarde au format P4

int sauve_image_P4(char * titre)
{
    int x,y;
    unsigned char pds;  /* connaitre le poid su bit */
    unsigned char octet; /*contient le resultat de l'octet a ecrire */
    octet=0;
    pds=128;
    fichier = fopen(titre,"w"); /* on ouvre le fichier en ecriture */
        if (fichier == NULL)
        {
            printf(" Je n'ai pas reussi a ouvrir le fichier \n");
            return(EXIT_FAILURE);  /*on sort du programme erreur .. d'ouverture */
        }
    /* En tete de l image */
        fprintf(fichier,"P4\n"); /* j'ecris dans le fichier  */
        fprintf(fichier,"%d %d\n",largeur,hauteur);
        for (y = 0; y < hauteur; y++)
        {
            for (x= 0; x < largeur; x++)
            {
                if (image[x][y]=='1')  octet =octet + pds;
                             //fprintf(fichier,"%c\n",image[x][y]);
                pds=(unsigned char)(pds>>1);
                if ((pds==0)|| (x==largeur-1))
                {
                    fprintf(fichier,"%c",octet);
                    octet=0;
                    pds=128;
                }
            }
            octet=0;
            pds=128;
         }
        fclose(fichier);  /* je ferme le fichier */
    return EXIT_SUCCESS;
}