You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

82 lines
3.3 KiB

#include "hide.h"
void hide_lsb(string picture_path, string file_path, string output_path, byte forced_lsb) {
u32 width, height, size;
u32 lsb; // nombre de bits occupes par channnel
u32 w_index = 1; // nombre de groupes de bits écrits
picture image = 0;
byte *to_hide = 0; // donnees a dissimuler
byte write_buffer = 0; // buffer d'ecriture
byte buffer_fill = 0; // remplissage du buffer
FILE *fp;
EXIT_ON_TRUE(lodepng_decode32_file(&image, &width, &height, picture_path), LODEPNG_ERROR);
EXIT_ON_FALSE(fp = fopen(file_path, "r"), SYSTEM_CALL_FAIL);
EXIT_ON_TRUE(fseek(fp, 0L, SEEK_END), SYSTEM_CALL_FAIL);
size = (u32) ftell(fp);
rewind(fp);
EXIT_ON_FALSE(to_hide = malloc((size + 5) * sizeof(byte)), SYSTEM_CALL_FAIL);
fread(to_hide + EMBEDDED_HEADER_SIZE, size, 1, fp);
if (fclose(fp)) exit(3);
if ((lsb = (size * 8 + HEADER_SIZE_BITS) / (width * height * 3 - 1) +
((size * 8 + HEADER_SIZE_BITS) % (width * height * 3 - 1) != 0)) > 7)
exit(DATA_DOESNT_FIT);
//printf("%d\n", lsb);
lsb = (forced_lsb && forced_lsb >= lsb) ? forced_lsb : lsb;
// premiere partie header (3 bits)
image[0] = (byte) ((image[0] & 0xf8) | lsb);
u32 mask = gen_mask(lsb);
// deuxieme partie header (32 bits)
for (u32 i = 0, m = 0xff000000; i < LEN_HEADER_SIZE; ++i, m >>= 8)
to_hide[i] = (byte) ((size & m) >> ((3 - i) * 2 * 4));
// octet reserve
to_hide[LEN_HEADER_SIZE] = 0;
// parcours des donnees a stocker octet par octet
for (u32 i = 0; i < size + EMBEDDED_HEADER_SIZE; ++i) {
// parcours octet courant bit a bit
// incrementation indice j
// deplacement masque mk
for (u32 j = 0, mk = 0x80; j < 8; ++j, mk >>= 1) {
// on decale le contenu du buffer pour liberer le dernier bit
// on ecrit le bit courant dans le buffer
write_buffer = (byte) (write_buffer << 1u | (byte) (to_hide[i] & mk) >> (8u - j - 1u));
buffer_fill++; // on incremente le nombre d'elements dans le buffer
if (buffer_fill == lsb) { // si on a assez de donnees dans le buffer pour ecrire un canal de pixel
// formule pour retrouver le canal en evitant les alpha
// on insere les donnees du buffer dans l'image
image[w_index + w_index / 3] = (byte) ((image[w_index + w_index / 3] & mask) |
(write_buffer & (~mask)));
w_index++; // on indique qu'un element de plus a ete ecrit
buffer_fill = 0; // on indique que le buffer est vide (c'est un mensonge)
}
}
}
if (buffer_fill) { // si le buffer n'est pas vide en fin d'execution on l'ecrit dans l'image
image[w_index + w_index / 3] =
(byte) ((image[w_index + w_index / 3] & mask) | (write_buffer << (lsb - buffer_fill) & ~mask));
w_index++;
}
for (u32 i = w_index + w_index / 3; i < width * height * 4; ++i) { // remplissage du reste de l'image avec du bruit
if (i % 4 == 3) continue; // on skip le canal alpha
image[i] = (byte) ((image[i] & mask) | ((byte) rand() & (~mask)));
}
EXIT_ON_TRUE(lodepng_encode32_file(output_path, image, width, height), LODEPNG_ERROR);
free(to_hide);
free(image);
}