This is my attempt to read the header of an PBM/PGM/PPM.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define MAX_LEN 1024
#define PPM_DELIM "\r\n\t "
typedef struct ppm_t {
uint8_t magic;
uint16_t width;
uint16_t height;
uint16_t brightness;
void *data;
} ppm;
int parseHeader(ppm *picture, FILE *input) {
char line[MAX_LEN] = {0}, *char_tmp;
int ppm_magic = -1, ppm_width = -1, ppm_height = -1, ppm_brightness = -1, ppm_header = 1;
while(ppm_header) {
fgets(line, MAX_LEN, input);
//check for comments
if (line[0] == '#') continue;
char_tmp = strtok(line, PPM_DELIM);
while (char_tmp) {
// get PPM format
if(ppm_magic < 0) {
if(char_tmp[0] == 'P') {
if ((sscanf(++char_tmp, "%d", &ppm_magic)) != 1) {
fprintf(stderr, "could not read magic number. exit.\n");
return -1;
}
else if(ppm_magic < 1 || ppm_magic > 6) {
fprintf(stderr, "invalid magic number. exit.\n");
return -1;
}
}
else {
fprintf(stderr, "no magic number found. is it really a PPM? exit.\n");
return -1;
}
}
else {
// get width
if (ppm_width < 0) {
if ((sscanf(char_tmp, "%d", &ppm_width)) != 1) {
fprintf(stderr, "could not read width. exit.\n");
return -1;
}
}
// get hight
else if (ppm_height < 0) {
if ((sscanf(char_tmp, "%d", &ppm_height)) != 1) {
fprintf(stderr, "could not read height. exit.\n");
return -1;
}
}
// get brightness
else if (ppm_brightness < 0) {
if ((sscanf(char_tmp, "%d", &ppm_brightness)) != 1) {
fprintf(stderr, "could not read brightness. exit.\n");
return -1;
}
}
}
char_tmp = strtok(NULL, PPM_DELIM);
}
if (ppm_magic > 0 && ppm_width > 0 && ppm_height > 0 && ppm_brightness > 0) ppm_header = 0;
}
picture->magic = ppm_magic;
picture->width = ppm_width;
picture->height = ppm_height;
picture->brightness = ppm_brightness;
picture->data = NULL;
return 0;
}
int main (int argc, char *argv[]) {
FILE *input = NULL;
ppm my_picture;
if (argc < 2) {
fprintf(stderr, "too few arguments.\n");
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
return EXIT_FAILURE;
}
if ((input = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "could not open file '%s'.\n", argv[1]);
return EXIT_FAILURE;
}
if (parseHeader(&my_picture, input) < 0) {
fprintf(stderr, "something went wrong.\n");
return EXIT_FAILURE;
}
printf("--- picture data ---\n");
printf("Format : %d\n", my_picture.magic);
printf("Width : %d\n", my_picture.width);
printf("Height : %d\n", my_picture.height);
printf("Brightness: %d\n", my_picture.brightness);
[…]
You can see i only use 'fgets()' and 'sscanf()'. Not playing around with 'getc()' and 'ungetc()'.