#include #include #include #include #include #include #include #include <9p.h> #include "mapbook.h" #include "imgfs.h" #include "ifslib.h" #include "import_ppm.h" int ppm_fd, red_fd, green_fd, blue_fd; int magic, width, height, maxval; float scalar; enum { /* Channel descriptors */ CRGB = 0, /* three channels, no map */ CYCbCr = 1, /* three channels, no map, level-shifted 601 color space */ CY = 2, /* one channel, luminance */ CRGB1 = 3, /* one channel, map present */ CRGBV = 4, /* one channel, map is RGBV, understood */ CRGB24 = 5, /* one channel in correct data order for loadimage(RGB24) */ CRGBA32 = 6, /* one channel in correct data order for loadimage(RGBA32) */ CYA16 = 7, /* one channel in correct data order for loadimage(Grey8+Alpha8) */ CRGBVA16= 8, /* one channel in correct data order for loadimage(CMAP8+Alpha8) */ /* GIF flags */ TRANSP = 1, INPUT = 2, DISPMASK = 7<<2 }; static int bitc, nbit; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } typedef struct Pix Pix; struct Pix { char magic; int maxcol; int (*fetch)(Biobufhdr*); int nchan; int chandesc; int invert; void (*flush)(Biobufhdr*); }; static Pix pix[] = { { '1', 1, Bgetdecimalbit, 1, CY, 1, nil }, /* portable bitmap */ { '4', 1, Bgetbit, 1, CY, 1, Bflushbit }, /* raw portable bitmap */ { '2', 0, Bgetint, 1, CY, 0, nil }, /* portable greymap */ { '5', 0, Bgetc, 1, CY, 0, nil }, /* raw portable greymap */ { '3', 0, Bgetint, 3, CRGB, 0, nil }, /* portable pixmap */ { '6', 0, Bgetc, 3, CRGB, 0, nil }, /* raw portable pixmap */ { 0 }, }; RGBint * free_rgb(RGBint *rgb) { if(rgb) { free(rgb->r); free(rgb->g); free(rgb->b); } return nil; } RGBint * readppm(Biobuf *b) { RGBint *rgb; int i, c; int (*fetch)(Biobufhdr*); Pix *p; int pixels; if(Bgetc(b) != 'P') { fprint(2, "Doubt it's a ppm"); return nil; } c = Bgetc(b); for(p=pix; p->magic; p++) if(p->magic == c) break; if(p->magic == 0) { fprint(2, "Bad magic"); return nil; } if(c != '3' && c != '6') { fprint(2, "sorry, RGB only"); return nil; } rgb = (RGBint*)mallocz(sizeof(RGBint), 1); rgb->width = Bgetint(b); rgb->height = Bgetint(b); if(rgb->width <= 0 || rgb->height <= 0){ fprint(2, "width or height < 0"); free_rgb(rgb); return nil; } rgb->maxcol = p->maxcol; if(rgb->maxcol == 0) { rgb->maxcol = Bgetint(b); if(rgb->maxcol <= 0) { fprint(2, "rgb->maxcol <= 0"); free_rgb(rgb); return nil; } } pixels = rgb->width * rgb->height; rgb->r = (int*)mallocz(sizeof(int)*pixels, 1); rgb->g = (int*)mallocz(sizeof(int)*pixels, 1); rgb->b = (int*)mallocz(sizeof(int)*pixels, 1); fetch = p->fetch; for(i=0; rgb && i < pixels; i++) if(((rgb->r[i] = (*fetch)(b)) < 0) || ((rgb->g[i] = (*fetch)(b)) < 0) || ((rgb->b[i] = (*fetch)(b)) < 0)) rgb = free_rgb(rgb); return rgb; } char * import_ppm(Aux *aux, char *fname) { RGBint *rgb; Biobuf b; int pixels; int i; Bitmap *target; int fd = open(fname, OREAD); if(fd == -1) return nil; if(Binit(&b, fd, OREAD) != -1) { rgb = readppm(&b); Bterm(&b); if(rgb) { clear_mapbook(aux->mapbook); aux->mapbook->width = rgb->width; aux->mapbook->height = rgb->height; pixels = rgb->width * rgb->height; target = get_or_create_bitmap(aux->mapbook, id_red); for(i = 0; i < pixels; i++) target->data[i] = 255 * rgb->r[i] / rgb->maxcol; target = get_or_create_bitmap(aux->mapbook, id_green); for(i = 0; i < pixels; i++) target->data[i] = 255 * rgb->g[i] / rgb->maxcol; target = get_or_create_bitmap(aux->mapbook, id_blue); for(i = 0; i < pixels; i++) target->data[i] = 255 * rgb->b[i] / rgb->maxcol; free_rgb(rgb); } } close(fd); return nil; }