1

I am trying to read pixel data from a PPM file. I have a function to read the header so I know it's pointing to the beginning of the pixel data. I tried using fgetc(file) but if the value is more than one digit it will not work. I also tried using an array and converting the array to an int or char but I have no way of knowing how many digits each value is. I'm also not sure if the values are separated by whitespace or not. Basically I need a way to extract the pixel data. (I'm using C.)

My code right now is:

char read_byte(FILE *ipt) {
    int c, i=0, sum=0;
    while (i<16) {
        c=fgetc(ipt);
        if((i%2)!=0 {
            if(c&1) {
                sum+=pow(2,i/2);
            }
        }
        i++;
    }
    return (char)sum;
}

EDIT: At first I thought the file was stored as the ASCII values, then I realized it's stored as binary. Right now I think I'm making it act like hex. I'm not sure if that's correct. I'm really stuck.

EDIT: changed my code a bit

char read_byte(FILE *ipt) {
    int c, i=0, sum=0;
    while(i<8) {
        c = fgetc(ipt);
        c=c&1;
        sum+=c*pow(2,i);
        i++;
    }
    return sum;
}

I print the sum as %c

Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69
Sams
  • 197
  • 1
  • 3
  • 14
  • 1
    This answer may point you in the right direction: http://stackoverflow.com/questions/2693631/read-ppm-file-and-store-it-in-an-array-coded-with-c – Russ Clarke Mar 18 '12 at 00:23
  • We need more code. Does the program correctly read all of the first 8 parts of the file, as described at http://netpbm.sourceforge.net/doc/ppm.html if it has, then it has the size, width and height, of the image data, and maxvalue, which gives the number of bytes (1 or 2) of each colour component. – gbulmer Mar 18 '12 at 02:13
  • I can correctly read the header. I'm doing a steganography assignment and right now I'm trying to extract the message from the pixel data. We only have to worry about P6 and 1 byte, 255 max value. – Sams Mar 18 '12 at 02:17

1 Answers1

2

Must you write this for an assignment, or is it for pleasure, or could you use someone else's code?

There is an Open Source solution. "Netpbm is a package of graphics programs and a programming library. " which includes programs to read PPM at http://netpbm.sourceforge.net/doc/

Edit: Have you got, or read the definition of the file format, e.g. http://netpbm.sourceforge.net/doc/ppm.html?

It looks like the data is either sequences of one byte RGB triples, or sequences of two byte RGB triples.

The program can detect which format is used from item 7 "The maximum color value (Maxval)". It says "If the Maxval is less than 256, it is 1 byte. Otherwise, it is 2 bytes."

So you code a function which reads one byte/component RGB data, then code another to read two byte/component RGB data.

The program can choose which to call once it has read the value of Maxval.

Edit {

According to the document at that link, the image data in a 'P6' ppm is binary.

So if MaxValue is <256, and hence the data for each colour component is one byte, then reading three bytes, with three calls of fgetc(fp) would return the binary value of one RGB pixel.

If the program has read the header, it has the values of width and height for the image data. So it could allocate an array for every row (width wide of RGB pixels), and an array of pointers to each allocated pixel row array. Then read the binary data into each row, and the program has something straightforward to operate on; a 2d array.

} end edit

My reading of your question suggests you already know how to read one byte data using fgetc.

Edit - it seems like this is irrelevant: You can read two byte data by calling fgetc twice, and shifting and bit or-ing the data, e.g. (partly ignoring error checking):

int a = fgetc(fp);
int b = fgetc(fp);
if (a >= 0 && b >= 0) { // then all is okay
    unsigned int twobyte = (a<<8) | b; // or (b<<8) | a; depending on byte order
// ...
gbulmer
  • 4,210
  • 18
  • 20