Partage
  • Partager sur Facebook
  • Partager sur Twitter

Parser d'image

Langage C

Sujet résolu
    14 octobre 2022 à 9:55:44

    Bonjour a tous,

    j'essaie de créer un parser d'image me permettant dans un premier tant d'ouvrir un fichier mini PNG et d'afficher certaines information sur l'image, puis ensuite afficher l'image en noir et blanc.

    voici l’énoncé du problème :

    Écrivez un parser lisant un fichier au format Mini-PNG et affichant les informations le concernant
    : largeur et hauteur de l’image, type de pixels.
    Voici le transcript attendu résultant de l’appel de votre programme sur le fichier A.mp :
    % ./Q1 A.mp
    Largeur : 8
    Hauteur : 10
    Type de pixel : 0 (noir et blanc)

    J'ai besoin d'aide de votre part pour y parvenir.

    Merci d'avance

    -
    Edité par vamskhalil 14 octobre 2022 à 10:07:21

    • Partager sur Facebook
    • Partager sur Twitter
      14 octobre 2022 à 10:19:33

      Salut, mini-PNG, c'est PNG ? 

      Car pour récupérer ces données d'un PNG, ça se fait :

      Selon la doc, après la signature du fichier, on a le segment IHDR (que j'ai souligné en vert), 

      En rouge, j'ai souligné le fait que c'est forcément le premier segment : ce qui fait que la position du IHDR est toujours la même.

      Ensuite, comme tu le vois en bas à gauche, le segment IHDR contient tout de suite la largeur et hauteur, puis profondeur de pixel (ce que tu cherches).

      Dans mon exemple, j'ai créé un PNG de 153x139  (ce qui fait en hexa 99 et 8B, qu'on retrouve souligné dans le fichier à partir de l'offset 0x10. Par contre, fait gaffe c'est du big-endian, et nos PC sont little-endian)

      https://web.maths.unsw.edu.au/~lafaye/CCM/video/format-png.htm

      https://www.w3.org/TR/REC-png.pdf

      • Partager sur Facebook
      • Partager sur Twitter

      Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

        14 octobre 2022 à 10:57:59 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


          14 octobre 2022 à 11:06:18

          Salut,

          Tout d'(abord utilise le bouton </> ci dessus pour mettre ton code.

          Ensuite si ça ne compile pas, dis nous les erreurs de compilation

          Sinon je vois déjà qu'un fread avec 4,0 ça va poser soucis : on ne passe pas de 0 à un fread.

          Ensuite, si tu sous Windows, un fichier binaire s'ouvre avec "rb" dans le fopen, pas "r"

          • Partager sur Facebook
          • Partager sur Twitter

          Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

            14 octobre 2022 à 11:19:31 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


              14 octobre 2022 à 11:22:59

              Bonjour,

              Le message qui suit est une réponse automatique activée par un membre de l'équipe de modération. Les réponses automatiques leur permettent d'éviter d'avoir à répéter de nombreuses fois la même chose, ce qui leur fait gagner du temps et leur permet de s'occuper des sujets qui méritent plus d'attention.
              Nous sommes néanmoins ouverts et si vous avez une question ou une remarque, n'hésitez pas à contacter la personne en question par Message Privé.

              Pour plus d'informations, nous vous invitons à lire les règles générales du forum

              Merci de colorer votre code à l'aide du bouton Code

              Les forums d'Openclassrooms disposent d'une fonctionnalité permettant de colorer et mettre en forme les codes source afin de les rendre plus lisibles et faciles à manipuler par les intervenants. Pour cela, il faut utiliser le bouton Code de l'éditeur, choisir un des langages proposés et coller votre code dans la zone prévue. Si vous utilisez l'éditeur de messages en mode Markdown, il faut utiliser les balises <pre class="brush: cpp;">Votre code ici</pre>.

              Merci de modifier votre message d'origine en fonction.

              Liens conseillés

              • Partager sur Facebook
              • Partager sur Twitter
                14 octobre 2022 à 11:33:20

                #include <stdlib.h>
                #include <stdio.h>
                
                
                typedef struct Header{ // bloc entete du fichier image contenant les informations sur les caracteristiques de l'image 
                 int largeur;
                 int hauteur;
                 int typePx;
                }Header;
                
                typedef struct Commentaire{ // il contient le descrptif de l'image 
                	char C;
                }Commentaire;
                
                typedef struct bitmap { // informations permettant d'obtenir le bitmap de l'image 
                	int PxCol;
                	int PxLn;
                }bitmap;
                
                 int Convert (unsigned char hex[4],int nbre){ //Fonction pour convertir de l'hexadecimal au decimal
                 	int result = 0;
                 	int i;
                 	for (i = nbre-1; i>=0; i--)
                	 {
                 		result = result * 256 + hex[i];
                 	 } 
                	return result;	
                 }
                 
                 void lire_fichier (char nomFichier [255]){
                 
                 	unsigned char buffer[4]; // pour stocker temporairement les informations lus 
                 	FILE * fichier = NULL;
                 	
                 	fichier = fopen (nomFichier,"rb");
                 	fread (&Header.largeur,4,1,fichier); // l'erreur est signalée ici 
                 	fread (&buffer,4,1,fichier);
                 	Header.largeur = Convert(buffer,4);
                 	fread(&buffer,4,1,fichier);
                 	fread(&header.hauteur,4,4,fichier);
                 	fread(&buffer,4,5,fichier);
                 	Header.hauteur = Convert(buffer,4);
                 	fread(&buffer,4,5,fichier);
                 	
                 	fclose(fichier);
                 	
                 }
                 
                l'intitulé de l'erreur est :   [Error] expected primary-expression before '.' token
                • Partager sur Facebook
                • Partager sur Twitter
                  14 octobre 2022 à 11:44:49

                  Met la ligne de l'erreur la prochaine fois.

                  Evidemment, Header est une structure, il faut créer une instance de cette structure.

                  Par exemple :

                  Header h;
                  h.largeur = ....



                  • Partager sur Facebook
                  • Partager sur Twitter

                  Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                    14 octobre 2022 à 11:59:58

                    Ok merci,

                    J'essaie d'avancer sur mon code et je vous direz la suite

                    • Partager sur Facebook
                    • Partager sur Twitter
                      14 octobre 2022 à 15:03:10

                      Bonjour. Plus d'infos ici sur le format d'image MiniPNG semble-t-il ...

                      • Partager sur Facebook
                      • Partager sur Twitter
                        14 octobre 2022 à 17:23:29

                        magma a écrit:

                        Bonjour. Plus d'infos ici sur le format d'image MiniPNG semble-t-il ...


                        On dirait même l'énoncé de l'exercice que le PO doit faire.:lol:
                        Donc on oublie la structure PNG évoquée plus haut, on applique le principe selon les données de l'exercice. (ça ressemble quand même un peu au PNG)

                        -
                        Edité par umfred 14 octobre 2022 à 17:23:42

                        • Partager sur Facebook
                        • Partager sur Twitter
                          14 octobre 2022 à 18:25:28

                          Hello,

                          buffer est assimilé à un pointeur. Tu ne dois donc pas passer son adresse à fread() lignes 37, 39, 41 et 43.

                          Edit : Oouups. En relisant le post, lignes 41 et 43 tu vas lire 20 bytes dans une variable qui ne peut en contenir que 4. Too bad.

                          -
                          Edité par edgarjacobs 14 octobre 2022 à 19:30:12

                          • Partager sur Facebook
                          • Partager sur Twitter

                          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                            14 octobre 2022 à 20:14:03

                            Les accidents sont plus rares si on définit des constantes, et/ou qu'on utilise sizeof

                            #define BUFFER_SIZE 4
                            
                            unsigned char buffer[BUFFER_SIZE];
                            
                            fread(&buffer, BUFFER_SIZE, 1, fichier);
                            
                            



                            • Partager sur Facebook
                            • Partager sur Twitter
                              17 octobre 2022 à 9:40:08

                              Bonjour à tous.

                              merci a tous ceux qui m'ont répondu, c'est cool.

                              umfred et magma oui c'est exactement le même projet que je dois faire alors si vous l'avez déjà réaliser merci de m'aider

                              je vais essayer de corriger pour l'utilisation du buffer.

                              mais c'est une question : Si je demande a un utilisateur de mon programme de rentrer un fichier image dois je utiliser une fonction speciale pour le permettre a mon prog de charger le fichier ou un scanf/fgets sera suffisant pour recuperer le fichier

                              -
                              Edité par vamskhalil 17 octobre 2022 à 10:06:49

                              • Partager sur Facebook
                              • Partager sur Twitter
                                17 octobre 2022 à 11:32:23

                                A signaler : bug dans l'énoncé.

                                Si on dit qu'un segment PNG  est composé

                                • d'une taille
                                • d'un type
                                • de données
                                • d'un CRC
                                alors il faut dire que la taille indiquée est celle des données, et pas celle du segment.
                                Exemple, 13 pour un IDHR.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  17 octobre 2022 à 12:38:39

                                  Je ne vois pas ce "bug" dans l'énoncé de l'exercice (qui utilise du mini-PNG et non du PNG).
                                  Pour moi, il y a pour chaque bloc 5 octets à lire dans un 1er temps:

                                  • le 1er octet indiquant le type de bloc et donc le type d'info contenu dans les données du bloc
                                  • les 4 octets suivants qui détermine la longueur l des données à lire ensuite

                                  Et donc dans un second temps, lire l octets de données à interpréter selon le type du bloc, et rien ne dit que les blocs sont dans l'ordre Header > Commentaire > Données

                                  Puis ensuite continuer de lire les blocs jusqu'à la fin du fichier.

                                  Pour le nom du fichier, il est dit qu'il sera passer par la ligne de commande, donc a priori, le nom du fichier est récupérable dans les paramètres du main.
                                  Le nom du fichier est une chaine de caractères, à ne pas confondre avec le fichier lui-même.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    17 octobre 2022 à 14:34:06

                                    Exact, ce n'est pas dans l'énoncé  mais dans la première réponse. C'est le texte présenté sur la capture d'écran qui décrit, de travers, le format png.

                                    https://web.maths.unsw.edu.au/~lafaye/CCM/video/format-png.htm

                                    -
                                    Edité par michelbillaud 17 octobre 2022 à 14:36:58

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      17 octobre 2022 à 20:43:47

                                      vamskhalil a écrit:

                                      mais c'est une question : Si je demande a un utilisateur de mon programme de rentrer un fichier image dois je utiliser une fonction speciale pour le permettre a mon prog de charger le fichier ou un scanf/fgets sera suffisant pour recuperer le fichier

                                      Ces deux fonctions sont orientées char *. Si tu veux lire un fichier dont tu ne connais pas à priori le contenu, fread() est nécessaire. Spécialement dans le cas de fichiers image, vidéo, bref de données dans le sens le plus large du mot, ceux qui contiennent des caractères non-human readable.

                                      -
                                      Edité par edgarjacobs 17 octobre 2022 à 20:45:22

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                                        18 octobre 2022 à 13:01:44

                                        Pour ceux qui veulent un exemple de fichier mini-PNG utilisé par le sujet > https://paperstreet.picty.org/POS/  paragraphe "TP noté"
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          21 octobre 2022 à 9:54:53

                                          Bonjour a tous,

                                          encore merci pour toutes vos réponse qui m'aide a comprendre et a avancer.

                                          le projet sur lequel je bosse en ce moment est bien celui -ci : http://paperstreet.picty.org/POS/minipng/minipng.pdf

                                          vu que je n'ai pas une très grande expérience en programmation je galère énormément .

                                          j'ai écrit ce bout de code pour essayer de répondre a la première question du projet mais je n'arrive pas a avoir le résultat voulu.

                                          Alors j'en appelle aux expert pour voir ce qui ne cloche pas

                                          #include <stdlib.h>
                                          #include <stdio.h>
                                          #include <math.h>
                                          #include <time.h>
                                          
                                          #define BUFFER_SIZE 4
                                          
                                          
                                          typedef struct Header{ // bloc entete du fichier image contenant les informations sur les caracteristiques de l'image 
                                           int largeur;
                                           int hauteur;
                                           int typePx;
                                          }Header;
                                          
                                          typedef struct Commentaire{ // il contient le descrptif de l'image 
                                          	char C;
                                          }Commentaire;
                                          
                                          typedef struct bitmap { // informations permettant d'obtenir le bitmap de l'image 
                                          	int PxCol;
                                          	int PxLn;
                                          }bitmap;
                                          
                                           int Convert (unsigned char hex[4],int nbre){ //Fonction pour convertir de l'hexadecimal au decimal
                                           	int result = 0;
                                           	int i;
                                           	for (i = nbre-1; i>=0; i--)
                                          	 {
                                           		result = result * 256 + hex[i];
                                           	 } 
                                          	return result;	
                                           }
                                          
                                           void lire_fichier (char nomFichier [255]){
                                           
                                           	unsigned char buffer[BUFFER_SIZE]; // pour stocker temporairement les informations lus 
                                           	FILE * fichier = NULL;
                                           	Header h;
                                           	 
                                           	
                                           	 if ( (fichier = fopen(nomFichier, "rb")) == NULL ) {
                                                   printf("Je ne peux pas ouvrir %s", nomFichier);
                                                   exit(1);
                                              }
                                              else {
                                          	
                                           	
                                           	fread (&h.largeur,4,1,fichier);
                                           	fread (&buffer,BUFFER_SIZE,1,fichier);
                                           	h.largeur = Convert(buffer,BUFFER_SIZE);
                                           	fread(&buffer,BUFFER_SIZE,1,fichier);
                                           	
                                           	fread(&h.hauteur,4,4,fichier);
                                           	fread(&buffer,BUFFER_SIZE,5,fichier);
                                           	h.hauteur = Convert(buffer,BUFFER_SIZE);
                                           	fread(&buffer,BUFFER_SIZE,5,fichier);
                                           	
                                           	fread(&h.typePx,1,8,fichier);
                                           	fread(&buffer,BUFFER_SIZE,8,fichier);
                                           	h.typePx = Convert(buffer,BUFFER_SIZE);
                                           	fread(&buffer,BUFFER_SIZE,8,fichier);
                                           	
                                           	fclose(fichier);
                                           	}
                                           }
                                           
                                          
                                          int main(int argc, char *argv[]){
                                          
                                          char nomFichier [255];
                                           Header h;
                                             printf("Entrer un fichier: ");
                                             fgets (nomFichier,255,stdin);
                                             lire_fichier("nomFichier");
                                             
                                             printf("la largeur de l'image est : %d\n",h.largeur);
                                             printf("la hauteur de l'image est : %d\n",h.hauteur);   
                                             printf("la largeur de l'image est : %d\n",h.largeur);
                                             printf("le type de pixel est : %d\n",h.typePx);	
                                          	
                                          return 0;
                                          }



                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            21 octobre 2022 à 10:20:17

                                            Reprends la description du fichier: le fichier commence par la chaine "Mini-PNG" donc 8 caractères (octets) pour le type du fichier; je ne vois pas cette lecture.

                                            Ensuite tu as 5 octets pour définir le bloc (1 octet pour le type de bloc et 4 pour la longueur L du contenu du bloc) et ensuite tu as le contenu du blocs (L octets) et ce contenu est interprété selon le type de bloc. (rien ne dit que le bloc Header vient tout de suite après "Mini-PNG")

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              21 octobre 2022 à 10:39:05

                                              Bonjour,

                                              Donc tu suis un parcours en "Fondements de l'informatique et ingénierie du logiciel".

                                              La première chose à faire avant même de pisser du code (en C ou quelqu'autre langage) est de bien lire le sujet et une fois qu'on a compris ce qu'on attend de toi de commencer par faire ressortir ce dont tu vas avoir besoin.

                                              En très gros et après une lecture en diagonal, il apparaît que tu vas devoir pouvoir lire et écrire un fichier qui a un certain format. C'est un format par bloc, il en existe 3 différents (H, C et D).

                                              Cela peut être une bonne idée de se dire que tu vas avoir besoin d'une structure représentant un bloc, que celui-ci aura un «type» particulier. Ici je mets type entre guillemets car il ne s'agit pas d'un type au sens «type de données C» mais plus d'un genre.

                                              On peut imaginer quelque chose comme :

                                              enum mp_chunk_kind { 
                                                  MP_HEADER='H',
                                                  MP_COMMENT='C',
                                                  MP_DATA='D'
                                              };
                                              
                                              struct mp_chunk_description {
                                                  mp_chunk_kind kind;
                                                  uint32_t size;
                                              };
                                              
                                              struct mp_chunk_header {
                                              …
                                              };
                                              
                                              struct mp_chunk_comment {
                                              …
                                              };
                                              
                                              struct mp_chunk_data {
                                              …
                                              };
                                              
                                              struct mp_chunk {
                                                  mp_chunk_description description;
                                                  union {
                                                      struct mp_chunk_header header;
                                                      struct mp_chunk_comment comment;
                                                      struct mp_chunk_data data;
                                                  } content;
                                              };
                                              

                                              Ensuite il va te falloir écrire/lire un fichier. Une petite API dédiée serait également une bonne idée :

                                              struct MPFILE {
                                                  mpfile_status status;
                                                  int fd;
                                                  …
                                              };

                                              qui va contenir un peu tout ce dont tu auras besoin pour les IO. Le champ status va décrire l'état = en gros tout est OK ou erreur d'accès, fichier invalide (=non mini png), fin de fichier atteinte, erreur en lecture, …

                                              Mais bon, ça c'est un peu de la tambouille interne. Parce  que ton programme va vraiment devoir manipuler n'est pas un fichier mais une image. Il te faut donc quelque chose qui va représenter une image :

                                              struct mp_image {
                                                  uint32_t width;
                                                  uint32_t height;
                                                  mp_image_kind kind;
                                                  uint8_t *data;
                                              };

                                              C'est vraiment cela que tu vas devoir manipuler dans ton main.

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                21 octobre 2022 à 10:59:09

                                                umfred, effectivement j'ai corrigé le compte en tenant compte de tes remarques mais j'ai un décalage dans la lecture des bits comme si je reprenais le dernier bit de la precedente donnée.

                                                voici le code et ce que ca donne a l'execution

                                                #include <stdio.h>
                                                #include <stdlib.h>
                                                
                                                /* run this program using the console pauser or add your own getch, system("pause") or input loop */
                                                int hex2dec (unsigned char hex[4],int nombre) //Fonction permettant de convertir un nombre hexa
                                                {					      //en décimal (plus facile à lire)
                                                	int resultat = 0;
                                                	int i;
                                                
                                                	for (i = nombre - 1; i >= 0; i--)
                                                	{
                                                		resultat = resultat * 256 + hex[i];
                                                	}
                                                	return resultat;
                                                }
                                                
                                                struct header{
                                                	char d[8];
                                                	char tb;
                                                	int Lb;
                                                	int lb;
                                                	int hb;
                                                	int tp;
                                                	char ascii[255];
                                                	
                                                	
                                                }h;
                                                
                                                void lire_fichier (char nom[255])
                                                {
                                                	unsigned char temp[8];
                                                	//Zone mémoire temporaire où on stoque ce qui est lu dans le fichier avant
                                                	FILE * fichier;        //de le traiter.
                                                
                                                	fichier = fopen (nom,"rb");
                                                
                                                	fread (&temp,8,1,fichier); 
                                                	h.d[0]=temp[0];
                                                	h.d[1]=temp[1];
                                                	h.d[2]=temp[2];
                                                	h.d[3]=temp[3];
                                                	h.d[4]=temp[4];
                                                	h.d[5]=temp[5];
                                                	h.d[6]=temp[6];
                                                	h.d[7]=temp[7];
                                                	fread (&temp,1,1,fichier);
                                                	h.tb=temp[0];
                                                	fread (&temp,4,1,fichier);
                                                	h.Lb=hex2dec(temp,4);
                                                	fread (&temp,4,1,fichier);
                                                	h.lb=hex2dec(temp,4);
                                                	fread (&temp,4,1,fichier);
                                                	h.hb=hex2dec(temp,4);
                                                	
                                                	
                                                
                                                	//Si c'est un image 8 bit, cette entête est suivie de la palette.
                                                        //Après la palette, ce sont les données de l'image
                                                	
                                                	fclose (fichier);
                                                }
                                                
                                                int main(int argc, char *argv[]) {
                                                	lire_fichier ("A.mp"); 
                                                    printf ("type de bloc1 : %s\n",h.d);
                                                	printf ("type de bloc : %c\n",h.tb);
                                                	printf ("Longueur du bloc : %d\n",h.Lb);
                                                	printf ("largeur du bloc : %d\n",h.lb);
                                                	printf ("hauteur du bloc : %d\n",h.hb);
                                                	
                                                	
                                                
                                                
                                                
                                                
                                                	return 0;
                                                }



                                                -
                                                Edité par vamskhalil 22 octobre 2022 à 18:04:56

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  21 octobre 2022 à 13:11:19

                                                  Bonjour,

                                                  ta fonction hex2dec() lit les nombres à l'envers (le dernier octet lu est *256*256*256 alors que ça devrait être le premier).
                                                  Les valeurs lues valent respectivement: 9, 8 et 10

                                                  -
                                                  Edité par Dalfab 21 octobre 2022 à 13:12:15

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  En recherche d'emploi.

                                                    21 octobre 2022 à 17:08:43

                                                    Bon, on va prendre ça calmement.

                                                    Quand on fait un projet comme ça, il ne faut pas s'imaginer qu'on va écrire directement le code du truc qu'on va rendre.  Avant ça, il faut explorer un peu, d'une part parce qu'on ne comprend pas complètement le problème, d'autre part parce qu'on ne connait pas bien les moyens pour le programmer.

                                                    Ca fait toujours marrer quand les débutants arrivent avec "je galère, j'y arrive pas, je suis débutant". Ben tiens, évidemment.  Déjà, quand on n'est pas débutant, la solution ne tombe pas du ciel non plus. Faut essayer des trucs avant de se lancer dans le programme demandé.

                                                    Bon, idée : on écrit un programme qui fait afficher les informations d'un fichier qui est au format demandé. Pour A.mp, ça donnerait

                                                    Magic number:   Mini-PNG
                                                    bloc type H taille 9
                                                    - Image 8 x 10, pixels 0 - noir et blanc
                                                    bloc type C taille 11
                                                    - Commentaire: La lettre A
                                                    bloc type D taille 10

                                                    Le main, cherchons pas la complication

                                                    int main()
                                                    {
                                                        traiter_fichier("A.mp");
                                                        return EXIT_SUCCESS;
                                                    }

                                                    Dans une version améliorée, on ferait une boucle sur argc/argv pour traiter plusieurs fichiers. Mais peu importe, concentrons-nous sur le traitement du fichier.

                                                    Pour traiter le fichier, on l'ouvre, on lit le "magic number" et les blocs

                                                    void traiter_fichier(const char *chemin)
                                                    {
                                                        int fd = open(chemin, O_RDONLY);
                                                        if (fd < 0) {
                                                            perror("ouverture fichier");
                                                            exit (EXIT_FAILURE);
                                                        }
                                                        traiter_magic_number(fd);
                                                        traiter_blocs(fd);
                                                        close(fd);
                                                    }

                                                    J'ai préféré les fichiers bas niveau, si vous voulez des FILE*/fopen/fread/... vous faites comme vous voulez profitez-en on est en république tant que c'est pas moi le chef.

                                                    Pour le magic number, on doit lire 8 octets dans le fichier, on utilise un tampon de 9 pour en faire une chaine à la C

                                                    void traiter_magic_number(int fd)
                                                    {
                                                        char chaine[8 + 1];
                                                        read(fd, chaine, 8);
                                                        chaine[8] = '\0';
                                                        printf("Magic number:\t%s\n", chaine);
                                                    }

                                                    Pour traiter les blocs, il faut faire une boucle, parce qu'il y en a plusieurs. Dans la boucle, on essaie de lire l'entete de bloc et si ça marche, on lit et on traite les données du bloc.


                                                    struct entete_bloc {
                                                        char type;
                                                        int taille_contenu;
                                                    };
                                                    
                                                    
                                                    void traiter_blocs(int fd)
                                                    {
                                                        while (true) {
                                                            struct entete_bloc h;
                                                            if (! traiter_entete_bloc(fd, &h))  break;
                                                            printf("bloc type %c taille %d\n", h.type, h.taille_contenu);
                                                            traiter_contenu_bloc(fd, &h);
                                                        }
                                                    }


                                                    L'entete du bloc c'est sur 5 octets, dont 1 pour le type et 4 pour un entier qu'il faut décoder

                                                    int valeur_entier(const char octets[], int taille)
                                                    {
                                                        int valeur = 0;
                                                        for (int i=0; i < taille; i++) {
                                                            valeur = (valeur << 8) | octets[i];
                                                        }
                                                        return valeur;
                                                    
                                                    }
                                                    
                                                    bool traiter_entete_bloc(int fd, struct entete_bloc *h)
                                                    {
                                                        char data[1 + 4];
                                                        int n = read(fd, data, 5);
                                                        if (n <= 0) return false;     // y en a plus
                                                        h->type = data[0];
                                                        h->taille_contenu = valeur_entier(data + 1, 4);
                                                        return true;                  // y en a
                                                    }
                                                    

                                                    Rappel : tableau + indice,  ça donne l'adresse de tableau[indice]. 

                                                    Maintenant la lecture et le traitement du bloc : on alloue dynamiquement un tampon de la taille voulue, on y met les données prises dans le fichier, on les traite, et on n'oublie pas de rendre le tampon (ici on ne s'en sert plus, donc on évite la fuite mémoire)

                                                    void traiter_contenu_bloc(int fd, const struct entete_bloc *h)
                                                    {
                                                        char *data = malloc(h->taille_contenu);
                                                    
                                                        read(fd, data, h->taille_contenu);
                                                    
                                                        // traitement à détailler selon le type
                                                        switch (h->type) {
                                                        case 'H' :
                                                            afficher_caracteristiques(data);
                                                            break;
                                                        case 'C' :
                                                            afficher_commentaire(data, h->taille_contenu);
                                                            break;
                                                        default:
                                                            break;
                                                        }
                                                        free(data);
                                                    }
                                                    



                                                    Les données d'un bloc de commentaires, c'est du texte, mais pas contenu dans une chaine avec un terminateur. Une solution, c'est de l'afficher par fwrite

                                                    void afficher_commentaire(const char *data, int taille)
                                                    {
                                                        printf("- Commentaire: ");
                                                        fwrite(data, taille, 1, stdout);
                                                        printf("\n");
                                                    }

                                                    et pour le bloc d'entête c'est pas compliqué non plus, grâce à la fonction de conversion   4 octets -> entier

                                                    void afficher_caracteristiques(const char *data)
                                                    {
                                                        static const char *type_pixels[] = {
                                                            "0 - noir et blanc",
                                                            "1 - niveaux de gris",
                                                            "2 - palette",
                                                            "3 - couleurs 14 bits"
                                                        };
                                                        printf("- Image %d x %d, pixels %s\n",
                                                               valeur_entier(data + 0, 4),
                                                               valeur_entier(data + 4, 4),
                                                               type_pixels[(int) data[8]]);
                                                    }
                                                    • Quelques includes au début du fichier, et ça roule.
                                                    • A tester sur plusieurs fichiers

                                                    Etape d'aprés :

                                                    • sauvegarder précieusement ce qui a été fait dans l'étape exploratoire.
                                                    • En faire une copie et la bidouiller pour que ça réponde aux questions, une par une.


                                                    IMPORTANT : sécuriser. Par exemple,

                                                    • pour chaque read, vérifier que le nombre de caractères lus correspond à ce qui était demandé.
                                                    • vérifier le magic number
                                                    • vérifier les champs qui ont des valeurs contraintes : types des blocs / types de pixel ...


                                                    Ne nous cachons pas la vérité : le choix du langage C va conduire au maximum d'emmerdements, en l'absence de mécanisme de gestion des erreurs (exceptions par exemple).


                                                    -
                                                    Edité par michelbillaud 21 octobre 2022 à 17:18:43

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      21 octobre 2022 à 17:54:28

                                                      Retélécharge le fichier A.mp peut-être aussi;

                                                      J'avais fait des essais concluants de code hier sur un compilateur en ligne (https://www.onlinegdb.com/online_c_compiler) mais aujourd'hui j'avais des valeurs comme les tiennes, le fichier A.mp enregistré sur le site avait été altéré (tous les octets nuls ont été supprimés, ce qui me faussait la lecture :colere:)

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        21 octobre 2022 à 19:09:55

                                                        vamskhalil a écrit:

                                                        -
                                                        Edité par vamskhalil il y a environ 8 heures

                                                        Voyons

                                                        $ echo $((9*256*256*256))
                                                        150994944
                                                        
                                                        $ echo $((8*256*256*256))
                                                        134217728
                                                        
                                                        $ echo $((10*256*256*256))
                                                        167772160
                                                        

                                                        COMME PAR HASARD.

                                                        Donc calcul fait à l'envers pour l'évaluation du nombre de 4 octets.

                                                        -
                                                        Edité par michelbillaud 21 octobre 2022 à 19:12:05

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          22 octobre 2022 à 21:13:19

                                                          Bonjour a tous,

                                                          merci pour les retours.

                                                          je crois que j'avance tout doucement faire l'objectif de ce projet, mais j'ai toujours besoin du regard éclairé des experts.

                                                          je vous montre ce que j'ai finalement réussi a faire en utilisant des fonctions plus adaptées a mes besoins mais il y a quand même des aspects qui me chiffonne une peu

                                                          #include <stdlib.h>
                                                          #include <stdio.h>
                                                          
                                                          #define S_SIZE 9 // taille du tableau contenant la signature 
                                                          
                                                          
                                                          struct Header{ // bloc entete du fichier image contenant les informations sur les caracteristiques de l'image
                                                          // char signature[S_SIZE]; // Pour la signature de l'image 
                                                          // char typeBloc; 
                                                           int largeur;
                                                           int hauteur;
                                                           char typePx;
                                                          }H;
                                                          
                                                           struct Commentaire{ // il contient le descrptif de l'image 
                                                          	char C[12];
                                                          }Comment;
                                                          
                                                           struct bitmap { // informations permettant d'obtenir le bitmap de l'image 
                                                          	int PxCol;
                                                          	int PxLn;
                                                          }bmp;
                                                          
                                                           
                                                           
                                                          
                                                           void lire_fichier (char nomFichier [255]){
                                                           
                                                           	FILE * fichier = NULL;
                                                           	
                                                           	 if ( (fichier = fopen(nomFichier, "rb")) == NULL ) {
                                                                   printf("Je ne peux pas ouvrir %s", nomFichier);
                                                                   exit(1);
                                                              }
                                                              else {
                                                          	
                                                           	
                                                          // 	fseek (fichier,0,SEEK_SET); // lire la signature du fichier 
                                                          // 	fgets (H.signature,S_SIZE,fichier);
                                                          // 	
                                                          // 	
                                                          //	fseek(fichier,8,SEEK_SET);  // lire de type de bloc 
                                                          // 	H.typeBloc = fgetc(fichier);
                                                           
                                                           	fseek(fichier,16,SEEK_SET); // lire la largeur de l'image 
                                                           	H.largeur = fgetc(fichier);
                                                           	
                                                           	fseek(fichier,20,SEEK_SET); // lire la hauteur de l'image 
                                                           	H.hauteur = fgetc(fichier);
                                                           	
                                                           	fseek(fichier,21,SEEK_SET); // lire le type de pixel  
                                                           	H.typePx = fgetc(fichier);
                                                           	
                                                           	fseek(fichier,27,SEEK_SET);
                                                           	fgets(Comment.C,12,fichier); // lire le commentaire de l'image 
                                                           	
                                                           	
                                                           	fclose(fichier);
                                                           	}
                                                           }
                                                           
                                                          
                                                          int main(int argc, char *argv[]){
                                                          
                                                          
                                                             lire_fichier("A.mp");
                                                             
                                                          //   printf("la signature du fichier est : %s\n",H.signature);
                                                          //   printf("le type de bloc est : %c\n",H.typeBloc);
                                                             printf("la largeur de l'image est : %d\n",H.largeur);
                                                             printf("Le nombre d'octets de la largeur de l'image est : %d\n\n",sizeof(H.largeur));
                                                             printf("la hauteur de l'image est : %d\n",H.hauteur); 
                                                             printf("Le nombre d'octets de la hauteur de l'image est : %d\n\n",sizeof(H.hauteur));
                                                             printf("le type de pixel est : %d (noir et blanc)\n",H.typePx);
                                                             printf("Le nombre d'octets du type de pixels est : %d\n\n",sizeof(H.typePx));
                                                             printf("Commentaire : %s\n",Comment.C);
                                                             printf("Le nombre d'octets du commentaire est : %d\n\n",sizeof(Comment.C));
                                                          	
                                                          return 0;
                                                          }

                                                          j'ai fait les 3 premières questions du projet mais mes préoccupations sont les suivantes :

                                                          - au niveau du commentaire j'ai fait quelque chose qui ne me satisfait pas je veux quelque de plus universel

                                                          - pour le test a faire pour verifier les tailles j'ai juste utilisé sizeof mais je me demande si c'est vraiment ce que je devais faire

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            22 octobre 2022 à 21:46:21

                                                            Est ce que tous les commentaires contiennent 12 caractères ?
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              23 octobre 2022 à 17:39:28

                                                              michelbillaud

                                                              Non justement,mais quand je ne met pas mon tableau a 12, il me prend tout ce qui vient derriere, donc je ne sais pas trop comment faire pour l'instant

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Parser d'image

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown