隐写术:如何更改像素阵列的 LSB
Steganography: how to change the LSB of a pixel array
我正在使用 lodePNG 库对 png 图像进行编码,并使用导入的 txt 文件更改像素的 LSB。我已经编译了程序,但我不确定 PNG 文件是否真的根据我的按位运算进行了编码。
lodePNG 库 decodes/encodes 来自 PNG 图像并将像素存储在向量 "image" 中,每个像素 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 替换为 char 中的一位。由于 char 是 8 个字节,因此 for 循环循环了 8 次。这个程序应该适用于大多数不超过大小的 PNG 图像和文本,但我不确定按位运算是否真的在做任何事情。另外,我怎样才能移动这些位,以便我们将 char 位从 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
在嵌入你的秘密位之前,你首先需要清除像素的 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++;
}
Edit:为了解释上面的代码,image[pixCount] & mask
是您的像素和所选掩码值(二进制为 1111110)之间的 AND 运算符,因此结果是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
我正在使用 lodePNG 库对 png 图像进行编码,并使用导入的 txt 文件更改像素的 LSB。我已经编译了程序,但我不确定 PNG 文件是否真的根据我的按位运算进行了编码。
lodePNG 库 decodes/encodes 来自 PNG 图像并将像素存储在向量 "image" 中,每个像素 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 替换为 char 中的一位。由于 char 是 8 个字节,因此 for 循环循环了 8 次。这个程序应该适用于大多数不超过大小的 PNG 图像和文本,但我不确定按位运算是否真的在做任何事情。另外,我怎样才能移动这些位,以便我们将 char 位从 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
在嵌入你的秘密位之前,你首先需要清除像素的 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++;
}
Edit:为了解释上面的代码,image[pixCount] & mask
是您的像素和所选掩码值(二进制为 1111110)之间的 AND 运算符,因此结果是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