#include #include #include #include #include "../inc/stegano.h" #include "../inc/automatos.h" /* Inverse le LSB d'un unsigne char *x passé en paramètre ex : 01001011 -> 01001010 */ void Change_LSB(unsigned char *x) { unsigned char mask = 0x01; //0b00000001 unsigned char tmp; tmp = *x & mask; tmp = ~tmp & 0x01; *x = (*x & 0xFE) | tmp; } /* Copie le LSB de x pour le stocker à la ie position de a */ void GetOneChar(unsigned char x, unsigned char *a, int i) { unsigned char mask = 0x01; //0b00000001 *a += (x & mask) << (7-i); } /* Determine la parité du voisinage d'un pixel (de coordonnées int i, int j) La règle à utiliser est passée en paramètre via int algo_tab[] */ int Parity_check(Image **I, int algo_tab[], int i, int j) { /* Pixels à considérer pour la parité */ int vois[9][2] = { { i , j } , { i , j+1 } , { i+1 , j+1 }, { i+1 , j } , { i+1 , j-1 } , { i , j-1 }, { i-1 , j-1 } , { i-1 , j } , { i-1 , j+1 } }; int parity = 0; int h = (*I)->height; int w = (*I)->width; /* Evaluation et stockage de la parité de chaque pixel voisin */ for (int k=0; k < 8; k++) { /* Considère ou non le voisin en fonction de l'algorithme de parité à appliquer */ if (algo_tab[k] == 1) { /* Verifie les dépassements de tableau */ if (vois[k+1][0] >= 0 && vois[k+1][0] < h && vois[k+1][1] >= 0 && vois[k+1][1] < w) { // Recupère le LSB du voisin (soit 1 si impair, soit 0 si pair) parity += ((*I)->Mat_data[vois[k+1][0]][vois[k+1][1]].blue) % 2; } } } // Ajoute la parité du pixel central lui même parity += (*I)->Mat_data[i][j].blue % 2; // Determine la parité globale du voisinage (0 si pair, 1 si impair) return (parity % 2); } /* Stocke les valeurs des 8 bits d'un octets 'byte' dans un int[8] passé en paramètre*/ void bit_in_tab(unsigned char *byte, int tab[]) { for(int k=7; k>=0; k--) { tab[k] = *byte % 2; *byte = *byte / 2; } } /* Cache un message de N bit, bit à bit, dans N pixel, en modifiant ou non la parité du voisinage de chaque pixel Au terme de la fonction, le voisinage d'un pixel est impair lorsqu'un 1 est caché le voisinage d'un pixel est pair lorsqu'un 0 est caché */ void Parity_encode(Image **I, unsigned char *msg) { /* Determination de l'algorithme de parité */ int algo_tab[8]; unsigned char algo_byte = (*I)->Mat_data[4][4].red; bit_in_tab(&algo_byte, algo_tab); /* variables concernant le message à cacher */ uint8_t current_byte = 0; int hide_byte[8]; int bit = 0; bit_in_tab(&msg[current_byte], hide_byte); /* Parcours de la matrice */ int h = (*I)->height; int w = (*I)->width; int parity = 0; int breaking = 0; for (int i = 0; i < h; i+=2) { for (int j = 0; j < w; j+=2) { /* Calcul de la parité des voisins*/ parity = Parity_check(I, algo_tab, i, j); /* Dissimulation du message en fonction de la parité */ if ((parity == 1) && (hide_byte[bit] == 0)) { Change_LSB(&((*I)->Mat_data[i][j].blue)); } else if ((parity == 0) && (hide_byte[bit] == 1)) { Change_LSB(&((*I)->Mat_data[i][j].blue)); } bit += 1; // Fin de message if (bit == 8 && breaking == 1) return; // Fin de caractère if (bit == 8) { current_byte ++; if (msg[current_byte] == '\0') breaking = 1; //Dernier caractère bit_in_tab(&msg[current_byte], hide_byte); //Chargement des 8 bits d'un caractère (msg[current_byte]) au sein d'un int[8] (hide_byte) bit = 0; } } } return; } /* Table de verité pour l'encodage : H = bit à cacher R = bit de poids faible du pixel central Paire et impaire = parités des voisins du pixel central(dépend de l'algo) | | H = 0 | H = 1 | |----------------------------------| | Impaire| change R | Nochange R| |----------------------------------| | Paire | Nochange R | change R | */ /* Extrait un potentiel message caché au sein d'une image ppm (stockée préalablement dans une matrice 2D) */ void Parity_decode(Image **I, unsigned char *msg) { /* Determination de l'algorithme de parité */ int algo_tab[8]; unsigned char algo_byte = (*I)->Mat_data[4][4].red; bit_in_tab(&algo_byte, algo_tab); uint8_t l = 0; int bit = 0; /* Parcours de la matrice */ int h = (*I)->height; int w = (*I)->width; int parity = 0; for (int i = 0; i < h; i+=2) { for (int j = 0; j < w; j+=2) { // parity == 0 (pair) -> le caractère caché est un 0 // parity == 1 (impair) -> le caractère caché est un 1 parity = Parity_check(I, algo_tab, i, j); GetOneChar(parity, &msg[l], bit); bit ++; //fin de caractère ou de message if (bit == 8) { if (msg[l] == '\0') return; l ++; bit = 0; } } } }