3

I am playing around with steganography. I am trying to pull a text file from a image. I am able to read the file, get the bits, but I have an issue with the extraction of these bits.

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 is an unsigned char. I have loop that calls extract() and fputc(3) the return value. I feel like I am getting garbage from these bits. Which causes me to have massive (1.5 gig) txt files in return.

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);

}
Joe Tyman
  • 1,417
  • 5
  • 28
  • 57

2 Answers2

2

You are only actually reading the first pixel in the image - [Edit] because while you are trying to use a static var to keep count, as Oli points out you're immediately overwriting it.

Instead use position to track your count; but hold the data in another var:

Instead extract() should look something like:

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

   pixel data = image[position];

   postion++;

   // use 'data' for processing
}
DaveR
  • 9,540
  • 3
  • 39
  • 58
2

Dave Rigby's excellent diagnosis is correct, but passing position as a parameter (and not incrementing it here) would lead to easier to understand and more flexible routines:

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;
}

Then, when you realize that changing all the pixels in a line makes it pretty obvious, and you'd rather use pixels located at Fibonacci values, the change is easy to make:

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;
}

You could stuff the Fibonacci computation into your extract() routine too, but decomposing functions into the smallest, most useful, pieces, gives you excellent legibility, excellent testability, and best chances for future code re-use.

Community
  • 1
  • 1
sarnold
  • 102,305
  • 22
  • 181
  • 238