[C] Sprintf et transformation en octet
boelraty
Messages postés
2
Date d'inscription
Statut
Membre
Dernière intervention
-
Mahmah Messages postés 496 Date d'inscription Statut Membre Dernière intervention -
Mahmah Messages postés 496 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
Je suis actuellement en train de travailler sur un programme qui a besoin de créer des fichiers BMP. Pour cela la première chose à faire est de créer le header du fichier.
Pour le moment, je fais des fwrite(&data,2,f) : f étant mon fichier, 2 la longueur en octet et data la donnée par exemple BM pour le type de fichier. Au lieu de faire un fwrite pour chaque élément du header, j'aimerais sauver toute l'entête du fichier dans une variable genre char.
J'ai donc pensé utiliser la fonction sprintf. Le problême c'est que je n'arrive pas à convertir en octet mes variables.
J'ai cela :
sprintf(head, "424D%08X%08X%08X%08X%08X%08X%04X%04X%08X%08X%08X%08X%08X%08X", BMPHeaderLenght, ReservedBit, DataOffset, DataHeaderLenght, width, height, Planes, BPP, Compression, ImageSize, ResX, Resy, ColorUsed, ColorImportant);
Chaque variable est de type int. Les 08 ou 04 correspondent à la taille en octet que je veux pour la variable (4 ou 2). Le problème c'est que je n'obtiens pas le bon résultat. Par ex pour une variable avec la valeur 40, j'ai 00000028 avec le sprintf et dans le fichier j'ai 28000000, c'est pas dans le bon sens.
A part lire la chaîne à l'envers et écrire les valeurs dans l'ordre inverse que puis-je faire ???? Je ne sais pas si les %08X sont adaptés à ce que je veux faire. Et encore c'est pas tellement lire à l'envers, c'est lire à l'envers octet par octet : par ex 0001E036 doit donner 36E00100
Merci pour vos réponses.
Je suis actuellement en train de travailler sur un programme qui a besoin de créer des fichiers BMP. Pour cela la première chose à faire est de créer le header du fichier.
Pour le moment, je fais des fwrite(&data,2,f) : f étant mon fichier, 2 la longueur en octet et data la donnée par exemple BM pour le type de fichier. Au lieu de faire un fwrite pour chaque élément du header, j'aimerais sauver toute l'entête du fichier dans une variable genre char.
J'ai donc pensé utiliser la fonction sprintf. Le problême c'est que je n'arrive pas à convertir en octet mes variables.
J'ai cela :
sprintf(head, "424D%08X%08X%08X%08X%08X%08X%04X%04X%08X%08X%08X%08X%08X%08X", BMPHeaderLenght, ReservedBit, DataOffset, DataHeaderLenght, width, height, Planes, BPP, Compression, ImageSize, ResX, Resy, ColorUsed, ColorImportant);
Chaque variable est de type int. Les 08 ou 04 correspondent à la taille en octet que je veux pour la variable (4 ou 2). Le problème c'est que je n'obtiens pas le bon résultat. Par ex pour une variable avec la valeur 40, j'ai 00000028 avec le sprintf et dans le fichier j'ai 28000000, c'est pas dans le bon sens.
A part lire la chaîne à l'envers et écrire les valeurs dans l'ordre inverse que puis-je faire ???? Je ne sais pas si les %08X sont adaptés à ce que je veux faire. Et encore c'est pas tellement lire à l'envers, c'est lire à l'envers octet par octet : par ex 0001E036 doit donner 36E00100
Merci pour vos réponses.
A voir également:
- [C] Sprintf et transformation en octet
- Transformer une image en icone - Guide
- Transformer majuscule en minuscule word - Guide
- Transformer epub en kindle - Guide
- Transformer clavier qwerty en azerty - Guide
- Transformer prise téléphone en rj45 - Forum câblage
4 réponses
Je ne comprends pas bien ton histoire.
En fait, le fait que ça soit à l'envers m'étonne déjà.
pour moi, le sprintf permet d'écrire du texte dans une variable et fwrite écris en binaire. MAIS une sortie en hexadécimal (donnée par %X) écrit du texte, par exemple si ton entier vaut dix, tu écrira "0A" dans ton texte, ce qui correspond aux entier 55 et 70 (par exemple, je n'ai pas vérifié) ce qui une fois écri en binaire te donnera tout à fait autre chose.
en C, normalement (à vérifier avec sizeof), char vaut 1 octet, int 4, short 2.
Donc, défini un pointeur d'octet : char* head; (Il faut faire attention, char est souvent vu comme un caractère, mais c'est aussi un entier, ce qui m'intéresse ici)
alloue lui la bonne taille, puis rempli le :
*(head + decalage_en_octet)=(short)/* ou int */ variable_a_stoker
En fait, le fait que ça soit à l'envers m'étonne déjà.
pour moi, le sprintf permet d'écrire du texte dans une variable et fwrite écris en binaire. MAIS une sortie en hexadécimal (donnée par %X) écrit du texte, par exemple si ton entier vaut dix, tu écrira "0A" dans ton texte, ce qui correspond aux entier 55 et 70 (par exemple, je n'ai pas vérifié) ce qui une fois écri en binaire te donnera tout à fait autre chose.
en C, normalement (à vérifier avec sizeof), char vaut 1 octet, int 4, short 2.
Donc, défini un pointeur d'octet : char* head; (Il faut faire attention, char est souvent vu comme un caractère, mais c'est aussi un entier, ce qui m'intéresse ici)
alloue lui la bonne taille, puis rempli le :
*(head + decalage_en_octet)=(short)/* ou int */ variable_a_stoker
Bonjour,
Un header de fichier respecte des spécifications qui en pratique permettent bien souvent de faire des structures. Ces structures pourront être écrites facilement dans un fichier avec un fwrite.
EDIT. : exemple FIN EDIT.
L'inversion est normale. C'est la simple différence entre les machines Big Endian et Little Endian. Quand un PC écrira 1 soit 0x00000001 pour un humain en 32 bits, il l'écrira en inversant les octets, soit 01 00 00 00. Un Mac PowerPC écrira 00 00 00 01. C'est comme ça. (voir Endianess sur wikipédia Ainsi, en regardant ton fichier ou tes données avec un éditeur héxa ou la mémoire avec un debuggueur, c'est inversé. Ce n'est pas un bug. ;-) Même un simple int i = 22; est physiquement écrit 16 00 00 00 en mémoire.
M.
Un header de fichier respecte des spécifications qui en pratique permettent bien souvent de faire des structures. Ces structures pourront être écrites facilement dans un fichier avec un fwrite.
EDIT. : exemple FIN EDIT.
L'inversion est normale. C'est la simple différence entre les machines Big Endian et Little Endian. Quand un PC écrira 1 soit 0x00000001 pour un humain en 32 bits, il l'écrira en inversant les octets, soit 01 00 00 00. Un Mac PowerPC écrira 00 00 00 01. C'est comme ça. (voir Endianess sur wikipédia Ainsi, en regardant ton fichier ou tes données avec un éditeur héxa ou la mémoire avec un debuggueur, c'est inversé. Ce n'est pas un bug. ;-) Même un simple int i = 22; est physiquement écrit 16 00 00 00 en mémoire.
M.
exact, une structure est l'idéal. J'avais pensé au bigEndian, mais dans mon souvenir ça changeais AB en BA... (je copierai 100 fois comment fait le big endian en vrai)
Pour en revenir aux structure :
struct A{
int BMPHeaderLenght;short ReservedBit;int DataOffset;...etc
}
et ensuite, pour écrire :
write(&A,sizeof(A),f);
Le souci, c'est qu'en utilisant des structures avec des données alterné comme ça, tu peux avoir des alignements et donc des problèmes d'écriture.
Pour en revenir aux structure :
struct A{
int BMPHeaderLenght;short ReservedBit;int DataOffset;...etc
}
et ensuite, pour écrire :
write(&A,sizeof(A),f);
Le souci, c'est qu'en utilisant des structures avec des données alterné comme ça, tu peux avoir des alignements et donc des problèmes d'écriture.
Ah oui, en effet, il faut surveiller les alignements pour les membres la structure. Il n'y a pas de convention pour le faire mais bon nombre de compilateurs reconnaissent le :
Sinon on doit pouvoir dire à n'importe quel compilateur quel alignement utiliser, mais c'est mieux de le faire localement dans le code quand c'est possible pour éviter de pénaliser toutes les structures/classes du programme.
Merci,
M.
#pragma pack( push, 1 ) // alignement forcé de 1 octet // Déclaration de la variable du type de la structure ... // Ecriture/Lecture ... #pragma pack( pop )
Sinon on doit pouvoir dire à n'importe quel compilateur quel alignement utiliser, mais c'est mieux de le faire localement dans le code quand c'est possible pour éviter de pénaliser toutes les structures/classes du programme.
Merci,
M.