Как работает этот метод LSB стеганографии?

106
14 февраля 2021, 17:40

Два вопроса по программе, использующую метод LSB Стеганографии. Дело в том, что у меня немного проблемы с понимаем того, зачем нужна та или иная функция, я просто знаю, что так можно делать, поэтому делаю. А когда просят объяснить почему так, то становится сложно.

  1. Как работает вот эта часть программы? (Комментарии приведены в полном коде ниже)

    for (i = 0; i < 54; i++) 
    {
        pic = fgetc(q); 
        fputc(pic, w); 
        count--;
    }
    
  2. Вопрос касательно части кода, представленной ниже. Почему именно на 2? Моё предположение, что это связано с бинарным представлением массива бит, полученного из изображения.

    for (i = 0; i < 24; i++) 
    {
        ff[i] = size2 % 2; 
        size2 = size2 / 2; 
    }
    

Полный код:

#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <clocale>
int main()
{
setlocale(LC_CTYPE, "rus");
FILE *q, *w, *f, *r; // Здесь q - Исходное изображение, f - Исходный текст, w - Зашифрованное изображение, r - расшифрованный текст
int i, j, k, s = 0, count; // i, j, k, s - показатели счётчика
long int size1, size2 = 0, size = 0;
printf("Введите для кодирования - 1, Введите для декодирования - 2: ");
scanf("%d", &i);
if (i == 1)
{
    q = fopen("1.bmp", "rb"); // Открываем рисунок
    f = fopen("1.txt", "r"); // Открываем текстовый документ с текстом
    char e;
    while (!feof(f))
    {
        e = getc(f);
        size2++;
    }
    fclose(f);
    f = fopen("1.txt", "r");
    w = fopen("2.bmp", "wb"); 
    {
        fseek(q, 0, SEEK_END); //Перемещение указателя позиции в потоке в конец
        size1 = ftell(q); //Возвращает текущее значение указателя положения в файле для потока. Это значение представляет собой количество байт, на которое указатель отстоит от начала файла. Запоминает это значение в переменной.
        fseek(q, 0, SEEK_SET); //Перемещение указателя позиции в потоке в начало
    }
    count = size1;
    bool buf[8], sym[8];
    unsigned char pic, temp; // pic - символ исходного изображения, temp - символ для исходного текста
    for (i = 0; i < 54; i++) // Начинаем записывать файлы исходного изображения в новое, записываем первые 54 байта, содержащие заголовок файла (40 байт, содержащие идентификатор BMP- файла, его общий размер, а также зарезервированные поля) и заголовок растра (14 байт, содержащие основные характеристики изображения: ширину, высоту, цветовое разрешение, общий размер растровых данных, их положение относительно начала всего файла.) 
    {
        pic = fgetc(q); //Cчитывание символов из потока и сохранение их в виде строки в параметр до тех пор пока не наступит конец строки или пока не будет достигнут конец файла.
        fputc(pic, w); //Записывание содержимого символа исходного изображения в заданный поток.
        count--;
    }
    bool ff[24]; //Число 24 здесь обозначет количество бит, у нас есть три цвета: Красный, синий, зелёный, где каждый цвет (пиксель) кодируется 8 битами. 8*3=24. 
    for (i = 0; i < 24; i++) 
    {
        ff[i] = size2 % 2; 
        size2 = size2 / 2; 
    }
    for (i = 0; i < 24; i++) 
    {
        pic = fgetc(q); 
        for (j = 0; j < 8; j++)
        {
            buf[j] = (int)pic % 2;
            pic = (int)pic / 2;
        }
        buf[0] = ff[i];
        i++;    
        buf[1] = ff[i];
        for (j = 0; j < 8; j++) //В одном байте 8 бит
            pic = pic + (int)buf[j] * pow(2.0, (int)j);
        fputc(pic, w);
        count--;
    }
    while (!feof(f)) //Записываем текст в изображение
    {
        temp = fgetc(f);
        for (i = 0; i < 8; i++)
        {
            sym[i] = (int)temp % 2;
            temp = (int)temp / 2;
        }
        for (i = 0; i < 8;)
        {
            pic = fgetc(q);
            for (j = 0; j < 8; j++)
            {
                buf[j] = (int)pic % 2;
                pic = (int)pic / 2;
            }
            pic = 0;
            for (k = 0; k < 8; k++, i++)
            {
                buf[k] = sym[i];
            }
            for (j = 0; j < 8; j++)
                pic = pic + (int)buf[j] * pow(2.0, (int)j);
            fputc(pic, w);
            count--;
        }
        s++;
    }
    while (count)
    {
        pic = fgetc(q);
        fputc(pic, w);
        count--;
    }
    fclose(q);
    fclose(f);
    fclose(w);
}
else
{printf("Error.\n");}
printf("Завершено.\n");
getch();
return 0;
}
Answer 1
for...
    {
        ff[i] = size2 % 2; 
        size2 = size2 / 2; 
    }

Да, этот фрагмент кода выделяет отдельные биты числа size2 и записывает их в массив. size2[0] соответствует младшему биту. size2 = size2 / 2; эквивалентно побитовому сдвигу вправо, чтобы на следующем шаге получить очередной бит, который теперь стал младшим

Вот эту

(int)buf[j] * pow(2.0, (int)j)

лучше заменить на

buf[j] * (1 << j)

поскольку использование плавающей арифметики здесь не оправдано, или даже (учитывая, что buf содержит только 0 или 1)

(buf[j] << j)
READ ALSO
Ошибка компилятора C3646 при сборке проекта c++

Ошибка компилятора C3646 при сборке проекта c++

Есть два класса, имеющие экземпляры друг друга:

83
Что за оператор такой &ldquo;&rdquo; (двойные кавычки)?

Что за оператор такой “” (двойные кавычки)?

В общем вопрос в заголовке, что за перегружаемый(если уместно применить к этому слово перегружаемый) оператор "" и зачем он используется?

100
html, что это значит? и как её заменить?

html, что это значит? и как её заменить?

Есть вот такая запись которая применяется ко всей странице,что тут означает запятая?

84
Позиционирование слоёв в CSS

Позиционирование слоёв в CSS

Прошу помочь, не могу разобраться с позиционированием слоев

99