aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c2
-rw-r--r--src/netpbm.c105
2 files changed, 107 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
index cddb436..3a669c6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,10 +26,12 @@ extern struct imageformat libjpeg;
extern struct imageformat giflib;
extern struct imageformat libpng;
extern struct imageformat bmp;
+extern struct imageformat netpbm;
struct imageformat *formats[] = {
&libjpeg,
&bmp,
&libpng,
+ &netpbm,
&giflib, /* HACK! make gif last (uses read()) */
NULL
};
diff --git a/src/netpbm.c b/src/netpbm.c
new file mode 100644
index 0000000..e6f6851
--- /dev/null
+++ b/src/netpbm.c
@@ -0,0 +1,105 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "meh.h"
+
+struct netpbm_t{
+ struct image img;
+ FILE *f;
+ char format;
+ unsigned int maxval;
+};
+
+void skipspace(FILE *f){
+ int c;
+ for(;;){
+ c = fgetc(f);
+ while(isspace(c))
+ c = fgetc(f);
+ if(c == '#')
+ while(fgetc(f) != '\n');
+ else
+ break;
+ }
+ ungetc(c, f);
+}
+
+struct image *netpbm_open(FILE *f){
+ struct netpbm_t *b;
+ rewind(f);
+
+ char format;
+ if(fgetc(f) != 'P')
+ return NULL;
+ format = fgetc(f);
+ if(format > '6' || format < '1')
+ return NULL;
+
+ b = malloc(sizeof(struct netpbm_t));
+ b->format = format;
+
+ skipspace(f);
+ fscanf(f, "%u", &b->img.bufwidth);
+ skipspace(f);
+ fscanf(f, "%u", &b->img.bufheight);
+ if(format == '1' || format == '4'){
+ b->maxval = 1;
+ }else{
+ skipspace(f);
+ fscanf(f, "%u", &b->maxval);
+ }
+
+ /* whitespace character */
+ fgetc(f);
+
+ b->f = f;
+
+ return (struct image *)b;
+}
+
+int netpbm_read(struct image *img){
+ struct netpbm_t *b = (struct netpbm_t *)img;
+ FILE *f = b->f;
+ int a = 0;
+
+ int left = img->bufwidth * img->bufheight;
+ int j, c;
+
+ if(b->format == '4'){
+ while(left){
+ c = fgetc(f);
+ for(j = 0; j < 8 && left; j++){
+ int val = (c & 1) ? 0 : 255;
+ img->buf[a++] = val;
+ img->buf[a++] = val;
+ img->buf[a++] = val;
+ c >>= 1;
+ left--;
+ }
+ }
+ }else if(b->format == '6'){
+ while(left){
+ img->buf[a++] = fgetc(f);
+ img->buf[a++] = fgetc(f);
+ img->buf[a++] = fgetc(f);
+ left--;
+ }
+ }
+
+ img->state = LOADED;
+ return 0;
+}
+
+void netpbm_close(struct image *img){
+ struct netpbm_t *b = (struct netpbm_t *)img;
+ fclose(b->f);
+}
+
+struct imageformat netpbm = {
+ netpbm_open,
+ NULL,
+ netpbm_read,
+ netpbm_close
+};
+