1

I'm trying to parse through a ppm file, but first need to verify if the header info is correct. A ppm file may have the following formats:

P3
100 100
255
data...

or

p3
100 100
255
data...

I'm using fscanf (file_stream, "P3 %d %d %d", &width, &height, &max_colour); to verify the header info. What I'd like to know is, how to move on to reading the data (char by char) after verifying the header info.

endmade
  • 159
  • 1
  • 4
  • 9

4 Answers4

2

Assuming the header tells you the size of the data then allocate a block of memory that is large enough and use fread() to read it in a single call - this is MUCH faster than reading a byte at a time.

  unsigned char *data = malloc(width*height); // or whaterver size
  fread(file_stream,width*height,1,data);
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
1

Add a %*[\n] to the end of your fscanf string to eat the last newline in the header, then you can use fread to read raw bytes from the remainder of the file (assuming you opened it in binary mode).

Jeremiah Willcock
  • 30,161
  • 7
  • 76
  • 78
  • 1
    Actually, putting a `\n` in the format string will cause it to eat all consecutive whitespace that there is—if the subsequent binary data happens to begin with any of the bytes `09`, `0A`, or `20` (tab, newline, or space), then they will accidentally be consumed. You really want to use the `%*c` format specifier, which will always eat exactly one char of input. – Adam Rosenfield Mar 07 '11 at 02:54
  • @Adam: Is what I changed it to now correct? That is trying to stop at the first `\n`. It still assumes the file is correct, though, unless you check the `scanf` result properly. – Jeremiah Willcock Mar 07 '11 at 03:02
  • @Adam: Actually, looking at the PPM spec, arbitrary whitespace is not allowed; it's a single newline only. – Jeremiah Willcock Mar 07 '11 at 03:03
0

Is there some reason not to use the netpbm library?

wnoise
  • 9,764
  • 37
  • 47
0

Using fscanf you can read a char with "%c".

char ch;
while (fscanf(file_stream, "%c", &ch) == 1) {
    /* process ch */
}

But instead of fscanf you can use fgetc()

int ch;
while ((ch = fgetc(file_stream)) != EOF) {
    /* process ch */
}

But, assuming a ppm file with ASCII encoding (P1, P2, or P3), fscanf is a really good option.

/* P3 format */
if (fscanf(file_stream, "%d%d%d", &red, &green, &blue) == 3) {
    /* RGB triplet read; process it */
}

Remember to open your file in binary mode if you want to deal with binary PPMs

fopen(filename, "rb");
pmg
  • 106,608
  • 13
  • 126
  • 198