Blame view

src/stegano.c 4.9 KB
17ba8f8f   tevrard   Ajout du code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <stdint.h>
  #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, &current_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
  */