17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <draw.h>
57dd7cddfSDavid du Colombier #include <ctype.h>
67dd7cddfSDavid du Colombier #include "imagefile.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier Rawimage *readppm(Biobuf*, Rawimage*);
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier /*
117dd7cddfSDavid du Colombier * fetch a non-comment character.
127dd7cddfSDavid du Colombier */
137dd7cddfSDavid du Colombier static
147dd7cddfSDavid du Colombier int
Bgetch(Biobufhdr * b)157dd7cddfSDavid du Colombier Bgetch(Biobufhdr *b)
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier int c;
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier for(;;) {
207dd7cddfSDavid du Colombier c = Bgetc(b);
217dd7cddfSDavid du Colombier if(c == '#') {
227dd7cddfSDavid du Colombier while((c = Bgetc(b)) != Beof && c != '\n')
237dd7cddfSDavid du Colombier ;
247dd7cddfSDavid du Colombier }
257dd7cddfSDavid du Colombier return c;
267dd7cddfSDavid du Colombier }
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier /*
307dd7cddfSDavid du Colombier * fetch a nonnegative decimal integer.
317dd7cddfSDavid du Colombier */
327dd7cddfSDavid du Colombier static
337dd7cddfSDavid du Colombier int
Bgetint(Biobufhdr * b)347dd7cddfSDavid du Colombier Bgetint(Biobufhdr *b)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier int c;
377dd7cddfSDavid du Colombier int i;
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier while((c = Bgetch(b)) != Beof && !isdigit(c))
407dd7cddfSDavid du Colombier ;
417dd7cddfSDavid du Colombier if(c == Beof)
427dd7cddfSDavid du Colombier return -1;
437dd7cddfSDavid du Colombier
447dd7cddfSDavid du Colombier i = 0;
457dd7cddfSDavid du Colombier do {
467dd7cddfSDavid du Colombier i = i*10 + (c-'0');
477dd7cddfSDavid du Colombier } while((c = Bgetch(b)) != Beof && isdigit(c));
487dd7cddfSDavid du Colombier
497dd7cddfSDavid du Colombier return i;
507dd7cddfSDavid du Colombier }
517dd7cddfSDavid du Colombier
527dd7cddfSDavid du Colombier static
537dd7cddfSDavid du Colombier int
Bgetdecimalbit(Biobufhdr * b)547dd7cddfSDavid du Colombier Bgetdecimalbit(Biobufhdr *b)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier int c;
577dd7cddfSDavid du Colombier while((c = Bgetch(b)) != Beof && c != '0' && c != '1')
587dd7cddfSDavid du Colombier ;
597dd7cddfSDavid du Colombier if(c == Beof)
607dd7cddfSDavid du Colombier return -1;
617dd7cddfSDavid du Colombier return c == '1';
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier static int bitc, nbit;
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier static
677dd7cddfSDavid du Colombier int
Bgetbit(Biobufhdr * b)687dd7cddfSDavid du Colombier Bgetbit(Biobufhdr *b)
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier if(nbit == 0) {
717dd7cddfSDavid du Colombier nbit = 8;
727dd7cddfSDavid du Colombier bitc = Bgetc(b);
737dd7cddfSDavid du Colombier if(bitc == -1)
747dd7cddfSDavid du Colombier return -1;
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier nbit--;
77*9863c128SDavid du Colombier return (bitc >> nbit) & 0x1;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier static
817dd7cddfSDavid du Colombier void
Bflushbit(Biobufhdr *)827dd7cddfSDavid du Colombier Bflushbit(Biobufhdr*)
837dd7cddfSDavid du Colombier {
847dd7cddfSDavid du Colombier nbit = 0;
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier Rawimage**
readpixmap(int fd,int colorspace)897dd7cddfSDavid du Colombier readpixmap(int fd, int colorspace)
907dd7cddfSDavid du Colombier {
917dd7cddfSDavid du Colombier Rawimage **array, *a;
927dd7cddfSDavid du Colombier Biobuf b;
939a747e4fSDavid du Colombier char buf[ERRMAX];
947dd7cddfSDavid du Colombier int i;
957dd7cddfSDavid du Colombier char *e;
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier USED(colorspace);
987dd7cddfSDavid du Colombier if(Binit(&b, fd, OREAD) < 0)
997dd7cddfSDavid du Colombier return nil;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier werrstr("");
1027dd7cddfSDavid du Colombier e = "out of memory";
1037dd7cddfSDavid du Colombier if((array = malloc(sizeof *array)) == nil)
1047dd7cddfSDavid du Colombier goto Error;
1057dd7cddfSDavid du Colombier if((array[0] = malloc(sizeof *array[0])) == nil)
1067dd7cddfSDavid du Colombier goto Error;
1077dd7cddfSDavid du Colombier memset(array[0], 0, sizeof *array[0]);
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier for(i=0; i<3; i++)
1107dd7cddfSDavid du Colombier array[0]->chans[i] = nil;
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier e = "bad file format";
1137dd7cddfSDavid du Colombier switch(Bgetc(&b)) {
1147dd7cddfSDavid du Colombier case 'P':
1157dd7cddfSDavid du Colombier Bungetc(&b);
1167dd7cddfSDavid du Colombier a = readppm(&b, array[0]);
1177dd7cddfSDavid du Colombier break;
1187dd7cddfSDavid du Colombier default:
1197dd7cddfSDavid du Colombier a = nil;
1207dd7cddfSDavid du Colombier break;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier if(a == nil)
1237dd7cddfSDavid du Colombier goto Error;
1247dd7cddfSDavid du Colombier array[0] = a;
1257dd7cddfSDavid du Colombier
1267dd7cddfSDavid du Colombier return array;
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier Error:
1297dd7cddfSDavid du Colombier if(array)
1307dd7cddfSDavid du Colombier free(array[0]);
1317dd7cddfSDavid du Colombier free(array);
1327dd7cddfSDavid du Colombier
1339a747e4fSDavid du Colombier errstr(buf, sizeof buf);
1347dd7cddfSDavid du Colombier if(buf[0] == 0)
1357dd7cddfSDavid du Colombier strcpy(buf, e);
1369a747e4fSDavid du Colombier errstr(buf, sizeof buf);
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier return nil;
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier typedef struct Pix Pix;
1427dd7cddfSDavid du Colombier struct Pix {
1437dd7cddfSDavid du Colombier char magic;
1447dd7cddfSDavid du Colombier int maxcol;
1457dd7cddfSDavid du Colombier int (*fetch)(Biobufhdr*);
1467dd7cddfSDavid du Colombier int nchan;
1477dd7cddfSDavid du Colombier int chandesc;
1487dd7cddfSDavid du Colombier int invert;
1497dd7cddfSDavid du Colombier void (*flush)(Biobufhdr*);
1507dd7cddfSDavid du Colombier };
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier static Pix pix[] = {
1537dd7cddfSDavid du Colombier { '1', 1, Bgetdecimalbit, 1, CY, 1, nil }, /* portable bitmap */
1547dd7cddfSDavid du Colombier { '4', 1, Bgetbit, 1, CY, 1, Bflushbit }, /* raw portable bitmap */
1557dd7cddfSDavid du Colombier { '2', 0, Bgetint, 1, CY, 0, nil }, /* portable greymap */
1567dd7cddfSDavid du Colombier { '5', 0, Bgetc, 1, CY, 0, nil }, /* raw portable greymap */
1577dd7cddfSDavid du Colombier { '3', 0, Bgetint, 3, CRGB, 0, nil }, /* portable pixmap */
1587dd7cddfSDavid du Colombier { '6', 0, Bgetc, 3, CRGB, 0, nil }, /* raw portable pixmap */
1597dd7cddfSDavid du Colombier { 0 },
1607dd7cddfSDavid du Colombier };
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier Rawimage*
readppm(Biobuf * b,Rawimage * a)1637dd7cddfSDavid du Colombier readppm(Biobuf *b, Rawimage *a)
1647dd7cddfSDavid du Colombier {
1657dd7cddfSDavid du Colombier int i, ch, wid, ht, r, c;
1667dd7cddfSDavid du Colombier int maxcol, nchan, invert;
1677dd7cddfSDavid du Colombier int (*fetch)(Biobufhdr*);
1687dd7cddfSDavid du Colombier uchar *rgb[3];
1699a747e4fSDavid du Colombier char buf[ERRMAX];
1707dd7cddfSDavid du Colombier char *e;
1717dd7cddfSDavid du Colombier Pix *p;
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier e = "bad file format";
1747dd7cddfSDavid du Colombier if(Bgetc(b) != 'P')
1757dd7cddfSDavid du Colombier goto Error;
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier c = Bgetc(b);
1787dd7cddfSDavid du Colombier for(p=pix; p->magic; p++)
1797dd7cddfSDavid du Colombier if(p->magic == c)
1807dd7cddfSDavid du Colombier break;
1817dd7cddfSDavid du Colombier if(p->magic == 0)
1827dd7cddfSDavid du Colombier goto Error;
1837dd7cddfSDavid du Colombier
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier wid = Bgetint(b);
1867dd7cddfSDavid du Colombier ht = Bgetint(b);
1877dd7cddfSDavid du Colombier if(wid <= 0 || ht <= 0)
1887dd7cddfSDavid du Colombier goto Error;
1897dd7cddfSDavid du Colombier a->r = Rect(0,0,wid,ht);
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier maxcol = p->maxcol;
1927dd7cddfSDavid du Colombier if(maxcol == 0) {
1937dd7cddfSDavid du Colombier maxcol = Bgetint(b);
1947dd7cddfSDavid du Colombier if(maxcol <= 0)
1957dd7cddfSDavid du Colombier goto Error;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier e = "out of memory";
1997dd7cddfSDavid du Colombier for(i=0; i<p->nchan; i++)
2007dd7cddfSDavid du Colombier if((rgb[i] = a->chans[i] = malloc(wid*ht)) == nil)
2017dd7cddfSDavid du Colombier goto Error;
2027dd7cddfSDavid du Colombier a->nchans = p->nchan;
2037dd7cddfSDavid du Colombier a->chanlen = wid*ht;
2047dd7cddfSDavid du Colombier a->chandesc = p->chandesc;
2057dd7cddfSDavid du Colombier
2067dd7cddfSDavid du Colombier e = "error reading file";
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier fetch = p->fetch;
2097dd7cddfSDavid du Colombier nchan = p->nchan;
2107dd7cddfSDavid du Colombier invert = p->invert;
2117dd7cddfSDavid du Colombier for(r=0; r<ht; r++) {
2127dd7cddfSDavid du Colombier for(c=0; c<wid; c++) {
2137dd7cddfSDavid du Colombier for(i=0; i<nchan; i++) {
2147dd7cddfSDavid du Colombier if((ch = (*fetch)(b)) < 0)
2157dd7cddfSDavid du Colombier goto Error;
2167dd7cddfSDavid du Colombier if(invert)
2177dd7cddfSDavid du Colombier ch = maxcol - ch;
2187dd7cddfSDavid du Colombier *rgb[i]++ = (ch * 255)/maxcol;
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier if(p->flush)
2227dd7cddfSDavid du Colombier (*p->flush)(b);
2237dd7cddfSDavid du Colombier }
2247dd7cddfSDavid du Colombier
2257dd7cddfSDavid du Colombier return a;
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier Error:
2289a747e4fSDavid du Colombier errstr(buf, sizeof buf);
2297dd7cddfSDavid du Colombier if(buf[0] == 0)
2307dd7cddfSDavid du Colombier strcpy(buf, e);
2319a747e4fSDavid du Colombier errstr(buf, sizeof buf);
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier for(i=0; i<3; i++)
2347dd7cddfSDavid du Colombier free(a->chans[i]);
2357dd7cddfSDavid du Colombier free(a->cmap);
2367dd7cddfSDavid du Colombier return nil;
2377dd7cddfSDavid du Colombier }
238