4

I'm doing a steganography project where I read in bytes from a ppm file and add the least significant bit to an array. So once 8 bytes are read in, I would have 8 bits in my array, which should equal some character in a hidden message. Is there an easy way to convert an array of 0's and 1's into an ascii value? For example, the array: char bits[] = {0,1,1,1,0,1,0,0} would equal 't'. Plain C

Thanks for all the answers. I'm gonna give some of these a shot.

Dan Herbert
  • 99,428
  • 48
  • 189
  • 219
Anon
  • 127
  • 1
  • 3
  • 11
  • Do you really mean `"0,1,1,1,0,1,0,0"`? Or maybe something more like `{0,1,1,1,0,1,0,0}`? – Gabe Mar 26 '10 at 05:27

4 Answers4

4

A simple for loop would work - something like


    unsigned char ascii = 0;
    unsigned char i;

    for(i = 0; i < 8; i++)
       ascii |= (bits[7 - i] << i);

There might be a faster way to do this, but this is a start at least.

sud03r
  • 19,109
  • 16
  • 77
  • 96
Sam Post
  • 3,721
  • 3
  • 17
  • 14
  • is there something missing in your for loop ? – stefanB Mar 26 '10 at 05:12
  • Yeah that was a mistake, thanks. bits contains '0' and '1', so I updated the loop. – Sam Post Mar 26 '10 at 05:35
  • @sam: bits is an array of 0's and 1's. Its not '0's and '1's – N 1.1 Mar 26 '10 at 05:37
  • Are his bits 0 and 1 or are they '0' and '1'? His response to Gabe was that he meant the 'brackets' which I assume means the braces, so that would imply they are actual binary data rather than characters, no? – Jason Coco Mar 26 '10 at 05:38
  • Yes, I also meant braces : P it's been a long night. Just tried this code out and it worked, so thanks again stack overflow! – Anon Mar 26 '10 at 05:47
  • Ah, I missed his comment about the braces. Thanks. @Nick, glad to help and good luck! – Sam Post Mar 26 '10 at 05:51
2

I wouldn't store the bits in an array -- I'd OR them with a char.

So you start off with a char value of 0: char bit = 0;

When you get the first bit, OR it with what you have: bit |= bit_just_read;

Keep doing that with each bit, shifting appropriately; i.e., after you get the next bit, do bit |= (next_bit << 1);. And so forth.

After you read your 8 bits, bit will be the appropriate ASCII value, and you can print it out or do whatever with it you want to do.

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • His bits are in the other order. And you have to shift your power as well, otherwise, assuming next_bit is ever set, you just always end up with 0x2|bit_just_read – Jason Coco Mar 26 '10 at 05:19
  • I don't see the OP mention what order the bits are in, but yes, the algorithm I listed would have to be adjusted depending on the ordering; and yes, each step has to shift the value left by another bit. – mipadi Mar 26 '10 at 05:25
  • He made a pseudo assignment in his question. char bits[] = "0,1,1,1,0,1,0,0"; clearly the syntax is suspect but that is correct for 't', so... – Jason Coco Mar 26 '10 at 05:28
0

I agree with mipadi, don't bother storing in an array first, that's kind of pointless. Since you have to loop or otherwise keep track of the array index while reading it in, you might as well do it in one go. Something like this, perhaps?

bits = 0;

for ( i = 0; i < 8; ++i ) {
    lsb = get_byte_from_ppm_somehow() & 0x01;
    bits <<= 1 | lsb;
}
Duncan
  • 2,056
  • 13
  • 11
0

As long as the bit endian is correct, this should work and compile down pretty small. If the bit endian is backwards then you should be able to change the initial value of mask to 1, the mask shift to <<= , and you might need to have (0x0ff & mask) as the do{}while conditional if your compiler doesn't do what it's supposed to with byte sized variables. Don't forget to do something for the magic functions that I included where I didn't know what you wanted or how you did something

#include <stdint.h> // needed for uint8_t
...
uint8_t acc, lsb, mask;
uint8_t buf[SOME_SIZE];
size_t len = 0;

while (is_there_more_ppm_data()) {
    acc = 0;
    mask = 0x80; // This is the high bit
    do {
         if (!is_there_more() ) {
             // I don't know what you think should happen if you run out  on a non-byte boundary
             EARLY_END_OF_DATA();
             break;
         }
         lsb = 1 & get_next_ppm_byte();
         acc |= lsb ? mask : 0; // You could use an if statement
         mask >>= 1;
    } while (mask);
    buf[len] = acc; // NOTE: I didn't worry about the running off the end of the buff, but you should. 
    len++;
}
nategoose
  • 12,054
  • 27
  • 42