glipper
Messages postés246Date d'inscriptiondimanche 2 juin 2002StatutMembreDernière intervention11 septembre 2016
-
24 févr. 2008 à 03:05
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019
-
24 févr. 2008 à 13:15
Bonjour,
j'essai de lire le header d'un fichier bitmap, et d'en extraire les informations.
Mon programme doit-être portable sur différentes machines, donc j'ai déclaré quelques types à ma façon :
typedef unsigned int BOOL; /* 1-Bit. */
typedef signed char S8; /* 8-Bit Signed. */
typedef unsigned char U8; /* 8-Bit Unsigned. */
typedef signed short S16; /* 16-Bit Signed. */
typedef unsigned short U16; /* 16-Bit Unsigned. */
typedef signed long S32; /* 32-Bit Signed. */
typedef unsigned long U32; /* 32-Bit Unsigned. */
Comme ça, si j'ai bien compris, la taille en octet d'un type ne dépendra plus de la machine.
Ensuite, j'ai déclaré une structure, dont le but est de contenir les informations :
/* Structure d'un en-tête de fichier bitmap */
typedef struct t_bmpHeader{
Enfin, j'ai enregistré le header de mon image :
FILE* pf_bmp;
t_bmpHeader t_headerFile;
pf_bmp = fopen("bitmap.bmp", "rb");
fread(&t_headerFile, 1, sizeof(t_headerFile), pf_bmp);
Et enfin j'essai d'afficher les informations :
printf("signature: %c%c \n", t_str->u8_signature[0], t_headerFile.u8_signature[1]);
printf("taille du fichier en octet: %li \n", t_headerFile.u32_tailleFichierOct);
printf("offset: %li \n", t_headerFile.u32_offset);
...
Mais voilà, ça ne marche pas. Les valeurs obtenus sont fausses, à part pour la signature qui est correcte (BM).
Je me demandais si le problème ne pouvait pas venir de la façon dont sont enregistrées les valeurs (Little endien, big endien...).
En changeant les U32 par des tableaux de U8, ça fonctionne parfaitement. Exemple :
U32 u32_tailleFichierOct; est remplacé par U8 u8_tailleFichierOct[4];
on affiche en écrivant : printf("taille du fichier en octet: %li \n", *(t_headerFile.u8_tailleFichierOct));
J'aimerais bien comprendre quel est le problème, car il me semblerait plus logique d'utiliser directement U32 au lieu d'un tableau de U8.
luhtor
Messages postés2023Date d'inscriptionmardi 24 septembre 2002StatutMembreDernière intervention28 juillet 20086 24 févr. 2008 à 11:09
Ca doit etre lié au padding du compilo. Il réordonne peut être les champs de ta structure pour optimiser la mémoire (je peux me tromper), mais si tu es sur que ta structure est bonne, c'est probablement cela. La solution, c'est soit de désactiver le pagging (je sais pas comment on fait), soit de lire les champs 1 par 1 et non d'un bloc comme tu essais de le faire.
Enfin pour l'histoire du padding, tu peux rapidement regarder si u32_tailleFichierOct est bien 2 octets apres le début de ta structure (et j'imagine que non):
glipper
Messages postés246Date d'inscriptiondimanche 2 juin 2002StatutMembreDernière intervention11 septembre 20161 24 févr. 2008 à 12:59
Merci,
Le problème semblait bien venir de là.
J'ai donc utilisé des U8 partout, et pas de U32 qui décallent les données.
J'ai hésité entre cette solution ou utiliser #pragma mais je me suis dit que désactiver le padding devait jouer sur les performances (je ne sais pas). Sachant que ce programme devrait modifier une image bmp, je voudrais qu'il soit rapide.
Voilà, juste une information pour ceux qui voudraient aussi faire un programme de ce type :
Ne pas oublier de convertir les tableaux de quatre U8 en U32 pour les afficher. Les données des bmp sont en Little Endien (les octets de poids forts sont stoqués à droite des octets de poids faibles)
Merci beaucoup pour votre aide :)
CA MARCHE !!! hihi
----------------------------------------------------------------------------------------
/* conversion d'un tableau de quatre U8 en un nombre U32 */
U32 a_U8toU32(U8* a_in) {
return *a_in + *(a_in+1)*256 + *(a_in+2)*256*256 + *(a_in+3)*256*256*256;
}
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 24 févr. 2008 à 13:15
Le non alignement par #pragma ne change en rien la vitesse tant que tu ne fais pas de lecture ou affectation sur un mauvais alignement, ce qui n'est pas le cas ici pour la lecture des octets d'un entete de fichier.
Multiplications et divisions de puissances de 2 se font avec des << ou >>.