added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / gfx / image_ppm.c
1 #include "image.h"
2 #include <stdio.h>
3
4 #ifdef IMGLIB_USE_PPM
5
6 #include <stdlib.h>
7 #include <ctype.h>
8 #include "color_bits.h"
9
10
11 int check_ppm(FILE *fp) {
12         fseek(fp, 0, SEEK_SET);
13         if(fgetc(fp) == 'P' && fgetc(fp) == '6') {
14                 return 1;
15         }
16         return 0;
17 }
18
19 static int read_to_wspace(FILE *fp, char *buf, int bsize) {
20         int c, count = 0;
21         
22         while((c = fgetc(fp)) != -1 && !isspace(c) && count < bsize - 1) {
23                 if(c == '#') {
24                         while((c = fgetc(fp)) != -1 && c != '\n' && c != '\r');
25                         c = fgetc(fp);
26                         if(c == '\n' || c == '\r') continue;
27                 }
28                 *buf++ = c;
29                 count++;
30         }
31         *buf = 0;
32         
33         while((c = fgetc(fp)) != -1 && isspace(c));
34         ungetc(c, fp);
35         return count;
36 }
37
38 void *load_ppm(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
39         char buf[64];
40         int bytes, raw;
41         unsigned int w, h, i, sz;
42         uint32_t *pixels;
43         
44         fseek(fp, 0, SEEK_SET);
45         
46         bytes = read_to_wspace(fp, buf, 64);
47         raw = buf[1] == '6';
48
49         if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
50                 fclose(fp);
51                 return 0;
52         }
53         if(!isdigit(*buf)) {
54                 fprintf(fp, "load_ppm: invalid width: %s", buf);
55                 fclose(fp);
56                 return 0;
57         }
58         w = atoi(buf);
59
60         if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
61                 fclose(fp);
62                 return 0;
63         }
64         if(!isdigit(*buf)) {
65                 fprintf(fp, "load_ppm: invalid height: %s", buf);
66                 fclose(fp);
67                 return 0;
68         }
69         h = atoi(buf);
70
71         if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
72                 fclose(fp);
73                 return 0;
74         }
75         if(!isdigit(*buf) || atoi(buf) != 255) {
76                 fprintf(fp, "load_ppm: invalid or unsupported max value: %s", buf);
77                 fclose(fp);
78                 return 0;
79         }
80
81         if(!(pixels = malloc(w * h * sizeof *pixels))) {
82                 fputs("malloc failed", fp);
83                 fclose(fp);
84                 return 0;
85         }
86
87         sz = h * w;
88         for(i=0; i<sz; i++) {
89                 int r = fgetc(fp);
90                 int g = fgetc(fp);
91                 int b = fgetc(fp);
92
93                 if(r == -1 || g == -1 || b == -1) {
94                         free(pixels);
95                         fclose(fp);
96                         fputs("load_ppm: EOF while reading pixel data", fp);
97                         return 0;
98                 }
99                 pixels[i] = PACK_COLOR24(r, g, b);
100         }
101
102         fclose(fp);
103
104         if(xsz) *xsz = w;
105         if(ysz) *ysz = h;
106         return pixels;
107 }
108
109 int save_ppm(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
110         int i, sz = xsz * ysz;
111         uint32_t *ptr = pixels;
112         
113         fprintf(fp, "P6\n%lu %lu\n255\n# 3dengfx PPM file writer\n", xsz, ysz);
114
115         for(i=0; i<sz; i++) {
116                 int r = (*ptr & RED_MASK32) >> RED_SHIFT32;
117                 int g = (*ptr & GREEN_MASK32) >> GREEN_SHIFT32;
118                 int b = (*ptr++ & BLUE_MASK32) >> BLUE_SHIFT32;
119
120                 if(fputc(r, fp) == EOF || fputc(g, fp) == EOF || fputc(b, fp) == EOF) {
121                         fputs("save_ppm: failed to write to file", stderr);
122                         fclose(fp);
123                         return -1;
124                 }
125         }
126
127         fclose(fp);
128         return 0;
129 }
130
131 #endif  /* IMGLIB_USE_PPM */