Problème de type: Pixel =int, char ?

Problème de type: Pixel =int, char ? - C - Programmation

Marsh Posté le 04-04-2007 à 12:44:33    

Salut,
 
Je fais un programme de stéganographie. Je dois donc coder les 8 bits d'un char dans 8 Pixels successfis (en modifiant leur bit de poid faible).
 
Les Pixels d'image sont stockés dans un tableau de unsigned char.
Je fais plusieurs opérations logiques pour manipuler les bits, par exemple: unsigned char c = caractere & 0xFE;
 
Et la apparait un problème:
 
1/ Si je fais putchar(c), j'ai systématiquement un point d'interrogation...
 
2/ Si j'affiche en tant que "int" j'ai certains nombres dans mon tableau. Donc la je fais un fwrite pour tout reécrire dans une image (image codée), mais les valeurs des pixels (que j'affiche avec od -c image.pgm) ne correspondent pas à celle du tableau.
 
Quelqu'un peut-il m'expliquer comment ca se passe réellement ? J'ai l'impression que le type char pose problème et je comprend pas trop...
 
Merci d'avance

Reply

Marsh Posté le 04-04-2007 à 12:44:33   

Reply

Marsh Posté le 04-04-2007 à 13:24:40    

Bonjour,
 
La question n'est pas très claire, parce qu'elle manque d'exemples, et parce que le vocabulaire ne parait pas très bien choisi.
Qu'est-ce qu'un pixel pour vous ? Théoriquement, c'est un point lumineux. Mais dans votre question, il semble que vous emplyer ce mot au lieu de "un charactère imprimable contenant une valeur booléenne". Putchar(), fwrite() ne vous doneront jamais de points lumineux. Il vous donneront des charactères. Quelle valeur booléenne voulez-vous obtenir ? Si vous voulez "0xFE", alors ce n'est pas un caractère imprimable et vous aurez un point d'interrogation à la place.
 
Si je ne me trompe pas, je devine que vous voulez faire les transformations suivantes :
 
Entrée Sortie
0 --> "00000000" = 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
1 --> "00000001" = 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,
2 --> "00000010" = 0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x30,
3 --> "00000011" = 0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,
...
255 --> 11111111
 
En entré ce serait un unsigned char, et en sortie ce serait 8 char ou 8 unsigned char contenant soit "0", soit "1".
Pour infos, le code pour "0" est 0x30. Le code pour "1" est 0x31.
 
Est-ce que j'ai bien compris la question et est-ce que vous voyez la solution ?

Reply

Marsh Posté le 05-04-2007 à 09:50:47    

Les Pixels sont lus avec fread, et récupérés dans des unsigned char.
Ces sur ces unsigned char que je dois faire les opérations (quelques masquages)
Ensuite je veux les récrire avec fread.
 
Or, bien que ce soit des unsigned char, je constate que putchar affiche des caractères non-imprimables -> 1er point obscur.
 
2éme point obscur: si je les affiche en tant que 'int' (avec un printf("%d" ) ), alors j'ai tout un ensemble de nombres qui me permettent de vérifier que mes opérations de masquages marchent bien.
Par contre, quand j'affiche le contenu de l'image avec la commande linux od -c img.pgm, la je constate que ces chiffres ne sont plus les mêmes !!! (comme si fwrite les avait changés)
 
 
PS: chaque Pixel (unsigned char p) suit l'opération suivante:
 
- p_old = p & 0xFE ( je sauvegarde les 7 premiers bits sauf le dernier)
 
- p=p_old | 0x01 (pour lui mettre le bit poid faible à 1 suivant la lettre à coder)
OU p=p_old | 0x00 (pour lui mettre le bit poid faible à zéro suivant...)

Reply

Marsh Posté le 05-04-2007 à 10:10:43    

char , en C , c'est juste la taille des données , donc il est logique que tu ai des caractères non affichables  , ou meme des bip :d . il n'y a pas de contrainte disant qu'un char doit etre un caractère affichable
 
pour la suite, je ne sais psa

Reply

Marsh Posté le 05-04-2007 à 10:35:35    

Poste nous ton code (la partie intéressante), comme ça on saura exactement ce que tu as fait (ce sera plus simple que de tenter de l'expliquer avec des mots)
 
Sinon, je ne sais pas trop ce que donne un printf("%d" ) avec un unsigned char. C'est peut-être simplement là que se situe ton problème...


---------------
TriScale innov
Reply

Marsh Posté le 05-04-2007 à 11:23:58    

cambronne3 a écrit :

1/ Si je fais putchar(c), j'ai systématiquement un point d'interrogation...


Normal, si la valeur que tu envoies à "putchar()" n'est pas celle d'un code ascii affichable (voir pour ça les fonctions "isprint()", "isascii()" et autres...) ben le terminal affiche ce qu'il peut...
 

cambronne3 a écrit :

2/ Si j'affiche en tant que "int" j'ai certains nombres dans mon tableau. Donc la je fais un fwrite pour tout reécrire dans une image (image codée), mais les valeurs des pixels (que j'affiche avec od -c image.pgm) ne correspondent pas à celle du tableau.


De quelle façon affiches-tu ? "%d" ?? "%u" ??? "%x" ???
 

cambronne3 a écrit :

Quelqu'un peut-il m'expliquer comment ca se passe réellement ? J'ai l'impression que le type char pose problème et je comprend pas trop...


Non, ce qui pose problème c'est la façon dont tu vérifies tes infos. Faut bien comprendre qu'un nombre codé en mémoire ne signifie pas la même chose selon qu'il soit int, double, signé, non-signé. Et "printf()" fait ce qu'il peut avec les infos qu'on lui donne. Par exemple, tu écrits

printf("%u", -1)


Ben (sauf erreur de ma part car je réponds au jugé) tu auras 65535 parce que, en binaire sur 16 bits non signés, 65535 se code "1111111111111111" alors que "-1" sur 16 bits signés se code "1111111111111111". Ainsi "printf()" recevant une valeur et toi lui demandant de l'afficher en non-signé, il l'affiche en non-signé.
 
Ce genre d'erreur (zut, je n'obtiens pas à l'écran ce que j'imagine avoir dans ma variable) est fréquent quand on mélange à la fois les types des variables et les ordres d'affichage donnés à "printf()".
 
Donc commence par bien poser tes types. Si tu travailles en non-signé c'est à dire si tu n'as pas besoin de réserver un bit pour le signe (ce qui est le cas avec la forme de stockage d'un pixel qui code chaque canal RVB sur un octet entier) alors déclare tes valeurs en "unsigned". En plus, coder en signé alors qu'on travaille en non-signé peut produire des effets de bords. Ex:
signed char a
unsigned int b
a=128        (soit 1000000 en binaire)
b=a  
Tu espères avoir "b=128" alors que t'auras (sauf erreur) "b=65408". Pourquoi ? Parce que "a" est considéré comme signé et que le signe est conservé donc le premier bit est recopié sur toute la zone située à gauche quand "a" est copié dans "b" (ça donne 1111 1111 1000 0000 en binaire).
 
Ensuite, quand tu donnes un format à "printf()", respecte bien le format du nombre que tu fournis.

  • "%c" => tu veux afficher un nombre au format "char"
  • "%d" => tu veux afficher un nombre au format "int signé"
  • "%u" => tu veux afficher un nombre au format "int non-signé"
  • "%hd" => tu veux afficher un nombre au format "short signé"
  • "%hu" => tu veux afficher un nombre au format "short non-signé"
  • "%ld" => tu veux afficher un nombre au format "long signé"
  • "%lu" => tu veux afficher un nombre au format "long non-signé"
  • "%o" => tu veux afficher un nombre converti en octal
  • "%x" => tu veux afficher un nombre converti en hexadécimal


Alors seulement là t'auras correspondance entre tes calculs et ce que tu vois à l'écran...
 

franceso a écrit :

Sinon, je ne sais pas trop ce que donne un printf("%d" ) avec un unsigned char.


Un "unsigned char" étant un nombre pouvant aller de 0 à 255, le printf() affichera simplement ce nombre   :sol:

Message cité 1 fois
Message édité par Sve@r le 05-04-2007 à 11:47:10

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 05-04-2007 à 11:46:37    

Au temps pour moi :jap:
 
Il me semblait qu'il y avait des problèmes de ce genre (en particulier avec les signes), mais je supose que ça ne concerne que les signed char.


---------------
TriScale innov
Reply

Marsh Posté le 05-04-2007 à 11:47:59    

franceso a écrit :

Au temps pour moi :jap:
 
Il me semblait qu'il y avait des problèmes de ce genre (en particulier avec les signes), mais je supose que ça ne concerne que les signed char.


J'ai modifié mon post précédent et cela devrait répondre aussi à ta question...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 05-04-2007 à 11:58:00    

Sve@r a écrit :


signed char a
unsigned int b
a=128        (soit 1000000 en binaire)
b=a  
Tu espères avoir "b=128" alors que t'auras (sauf erreur) "b=65408". Pourquoi ? Parce que "a" est considéré comme signé et que le signe est conservé donc le premier bit est recopié sur toute la zone située à gauche quand "a" est copié dans "b" (ça donne 1111 1111 1000 0000 en binaire).


 
euh, b vaudra 128 la. Promotion entière tout ça ...
ah ben non :| diantre o_O

Message cité 1 fois
Message édité par Joel F le 05-04-2007 à 12:00:14
Reply

Marsh Posté le 05-04-2007 à 15:16:27    

Je vous remercie tous pour vos explications, en fait la différences entre caractères affichés par printf("%d" ) et "od -c image" vient tout simplement du fait que "od -c" affiche en octal, et qu'aprés conversion j'avais bien le bon affichage...

Reply

Marsh Posté le 05-04-2007 à 15:16:27   

Reply

Marsh Posté le 05-04-2007 à 15:59:47    

Joel F a écrit :

euh, b vaudra 128 la. Promotion entière tout ça ...
ah ben non :| diantre o_O


Hum...  :whistle:
 
b vaudra 128 si tu déclares "a" comme "unsigned"...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed