я впервые здесь задаю вопросы, так что терпите меня! У меня есть стеганографическая лаборатория, с которой я почти укомплектован. Я завершил программу, которая скрывает сообщение в нижних битах изображения, но программа для извлечения изображения — то, где я застрял. Изображение находится в файле, представленном в виде 2D-матрицы, в главном порядке столбцов. Так вот код, где я застрял.
void image::reveal_message()
{
int bitcount = 0;
char c;
char *msg;
while(c != '\0' || bitcount < 1128)
{
for(int z = 0; z < cols; z++)
{
for(int k = 0; k < 8; k++)
{
int i = bitcount % rows ;
int j = bitcount / rows ;
int b = c & 1;
if(img[i][j] % 2 != 0 && b == 0)
{
c = c & (~1);
}
else if(img[i][j] % 2 == 0 && b == 1)
{
c = c | 1;
}
bitcount++;
c = c << 1;
}
reverse_bits(c);
cout << c << endl;
//strncat(msg, &c, 1);
}
}
int i = 0;
for(int i = 0; i < cols; i++)
{
if(!isprint(msg[i]))
{
cout << "There is no hidden message" << endl;
}
}
cout << "This is the hidden message" << endl;
cout << msg;
}
Код может циклически проходить и захватывать все нужные числа для битов. Биты основаны на том, является ли число в матрице нечетным или четным. Когда у меня возникают проблемы, я на самом деле устанавливаю биты символа в биты, которые я извлек из матрицы. Я не лучший в битовых операциях, и мы также не должны использовать какую-либо библиотеку для этого. Функция reverse_bits работает также хорошо, так что, похоже, просто мои операции сдвига и битовые операции испорчены. Я также закомментировал строку strcat (), поскольку она выдает много ошибок из-за того, что char c неверен , Также основной ошибкой, которую я продолжаю получать, является дамп сегментации.
Насколько я понимаю из вашего кода, вы встраивали свое сообщение как 1 бит на пиксель, строка за строкой. Например, если у вас есть изображение 3х10, с пикселями
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
первый символ вашего сообщения находится в пикселях 01-08, второй — с 09 до 16 и т. д. После вашего сообщения вы ввели дополнительный нулевой символ, который вы можете использовать во время извлечения, чтобы знать, когда нужно остановиться. Имея все это в виду, вы ищете что-то вроде этого.
int bitcount = 0;
int i = 0;
int j = 0;
while(bitcount < 1128)
{
// this will serve as the ordinal value for the extracted char
int b = 0;
for(int k = 0; k < 8; k++)
{
b = (b << 1) | (img[i][j] & 1);
j++;
if(j == cols)
{
i++;
j = 0;
}
}
bitcount += 8;
// do whatever you want with this, print it, store it somewhere, etc
c = (char)b;
if(c == '\0')
{
break;
}
}
Понимание того, как работает битшифтинг. b
начинается со значения 0 или 00000000
если вы хотите визуализировать его в двоичном виде. Каждый раз вы сдвигаете его влево на единицу, чтобы освободить место для нового извлеченного бита, который вы ИЛИ. Не нужно проверять, 1 или 0, это просто сработает.
Итак, представьте, что вы уже извлекли 5 битов, b
00010011, и младший значащий бит текущего пикселя изображения равен 1. Что произойдет, это
b = (b << 1) | 1 // b = 00100110 | 1 = 00100111
И таким образом вы извлекли 6-й бит.
Теперь предположим, что вы ввели символ «а» (01100001) в первые 8 пикселей.
01 02 03 04 05 06 07 08 \\ pixels
0 1 1 0 0 0 0 1 \\ least significant bit of each pixel
Когда вы извлекаете биты с вышеупомянутым, b
будет равно 97 и c
даст вам «а». Однако, если вы вставили свои биты в обратном порядке, то есть,
01 02 03 04 05 06 07 08 \\ pixels
1 0 0 0 0 1 1 0 \\ least significant bit of each pixel
Вы должны изменить алгоритм извлечения на следующий, чтобы вам не пришлось менять биты позже
int b = 0;
for(int k = 7; k <= 0; k--)
{
b = b | ((img[i][j] & 1) << k);
// etc
}
Вы начинаете с неопределенными данными в вашем char c
,
Вы читаете здесь int b = c & 1;
,
Это явно глупость.
c = c <<1; // shift before, not after
// if odd clear:
if(img[i][j] % 2)
{
c = c & (~1);
}
else // if even set:
{
c = c | 1;
}
вышеупомянутое не может прочитать данные, но по крайней мере не бессмыслица.
Побитовые операции выглядят нормально.
char *msg;
должно быть std::string
и использовать +=
вместо strncat
,