added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / gfx / image_ppm.c
diff --git a/src/3dengfx/src/gfx/image_ppm.c b/src/3dengfx/src/gfx/image_ppm.c
new file mode 100644 (file)
index 0000000..5809078
--- /dev/null
@@ -0,0 +1,131 @@
+#include "image.h"
+#include <stdio.h>
+
+#ifdef IMGLIB_USE_PPM
+
+#include <stdlib.h>
+#include <ctype.h>
+#include "color_bits.h"
+
+
+int check_ppm(FILE *fp) {
+       fseek(fp, 0, SEEK_SET);
+       if(fgetc(fp) == 'P' && fgetc(fp) == '6') {
+               return 1;
+       }
+       return 0;
+}
+
+static int read_to_wspace(FILE *fp, char *buf, int bsize) {
+       int c, count = 0;
+       
+       while((c = fgetc(fp)) != -1 && !isspace(c) && count < bsize - 1) {
+               if(c == '#') {
+                       while((c = fgetc(fp)) != -1 && c != '\n' && c != '\r');
+                       c = fgetc(fp);
+                       if(c == '\n' || c == '\r') continue;
+               }
+               *buf++ = c;
+               count++;
+       }
+       *buf = 0;
+       
+       while((c = fgetc(fp)) != -1 && isspace(c));
+       ungetc(c, fp);
+       return count;
+}
+
+void *load_ppm(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
+       char buf[64];
+       int bytes, raw;
+       unsigned int w, h, i, sz;
+       uint32_t *pixels;
+       
+       fseek(fp, 0, SEEK_SET);
+       
+       bytes = read_to_wspace(fp, buf, 64);
+       raw = buf[1] == '6';
+
+       if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
+               fclose(fp);
+               return 0;
+       }
+       if(!isdigit(*buf)) {
+               fprintf(fp, "load_ppm: invalid width: %s", buf);
+               fclose(fp);
+               return 0;
+       }
+       w = atoi(buf);
+
+       if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
+               fclose(fp);
+               return 0;
+       }
+       if(!isdigit(*buf)) {
+               fprintf(fp, "load_ppm: invalid height: %s", buf);
+               fclose(fp);
+               return 0;
+       }
+       h = atoi(buf);
+
+       if((bytes = read_to_wspace(fp, buf, 64)) == 0) {
+               fclose(fp);
+               return 0;
+       }
+       if(!isdigit(*buf) || atoi(buf) != 255) {
+               fprintf(fp, "load_ppm: invalid or unsupported max value: %s", buf);
+               fclose(fp);
+               return 0;
+       }
+
+       if(!(pixels = malloc(w * h * sizeof *pixels))) {
+               fputs("malloc failed", fp);
+               fclose(fp);
+               return 0;
+       }
+
+       sz = h * w;
+       for(i=0; i<sz; i++) {
+               int r = fgetc(fp);
+               int g = fgetc(fp);
+               int b = fgetc(fp);
+
+               if(r == -1 || g == -1 || b == -1) {
+                       free(pixels);
+                       fclose(fp);
+                       fputs("load_ppm: EOF while reading pixel data", fp);
+                       return 0;
+               }
+               pixels[i] = PACK_COLOR24(r, g, b);
+       }
+
+       fclose(fp);
+
+       if(xsz) *xsz = w;
+       if(ysz) *ysz = h;
+       return pixels;
+}
+
+int save_ppm(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
+       int i, sz = xsz * ysz;
+       uint32_t *ptr = pixels;
+       
+       fprintf(fp, "P6\n%lu %lu\n255\n# 3dengfx PPM file writer\n", xsz, ysz);
+
+       for(i=0; i<sz; i++) {
+               int r = (*ptr & RED_MASK32) >> RED_SHIFT32;
+               int g = (*ptr & GREEN_MASK32) >> GREEN_SHIFT32;
+               int b = (*ptr++ & BLUE_MASK32) >> BLUE_SHIFT32;
+
+               if(fputc(r, fp) == EOF || fputc(g, fp) == EOF || fputc(b, fp) == EOF) {
+                       fputs("save_ppm: failed to write to file", stderr);
+                       fclose(fp);
+                       return -1;
+               }
+       }
+
+       fclose(fp);
+       return 0;
+}
+
+#endif /* IMGLIB_USE_PPM */