Стеганография: как изменить LSB пиксельного массива

Я использую библиотеку lodePNG для кодирования изображения в формате png и изменения LSB пикселей с помощью импортированного текстового файла. Я скомпилировал программу, но я не уверен, что файл PNG действительно кодируется в соответствии с моей побитовой операцией.

Библиотека lodePNG декодирует / кодирует из PNG-изображения и сохраняет пиксели в векторе "изображение", 4 байта на пиксель, упорядоченный RGBARGBA...,

void decodeOneStep(const char* filename)
{

      unsigned width, height;

      //decode
      unsigned error = lodepng::decode(image, width, height, filename);

      //if there's an error, display it
      if (error) std::cout << "decoder error " << error << ": " << 
          lodepng_error_text(error) << std::endl;
}

Программа принимает аргумент командной строки текстового файла и файла PNG. Я еще не включил проверку ошибок для аргументов.

int const MAX_SIZE = 100; 
std::vector<unsigned char> image;

int main(int argc, char *argv[])
{
const char* filename;
char* textArray = new char[MAX_SIZE];

std::ifstream textfile;
textfile.open(argv[1]);

int numCount = 0;
while (!textfile.eof() && numCount < MAX_SIZE)
{
    textfile.get(textArray[numCount]); //reading single character from file to array
    numCount++;
}

textfile.close();

    filename = argv[2];
    decodeOneStep(filename);

    unsigned width = 512, height = 512;
    image.resize(width * height * 4);

    int pixCount = 0; 

    for (int i = 0; i < numCount - 1; i++) {

        std::cout << textArray[i]; 

        for (int j = 0; j < 8; j++) {

            std::cout << ((textArray[i]) & 1); //used to see actual bit value.
            image[pixCount++] |= ((textArray[i]) & 1);
            (textArray[i]) >>= 1; 
        }                       
        std::cout << std::endl; 
    } 

encodeOneStep(filename, image, width, height);

В цикле for я прохожу каждый пиксель в векторе и заменяю LSB битом из символа. Поскольку символ равен 8 байтам, цикл for зацикливается 8 раз. Эта программа должна работать для большинства изображений PNG и текстов, размер которых не превышает размер, но я не уверен, что побитовая операция действительно что-то делает. Кроме того, как бы я мог сдвинуть биты, чтобы мы сохранили биты символов из MSB в LSB? Я чувствую, что понимаю что-то не так с тем, как значения пикселей (биты) хранятся в массиве.

РЕДАКТИРОВАТЬ: Тест, я запустил на новой битовой операции:

    for (int j = 7; j >= 0; j--) {

        //These tests were written to see if the 4-bits of the pixels were actually being replaced.
        //The LSB of the pixel bits are replaced with the MSB of the text character. 

        std::cout <<"Initial pixel 4-bits: " << std::bitset <4>(image[pixCount]) << "  "; 
        std::cout << "MSB of char: " << ((textArray[i] >> j) & 0x01) << " ";
        std::cout << "Pixel LSB replaced: " << ((image[pixCount] & mask) | ((textArray[i] >> j) & 0x01)) << " ";

        image[pixCount] = (image[pixCount] & mask) | ((textArray[i] >> j) & 0x01);
        pixCount++;

        std::cout << std::endl;

    }

Результат испытаний:

For char 'a' 
Initial pixel 4-bits : 0000 MSB: 0 Pixel LSB replaced: 0
Initial pixel 4-bits : 0001 MSB: 1 Pixel LSB replaced: 1
Initial pixel 4-bits : 0001 MSB: 1 Pixel LSB replaced: 1
Initial pixel 4-bits : 0000 MSB: 0 Pixel LSB replaced: 0
Initial pixel 4-bits : 0000 MSB: 0 Pixel LSB replaced: 0
Initial pixel 4-bits : 0000 MSB: 0 Pixel LSB replaced: 0
Initial pixel 4-bits : 0000 MSB: 0 Pixel LSB replaced: 0
Initial pixel 4-bits : 0001 MSB: 1 Pixel LSB replaced: 1

1 ответ

Решение

Сначала вам нужно очистить lsb пикселя, прежде чем встраивать свой секретный бит.

unsigned char mask = 0xfe;  // in binary 11111110

// and in your loop
image[pixCount] = (image[pixCount] & mask) | (textArray[i] & 1);
pixCount++;

Если вы хотите встроить биты каждого символа секрета от самого младшего к младшему, вы хотите отсчитать j петля.

for (int j = 7; j >= 0; j--) {
    image[pixCount] = (image[pixCount] & mask) | ((textArray[i] >> j) & 0x01);
    pixCount++;
}

Изменить: Чтобы объяснить код выше, image[pixCount] & mask является оператором И между вашим пикселем и выбранным значением маски (1111110 в двоичном виде), поэтому в результате очищается lsb.

(textArray[i] >> j) & 0x01 сдвигает ваш символ влево j и только держит lsb. Если вы наметить математику, это то, что вы получите

// assume our character has the bits `abcdefgh`

j = 7
(character >> j) & 0x01 = 0000000a & 0x01 = a

j = 6
(character >> j) & 0x01 = 000000ab & 0x01 = b

j = 5
(character >> j) & 0x01 = 00000abc & 0x01 = c

// and so on

j = 0
(character >> j) & 0x01 = abcdefgh & 0x01 = h
Другие вопросы по тегам