比特提取和隐写术

时间:2011-07-03 20:56:46

标签: c bit-manipulation steganography

我正在玩隐写术。我试图从图像中提取文本文件。我能够读取文件,得到这些位,但是我在提取这些位时遇到了问题。

int getbits( pixel p) {
    return p & 0x03;   
}

char extract ( pixel* image ) {
    static int postion;
    postion = 0;

    postion = *image;

    postion++;

    char curChar;
    curChar = '\0';
    for(int i = 0; i<4; ++i) {
        curChar = curChar << 2;
        curChar = curChar | getbits(postion);
    }
    return curChar;
}

Pixel是一个unsigned char。我有循环调用extract()fputc(3)返回值。我觉得我从这些位中得到了垃圾。这导致我有大量(1.5演出)txt文件作为回报。

void decode( PgmType* pgm, char output[80] )
{
FILE*outstream;
int i, length;

outstream = fopen(output, "w");

if(!outstream)
{
    fatal("Could not open");
}
for(i=0; i < 16; ++i)
{
    length = length << 2;
    length = length | getbits(*pgm->image);
}
if ((length* 4) < (pgm->width * pgm->height))
{
    fatal("File Too Big");
}
for (i = 0 ;i<length; ++i)
{
    fputc(extract(pgm->image), outstream);

}
fclose(outstream);

}

2 个答案:

答案 0 :(得分:2)

您实际上只是在读取图像中的第一个像素 - [编辑],因为当您尝试使用静态变量来保持计数时,正如Oli指出的那样,您会立即覆盖它。

而是使用位置来追踪你的数量;但是将数据保存在另一个var中:

extract()应该类似于:

char extract ( pixel* image )
{
   static int postion = 0;

   pixel data = image[position];

   postion++;

   // use 'data' for processing
}

答案 1 :(得分:2)

Dave Rigby的excellent diagnosis是正确的,但是将position作为参数传递(并且将其递增到此处)将导致更容易理解和更灵活的例程:

char extract ( pixel* image, int position ) {
    char curChar = '\0';
    for(int i = 0; i<4; ++i) {
        curChar = curChar << 2;
        curChar = curChar | getbits(postion);
    }
    return curChar;
}

char *build_string(pixel *image) {
    int i;
    char *ret = malloc(SECRET_SIZE);
    for (i=0; i<SECRET_SIZE; i++) {
        ret[i]=extract(image, i);
    }
    ret[i] = '\0';
    return ret;
}

然后,当你意识到改变一行中的所有像素使得它非常明显,而你宁愿使用位于Fibonacci值的像素时,很容易做出改变:

char *build_string_via_fib(pixel *image) {
    int i;
    char *ret = malloc(SECRET_SIZE);

    for (i=0; i<SECRET_SIZE; i++) {
        ret[i]=extract(image, fib(i));
    }
    ret[i]='\0';
    return ret;
}

可以将Fibonacci计算填充到你的extract()例程中,但是将函数分解为最小,最有用的部分,可以提供出色的可读性,出色的可测试性和最佳的机会。未来的代码重用。