C ++使用按位运算从图像中提取字符

C++ Extracting a character from an image using bit-wise operations

这是我第一次在这里提问,请多多包涵!我有一个快要完成的隐写术实验室。我已经完成了一个在图像的低位隐藏消息的程序,但是提取图像的程序是我卡住的地方。图像在一个表示为二维矩阵、列主要顺序的文件中。所以这是我卡住的代码。

void image::reveal_message()
{
    int bitcount = 0;
    char c;
    char *msg;
    while(c != '[=10=]' || 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;
}

代码能够遍历并获取位的所有正确数字。这些位基于矩阵中的数字是奇数还是偶数。我遇到麻烦的地方实际上是将 char 的位设置为我从矩阵中提取的位。我不是最擅长位操作的,我们也不应该为此使用任何库。 reverse_bits 函数也能正常工作,所以这似乎只是我的移位和按位操作搞砸了 up.I 还注释掉了 strcat() 行,因为它由于以下原因产生了很多错误char c 不正确的事实。另外,我不断收到的主要错误是分段转储。

您从 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

我从您的代码中了解到,您将消息嵌入为每像素 1 位,一行一行。例如,如果您有一张 3x10 的图像,像素

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 == '[=11=]')
    {
        break;
    }
}

了解移位的工作原理。 b 以值 0 开头,或者 00000000 如果您想以二进制形式将其可视化。每次,您都将其向左移动一位,以便为新提取的位腾出空间,您可以进行或运算。无需检查它是 1 还是 0,它会正常工作。

所以,假设你到目前为止已经提取了 5 位,b 是 00010011,当前图像像素的最低有效位是 1。会发生什么

b = (b << 1) | 1    // b = 00100110 | 1 = 00100111

因此您已经提取了第 6 位。

现在,假设您在前 8 个像素中嵌入了字符 "a" (01100001)。

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 将得到 "a"。但是,如果您以相反的顺序嵌入位,即

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
}