IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Lecture d'adresse et positionnement


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Lecture d'adresse et positionnement
    Bonjour à tous,

    me penchant sur la manipulation de fichiers images (bitmap), je cherche à positionner le curseur du fichier à la bonne adresse afin de récupérer une certaine plage d'octets (correspondant aux pixels de l'image). Pour cela, j'essaie de coder une fonction visant à ouvrir le fichier image, récupérer l'offset du 1er pixel et positionner mon curseur à cette adresse:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
    void ouverture_image(char* path, FILE* fichier_image, char buffer_pixels[]){
            size_t cpt;
     
            /* ouverture du fichier image en lecture */
            fichier_image = fopen(path, "r");
            if (fichier_image == NULL){
                    fprintf(stderr, "erreur ouverture fichier image\n");
                    exit(1);
            }
     
     
            /* l'offset du 1er pixel est donné par les bits 10, 11, 12 et 13 de l'en-tête du fichier image */
            cpt = fseek(fichier_image, 9, SEEK_SET);
     
            /* récupération de l'offset du 1er pixel */
            long offset;
            cpt = fread(&offset, 8, 1, fichier_image);
     
            if (cpt >= 1){
                    int pos;
                    printf("OFFSET: (hex) %lx \t (dec) %ld \n", offset, offset);
     
                    /* positionnement du curseur sur le 1er pixel */
                    fseek(fichier_image, offset, SEEK_SET);
            }
            else printf("erreur lecture offset");
    }
    voici l'en-tête (en hexadécimal big-endian) du fichier bitmap sur lequel j'ai testé mon programme:

    0000000 4d42 0038 0024 0000 0000 0036 0000 0028
    0000010 0000 0400 0000 0300 0000 0001 0018 0000
    0000020 0000 0002 0024 0b12 0000 0b12 0000 0000
    0000030 0000 0000 0000 0707 0707 0707 0707 0707
    0000040 0707 0707 0707 0707 0707 0707 0707 0707

    en gras l'offset du 1er pixel de l'image: le 36eme octet (0x36),
    en souligné le 1et octet du 1er pixel.

    Et voici l'affichage produit lorsque je teste mon programme sur ce fichier:

    OFFSET: 3600 13824

    Mon problème est le suivant, pour positionner mon curseur sur le 1er pixel, la ligne de code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     // Prototype: fseek(FILE*, long, int)
    fseek(fichier_image, offset, SEEK_SET);
    n'offre pas le résultat attendu vu qu'offset est considéré comme un long (= 13824) au lieu d'être considéré comme une adresse (0x36).

    Comment faire pour remédier à ce problème?


    Merci à tous pour votre attention,
    Heisen.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            /* l'offset du 1er pixel est donné par les bits 10, 11, 12 et 13 de l'en-tête du fichier image */
            cpt = fseek(fichier_image, 9, SEEK_SET);
    - Le commentaire est incorrect
    - pourquoi 9 et pas 10 ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            /* l'offset du 1er pixel est donné par les bytes 10, 11, 12 et 13 de l'en-tête du fichier image */
            cpt = fseek(fichier_image, 10, SEEK_SET);

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            cpt = fread(&offset, 8, 1, fichier_image);
    - pourquoi 8 alors que la donnée sur le fichier ne fait que 4 bytes ?

  3. #3
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Bonjour Diogene,

    - pourquoi 9 et pas 10 ?
    pensant que le 1er octet était l'octet n°0, j'en ai conclu que le 10eme serait le n°9; mon approche est-elle fausse?

    - pourquoi 8 alors que la donnée sur le fichier ne fait que 4 bytes ?
    je crois que ceci est une pure faute d'inattention..


    Un internaute, après avoir corriger mes erreurs également, m'a conseillé d'utiliser certaines structures pour résoudre mon problème:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     1
    struct bmpfile_magic {
      unsigned char magic[2];
    };
     
    struct bmpfile_header {
      uint32_t filesz;
      uint16_t creator1;
      uint16_t creator2;
      uint32_t bmp_offset;
    };
    c'est la solution que je compte expérimenter, qu'en pensez-vous?

    Merci de votre attention,
    Heisen.

  4. #4
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    91
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 91
    Points : 115
    Points
    115
    Par défaut
    Bonjour,

    Si la solution consiste à récupérer les données d'en-tête sous forme d'une structure en un seul bloc, sache que cela n'est pas portable.

    En effet, les membres d'une structure ne sont pas forcément alignés en mémoire les uns à la suite des autres, mais des bit dit "de bourrage" peuvent être ajoutés suivant les machines (pour des raisons de performance).

    Pour ton problème de positionnement du curseur, je suggère avant tout que tu utilises le mode d'ouverture approprié pour des manipulations en mode binaire, à savoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fichier_image = fopen(path, "rb");

  5. #5
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    pensant que le 1er octet était l'octet n°0, j'en ai conclu que le 10eme serait le n°9; mon approche est-elle fausse?
    Sauf erreur de ma part, si le premier byte du fichier est le n° 0, le premier byte de l'offset est le N° 10 (et est donc le 11° byte du fichier)

  6. #6
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    merci pour vos indications,

    par pure curiosité, existe-t-il une solution portable ?

    Je vais me renseigner sur les différents mode d'ouverture d'un fichier, et poserai de nouvelles questions si besoin en est

    merci encore
    Heisen

  7. #7
    Membre éclairé
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Points : 750
    Points
    750
    Par défaut
    Quelques remarques:
    • pour la portabilité (architecture, pas OS/compilo), si tu as gcc tu peux utiliser __attribute__((__packed__)) pour forcer gcc à ne pas mettre de padding. Tu peux donc déclarer ta structure comme suit:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      struct bmpfile_header {
        unsigned char magic[2];
        uint32_t filesz;
        uint16_t creator1;
        uint16_t creator2;
        uint32_t bmp_offset;
      } __attribute__((__packed__));
      Pour t'assurer du truc, tu peux vérifier que sizeof(struct bmpfile_header) == 14
    • si ta machine est en big-endian, il faut changer d'endianness (avec le32toh() et consorts (dans endian.h)), car le format BMP est en little-endian (cf. la page wikipedia (anglais) où tu as repris les définitions des headers ).
    • le FILE *devrait être local (ou alors il manque une *)
    • const char * serait plus approprié pour path

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 380
    Points : 41 576
    Points
    41 576
    Par défaut
    Note: sous Visual Studio et MinGW, tu as les structures BITMAPFILEHEADER et BITMAPINFOHEADER qui contiennent les champs à la bonne taille et avec le bon alignement.

Discussions similaires

  1. [Tableaux] lecture de l'adresse
    Par teac2006 dans le forum Langage
    Réponses: 2
    Dernier message: 25/04/2008, 18h34
  2. Lecture de fonction &Positionnement
    Par Debault dans le forum Delphi
    Réponses: 4
    Dernier message: 03/08/2006, 17h07
  3. Positionnement lors de la lecture d'un resultSet
    Par salome dans le forum Langage SQL
    Réponses: 5
    Dernier message: 02/08/2006, 21h35
  4. [LG]Lecture de fichier avec une adresse internet
    Par forbin dans le forum Langage
    Réponses: 8
    Dernier message: 09/02/2005, 19h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo