cdaebf51f36aac73a2c6c3282820c1042c61adca
[libjh.git] / ppm.c
1 // Copyright (2013) Jann Horn <jann@thejh.net>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <assert.h>
6 #include <string.h>
7 #include <errno.h>
8
9 HEADER typedef struct {
10 HEADER   int width, height;
11 HEADER   unsigned char *data;
12 HEADER   int data_size;
13 HEADER } pnm_image;
14
15 pnm_image *read_image(char *path) {
16   int saved_errno = 0;
17   
18   // prepare stuff
19   FILE *f = fopen(path, "r");
20   if (!f) return NULL;
21   pnm_image *result = malloc(sizeof(pnm_image));
22   if (!result) { saved_errno = errno; goto out_close; }
23   
24   // read header
25   int line = 0;
26   int bufsize = 1024;
27   char *buf = malloc(bufsize);
28   while (line < 3) {
29     assert(fgets(buf, bufsize, f) == buf);
30     if (buf[0] == '#') continue;
31     switch (line) {
32       case 0: {
33         if (strcmp(buf, "P6\n")) {
34           saved_errno = ENOEXEC;
35           free(result);
36           goto out_freebuf;
37         }
38         break;
39       }
40       case 1: {
41         sscanf(buf, "%i %i", &result->width, &result->height);
42         result->data_size = 3 * result->width * result->height;
43         result->data = malloc(result->data_size);
44         // FIXME NULL check?
45         break;
46       }
47       case 2: {
48         if (strcmp(buf, "255\n")) {
49           saved_errno = EINVAL;
50           free(result->data);
51           free(result);
52           goto out_freebuf;
53         }
54         break;
55       }
56       default: assert(0);
57     }
58     line++;
59   }
60   
61   // read pixel data
62   assert(fread(result->data, result->data_size, 1, f) == 1);
63
64   // clean up
65 out_freebuf:
66   free(buf);
67 out_close:
68   fclose(f);
69   if (saved_errno) errno = saved_errno;
70   return result;
71 }