#include #include #include #include #include "../inc/stegano.h" /* Génère une matrice 2D dynamique */ void NouvelleImage(int width, int height, Image** I) { *I = malloc(sizeof(Image)); (*I)->width = width; (*I)->height = height; /* Tableau de pointeur de tableau */ (*I)->Mat_data = (Pix_rgb **)malloc(height * sizeof(Pix_rgb *)); /* Allocation de mémoire pour chaque tableau */ for (int i = 0; i < height; ++i) { (*I)->Mat_data[i] = (Pix_rgb *)malloc(width * sizeof(Pix_rgb)); } return; } /* Libere l'espace mémoire alloué à la structure Image */ void free_image(Image** I) { for (int i = 0; i < (*I)->height; ++i) free((*I)->Mat_data[i]); free((*I)->Mat_data); free(*I); } /* Lit l'entete d'un fichier ppm pour extraire la taille */ void read_header(FILE * im_file, int *width, int *height) { char * buff = malloc(10*sizeof(char)); char * line = NULL; size_t len = 0; int nb_line = 0; /* Ignore les commentaire jusqu'à la ligne contenant la taille */ while (nb_line != 2) { getline(&line, &len, im_file); if (strncmp(line, "#", 1) != 0) { nb_line ++; } } /* Recupere la taille */ strcpy(buff, strtok(line, " ")); *width = atoi(buff); strcpy(buff, strtok(NULL, " ")); *height = atoi(buff); getline(&line, &len, im_file); free(buff); } /* Charge l'image au sein d'une matrice */ int chargement_ppm(char *image_name, Image** I) { /* Ouverture du fichier image .ppm */ FILE* im_file = NULL; if((im_file = fopen(image_name,"r")) == NULL) return -1; int width, height; read_header(im_file, &width, &height); printf("SIZE : %d %d\n", width, height); /* RECUPERATION ET STOCKAGE DES PIXELS */ NouvelleImage(width,height, I); for (int i=0; i < (*I)->height; i++) { for (int j=0; j < (*I)->width ; j++) { fscanf(im_file, "%c", &((*I)->Mat_data[i][j].red)); fscanf(im_file, "%c", &((*I)->Mat_data[i][j].green)); fscanf(im_file, "%c", &((*I)->Mat_data[i][j].blue)); } } fclose(im_file); return 0; } /* Crée une nouvelle image .ppm à partir d'une structure Image */ int sauvegarde_ppm(char* image_name, Image** I) { FILE* out = fopen(image_name, "w"); if(!out) return -1; fprintf(out, "P6\n%d %d\n255\n", (*I)->width, (*I)->height); for (int i=0; i < (*I)->height; i++) { for (int j=0; j < (*I)->width ; j++) { fprintf(out, "%c", (*I)->Mat_data[i][j].red); fprintf(out, "%c", (*I)->Mat_data[i][j].green); fprintf(out, "%c", (*I)->Mat_data[i][j].blue); } } fclose(out); printf("saveOK\n"); return 0; } /* Copie les 2 bits de poids faible de x pour les stocker dans le 1eme quart de a */ void GetPartChar(unsigned char x, unsigned char *a, int i) { unsigned char mask = 0x03; //0b00000011 *a += (x & mask) << (i-1)*2; } /* Copie le ieme quart de a pour les stocker dans les 2 bits de poids faible de x */ void SetPartChar(unsigned char *x, unsigned char a, int i) { unsigned char mask = 0x03; //0b00000011 unsigned char tmp; tmp = a & (mask << (i-1)*2); //Decale mask pour obtenir un masque sur le ieme quart *x = (*x & 0xFC) | (tmp >> (i-1)*2);//Place les 2 bits au niveau du poids faible de x } /* Determine dans quel pixels l'information est/sera dissimulée L'utilisation d'un chiffrement vigenere (int vigenere == 1) et donc d'une clé (unsigned char *cle) influe sur la détermination des pixels */ void Next_pixel(Image **I, int *current_pos, int *i, int *j, int vigenere, unsigned char *cle) { int h = (*I)->height; int w = (*I)->width; int im_size = h * w; *current_pos += ((*I)->Mat_data[(*i)][(*j)].red & (*I)->Mat_data[(*i)][(*j)].green) / 5; *current_pos += 1; if (vigenere) { int icle = *current_pos % strlen((const char *)cle); *current_pos += (*current_pos & cle[icle]) / 5; } int tmp_pos = *current_pos; if (tmp_pos % 2 == 0) tmp_pos = im_size - tmp_pos; //tmp_pos = tmp_pos % (w*h); //printf("pos %d\n", tmp_pos); *i = tmp_pos / w; *j = tmp_pos % w; } /* Cache ou extrait un unsigned char *msg au sein de la matrice Image **I int encode = 1 -> cache le message = 0 -> extrait le message int vigenere -> permet de savoir si un chiffrement vigenere a été ou doit être effectué (utile pour Next_pixel) unsigned char *clef -> utilisé en cas de chiffrement avec vigenere */ void LSB_hide(Image **I, unsigned char *msg, int encode, int vigenere, unsigned char *cle) { uint8_t k = 0; int quart = 1; int h = (*I)->height; int w = (*I)->width; int i = 0; int j = 0; int current_pos = i*h + j; /* dissimulation ou extraction message */ while(1) { Next_pixel(I, ¤t_pos, &i, &j, vigenere, cle); if (encode == 1) SetPartChar(&((*I)->Mat_data[i][j].blue), msg[k], quart); else GetPartChar((*I)->Mat_data[i][j].blue, &msg[k], quart); quart += 1; if (quart == 5) { quart = 1; if ( msg[k] == '\0') return; k ++; } if (current_pos >= h*w) return; } } /* TODO 1- vidage du buffer */