URI:
       treadppm.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       treadppm.c (3603B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <draw.h>
            5 #include <ctype.h>
            6 #include "imagefile.h"
            7 
            8 Rawimage *readppm(Biobuf*, Rawimage*);
            9 
           10 /*
           11  * fetch a non-comment character.
           12  */
           13 static
           14 int
           15 Bgetch(Biobuf *b)
           16 {
           17         int c;
           18 
           19         c = Bgetc(b);
           20         if(c == '#') {
           21                 while((c = Bgetc(b)) != Beof && c != '\n')
           22                         ;
           23         }
           24         return c;
           25 }
           26 
           27 /*
           28  * fetch a nonnegative decimal integer.
           29  */
           30 static
           31 int
           32 Bgetint(Biobuf *b)
           33 {
           34         int c;
           35         int i;
           36 
           37         while((c = Bgetch(b)) != Beof && !isdigit(c))
           38                 ;
           39         if(c == Beof)
           40                 return -1;
           41 
           42         i = 0;
           43         do {
           44                 i = i*10 + (c-'0');
           45         } while((c = Bgetch(b)) != Beof && isdigit(c));
           46 
           47         return i;
           48 }
           49 
           50 static
           51 int
           52 Bgetdecimalbit(Biobuf *b)
           53 {
           54         int c;
           55         while((c = Bgetch(b)) != Beof && c != '0' && c != '1')
           56                 ;
           57         if(c == Beof)
           58                 return -1;
           59         return c == '1';
           60 }
           61 
           62 static int bitc, nbit;
           63 
           64 static
           65 int
           66 Bgetbit(Biobuf *b)
           67 {
           68         if(nbit == 0) {
           69                 nbit = 8;
           70                 bitc = Bgetc(b);
           71                 if(bitc == -1)
           72                         return -1;
           73         }
           74         nbit--;
           75         return (bitc >> (nbit-1)) & 0x1;
           76 }
           77 
           78 static
           79 void
           80 Bflushbit(Biobuf *b)
           81 {
           82         USED(b);
           83         nbit = 0;
           84 }
           85 
           86 
           87 Rawimage**
           88 readpixmap(int fd, int colorspace)
           89 {
           90         Rawimage **array, *a;
           91         Biobuf b;
           92         char buf[ERRMAX];
           93         int i;
           94         char *e;
           95 
           96         USED(colorspace);
           97         if(Binit(&b, fd, OREAD) < 0)
           98                 return nil;
           99 
          100         werrstr("");
          101         e = "out of memory";
          102         if((array = malloc(sizeof *array)) == nil)
          103                 goto Error;
          104         if((array[0] = malloc(sizeof *array[0])) == nil)
          105                 goto Error;
          106         memset(array[0], 0, sizeof *array[0]);
          107 
          108         for(i=0; i<3; i++)
          109                 array[0]->chans[i] = nil;
          110 
          111         e = "bad file format";
          112         switch(Bgetc(&b)) {
          113         case 'P':
          114                 Bungetc(&b);
          115                 a = readppm(&b, array[0]);
          116                 break;
          117         default:
          118                 a = nil;
          119                 break;
          120         }
          121         if(a == nil)
          122                 goto Error;
          123         array[0] = a;
          124 
          125         return array;
          126 
          127 Error:
          128         if(array)
          129                 free(array[0]);
          130         free(array);
          131 
          132         errstr(buf, sizeof buf);
          133         if(buf[0] == 0)
          134                 strcpy(buf, e);
          135         errstr(buf, sizeof buf);
          136 
          137         return nil;
          138 }
          139 
          140 typedef struct Pix        Pix;
          141 struct Pix {
          142         char magic;
          143         int        maxcol;
          144         int        (*fetch)(Biobuf*);
          145         int        nchan;
          146         int        chandesc;
          147         int        invert;
          148         void        (*flush)(Biobuf*);
          149 };
          150 
          151 static Pix pix[] = {
          152         { '1', 1, Bgetdecimalbit, 1, CY, 1, 0 },        /* portable bitmap */
          153         { '4', 1, Bgetbit, 1, CY, 1, Bflushbit },        /* raw portable bitmap */
          154         { '2', 0, Bgetint, 1, CY, 0, 0 },        /* portable greymap */
          155         { '5', 0, Bgetc, 1, CY, 0, 0 },        /* raw portable greymap */
          156         { '3', 0, Bgetint, 3, CRGB, 0, 0 },        /* portable pixmap */
          157         { '6', 0, Bgetc, 3, CRGB, 0, 0 },        /* raw portable pixmap */
          158         { 0 }
          159 };
          160 
          161 Rawimage*
          162 readppm(Biobuf *b, Rawimage *a)
          163 {
          164         int i, ch, wid, ht, r, c;
          165         int maxcol, nchan, invert;
          166         int (*fetch)(Biobuf*);
          167         uchar *rgb[3];
          168         char buf[ERRMAX];
          169         char *e;
          170         Pix *p;
          171 
          172         e = "bad file format";
          173         if(Bgetc(b) != 'P')
          174                 goto Error;
          175 
          176         c = Bgetc(b);
          177         for(p=pix; p->magic; p++)
          178                 if(p->magic == c)
          179                         break;
          180         if(p->magic == 0)
          181                 goto Error;
          182 
          183 
          184         wid = Bgetint(b);
          185         ht = Bgetint(b);
          186         if(wid <= 0 || ht <= 0)
          187                 goto Error;
          188         a->r = Rect(0,0,wid,ht);
          189 
          190         maxcol = p->maxcol;
          191         if(maxcol == 0) {
          192                 maxcol = Bgetint(b);
          193                 if(maxcol <= 0)
          194                         goto Error;
          195         }
          196 
          197         e = "out of memory";
          198         for(i=0; i<p->nchan; i++)
          199                 if((rgb[i] = a->chans[i] = malloc(wid*ht)) == nil)
          200                         goto Error;
          201         a->nchans = p->nchan;
          202         a->chanlen = wid*ht;
          203         a->chandesc = p->chandesc;
          204 
          205         e = "error reading file";
          206 
          207         fetch = p->fetch;
          208         nchan = p->nchan;
          209         invert = p->invert;
          210         for(r=0; r<ht; r++) {
          211                 for(c=0; c<wid; c++) {
          212                         for(i=0; i<nchan; i++) {
          213                                 if((ch = (*fetch)(b)) < 0)
          214                                         goto Error;
          215                                 if(invert)
          216                                         ch = maxcol - ch;
          217                                 *rgb[i]++ = (ch * 255)/maxcol;
          218                         }
          219                 }
          220                 if(p->flush)
          221                         (*p->flush)(b);
          222         }
          223 
          224         return a;
          225 
          226 Error:
          227         errstr(buf, sizeof buf);
          228         if(buf[0] == 0)
          229                 strcpy(buf, e);
          230         errstr(buf, sizeof buf);
          231 
          232         for(i=0; i<3; i++)
          233                 free(a->chans[i]);
          234         free(a->cmap);
          235         return nil;
          236 }