C ++使用逐位操作从图像中提取字符

时间:2016-03-28 21:46:00

标签: c++ matrix bitwise-operators bit-shift steganography

这是我第一次在这里提问,所以请耐心等待!我有一个我几乎完成的隐写术实验室。我已经完成了一个程序,它在图像的低位隐藏了一条消息,但是提取图像的程序是我被卡住的地方。图像位于表示为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;
}

代码能够遍历并获取所有正确的位数。这些位基于矩阵中的数字是奇数还是偶数。我遇到麻烦的地方实际上是将char的位设置为我从矩阵中提取的位。我不是最好的逐位操作,我们也不应该使用任何库。 reverse_bits函数也可以工作,所以它似乎只是我的移位和逐位操作搞砸了。我还注释掉了strcat()行,因为它因charc不正确而产生了很多错误。我一直收到的主要错误是Segmentation Dump。

2 个答案:

答案 0 :(得分:0)

您从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 :(得分:0)

我对您的代码的理解是,您将消息嵌入到每像素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 == '\0')
    {
        break;
    }
}

了解比特换档的工作原理。 b以值0开头,或00000000,如果您想以二进制形式显示它。每次,你将它向左移一个,为你提取的新位提供空间。无需检查它是1还是0,它只是起作用。

所以,想象一下到目前为止你已经提取了5位,b是00010011而当前图像像素的最低有效位是1.会发生什么呢

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

因此你提取了第6位。

现在,让我们说你嵌入了角色&#34; a&#34; (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将为您提供&#34; a&#34;。但是,如果以相反的顺序嵌入位,即

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
}