home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 564a.lha / wasp_v1.21 / Src.LZH / Src / readgif.c < prev    next >
C/C++ Source or Header  |  1991-10-19  |  15KB  |  627 lines

  1. /* wasp - copyright Steven Reiz 1990, 1991
  2.  * see wasp.c for further info
  3.  * readgif.c, 9/12/90 - 30/1/91,
  4.  * 30/4/91 - 2/6/91, 23/6/91, 30/6/91,
  5.  * 8/7/91
  6.  */
  7.  
  8. #include "wasp.h"
  9. #ifndef NOSH
  10. #include "readgif.sh"
  11. #endif
  12.  
  13. static u_short width, height;
  14. static short bitsperpixel, interlaced, codesize;
  15. static u_short *cm=NULL;
  16. static u_short *rgboverflowrow=NULL;
  17. static u_short *gpp;
  18.  
  19.  
  20. #ifdef __STDC__
  21. read_gif(void)
  22. #else
  23. read_gif()
  24. #endif
  25. {
  26.     char signature[6], separator;
  27.     short y;
  28.  
  29.     cread(signature, 6);
  30.     if (strncmp(signature, "GIF87a", 6)) {
  31.         lseek(infd, 0L, 0);
  32.         return 0;
  33.     }
  34.     if (readscreendescriptor())
  35.         readcolormap();
  36.     cread(&separator, 1);
  37.     if (separator!=',')
  38.     error1(E0_FATAL, E1_GIF, E2_FORMAT, E3_MISS_SEP, ',');
  39.     if (readimagedescriptor())
  40.         readcolormap();
  41.     cread(&separator, 1); codesize=separator;
  42.     printf("GIF input; %d x %d, %d bits/pixel", (int)width, (int)height,
  43.      (int)bitsperpixel);
  44.     if (interlaced)
  45.     printf(", interlaced");
  46.     if (codesize!=bitsperpixel)
  47.     printf(", codesize: %d", (int)codesize);
  48.     putchar('\n'); fflush(stdout);
  49.     if (!outfilename)
  50.     exit(0);
  51.     xsz=width;
  52.     ysz=height;
  53.     rgb=Malloc(ysz*sizeof(u_short *));
  54.     for (y=0; y<ysz; ++y)
  55.         rgb[y]=Calloc(xsz*sizeof(u_short));
  56.     readbody();
  57.     cread(&separator, 1);
  58.     if (separator==',')
  59.         error0(E0_WARNING, E1_GIF, E2_FORMAT, E3_MULTI_IMG);
  60.     else if (separator!=';')
  61.     error1(E0_FATAL, E1_GIF, E2_FORMAT, E3_MISS_SEP, ';');
  62.     return 1;
  63. }
  64.  
  65.  
  66. #ifdef __STDC__
  67. PRIVATE int readscreendescriptor(void)
  68. #else
  69. PRIVATE int readscreendescriptor()
  70. #endif
  71. {
  72.     struct sd_t {
  73.         u_char widthlo, widthhi;
  74.         u_char heightlo, heighthi;
  75.         u_char misc, bgindex, reserved;
  76.     } sd;
  77.  
  78.     cread(&sd, 7);
  79.     bitsperpixel=(sd.misc&7)+1;
  80.     return sd.misc&0x80;
  81. }
  82.  
  83.  
  84. #ifdef __STDC__
  85. PRIVATE int readimagedescriptor(void)
  86. #else
  87. PRIVATE int readimagedescriptor()
  88. #endif
  89. {
  90.     struct id_t {
  91.         u_char xoffsetlo, xoffsethi;
  92.         u_char yoffsetlo, yoffsethi;
  93.         u_char widthlo, widthhi;
  94.         u_char heightlo, heighthi;
  95.         u_char misc;
  96.     } id;
  97.  
  98.     cread(&id, 9);
  99.     width=(id.widthhi<<8)|id.widthlo;
  100.     height=(id.heighthi<<8)|id.heightlo;
  101.     interlaced=(id.misc&0x40 ? 1 : 0);
  102.     if (id.misc&0x80) {
  103.         bitsperpixel=(id.misc&7)+1;
  104.         return 1;
  105.     } else
  106.         return 0;
  107. }
  108.  
  109.  
  110. #ifdef __STDC__
  111. PRIVATE readcolormap(void)
  112. #else
  113. PRIVATE readcolormap()
  114. #endif
  115. {
  116.     char *rgbin, *rgbp;
  117.     int r, g, b, roundin;
  118.     short i, nentries;
  119.  
  120.     roundin=(gifmaptrunc ? 0 : 8);
  121.     nentries=1<<bitsperpixel;
  122.     rgbin=Malloc(nentries*3);
  123.     if (cm)
  124.         free(cm);
  125.     cread(rgbin, (int)(nentries*3));
  126.     cm=Malloc(nentries*2);
  127.     for (i=0, rgbp=rgbin; i<nentries; ++i) {
  128.         r= *rgbp++ & 0xff;
  129.         g= *rgbp++ & 0xff;
  130.         b= *rgbp++ & 0xff;
  131.         r=(r+roundin)>>4; if (r>15) r=15;
  132.         g=(g+roundin)>>4; if (g>15) g=15;
  133.         b=(b+roundin)>>4; if (b>15) b=15;
  134.         cm[i]=(r<<8)|(g<<4)|b;
  135.     }
  136.     free(rgbin);
  137. }
  138.  
  139.  
  140. #define NCODES 6144
  141. static u_short *codes;
  142. static u_short *prefix;
  143. static u_char  *suffix;
  144. static u_char  *stack;
  145. #define NUBYTES 4096
  146. static u_short *ubytes;
  147. #define NBUF 16384
  148. static u_char *buf;
  149. #define NTRANSCHARS 256
  150. static u_char *transchars;
  151. #define NMASKS 64
  152. static u_short *masks;
  153.  
  154.  
  155. #ifdef __STDC__
  156. PRIVATE readbody(void)
  157. #else
  158. PRIVATE readbody()
  159. #endif
  160. {
  161.     codes=Malloc(NCODES*sizeof(u_short));
  162.     ubytes=Malloc(NUBYTES);
  163.     buf=Malloc(NBUF);
  164.     transchars=Malloc(NTRANSCHARS);
  165.     masks=Malloc(NMASKS*sizeof(u_short));
  166.     prefix=Malloc(NCODES*sizeof(u_short));
  167.     suffix=Malloc(NCODES);
  168.     stack=Malloc(NCODES);
  169.     fill_transchars();
  170.     decompress();
  171.     free(codes);
  172.     free(ubytes);
  173.     free(buf);
  174.     free(transchars);
  175.     free(masks);
  176.     free(prefix);
  177.     free(suffix);
  178.     free(stack);
  179. }
  180.  
  181.  
  182. #ifdef __STDC__
  183. PRIVATE short nextrow(int mode)
  184. #else
  185. PRIVATE short nextrow(mode)
  186. int mode;
  187. #endif
  188. {
  189.     static int rowsdone= -1;
  190.     static int phase= -1;
  191.     static int currow;
  192.  
  193.     ++rowsdone;
  194.     counter();
  195.     if (mode) {
  196.         erase_counter(NULL);
  197.         if (rowsdone!=ysz)
  198.         error2(E0_WARNING, E1_GIF, E2_FORMAT, E3_WRONG_NR_ROWS, rowsdone, (int)ysz);
  199.     } else {
  200.         switch (phase) {
  201.         case -1:
  202.             currow=0;
  203.             if (interlaced)
  204.                 phase=1;
  205.             else
  206.                 phase=0;
  207.         break;
  208.         case 0:
  209.             ++currow;
  210.         break;
  211.         case 1:
  212.             currow+=8;
  213.             if (currow>=ysz) {
  214.                 phase=2;
  215.                 currow=4;
  216.             }
  217.         break;
  218.         case 2:
  219.             currow+=8;
  220.             if (currow>=ysz) {
  221.                 phase=3;
  222.                 currow=2;
  223.             }
  224.         break;
  225.         case 3:
  226.             currow+=4;
  227.             if (currow>=ysz) {
  228.                 phase=4;
  229.                 currow=1;
  230.             }
  231.         break;
  232.         case 4:
  233.             currow+=2;
  234.         break;
  235.         }
  236.         if (currow>=ysz) {
  237.             if (!rgboverflowrow)
  238.                 rgboverflowrow=Malloc(xsz*sizeof(u_short));
  239.             gpp=rgboverflowrow;
  240.         } else
  241.             gpp=rgb[currow];
  242.         return xsz-1;
  243.     }
  244. }
  245.  
  246.  
  247. #ifdef __STDC__
  248. PRIVATE decompress(void)
  249. #else
  250. PRIVATE decompress()
  251. #endif
  252. {
  253.     u_short *cp; /* code pointer, into codes */
  254.     u_char *sp;  /* stack pointer, into stack */
  255.     u_short *pp; /* pixel pointer, into rgb */
  256.     u_short lastnormal;
  257.     short ncodes;
  258.     short curfree;
  259.     u_char finchar;
  260.     u_short oldcode, curcode, incode;
  261.     short npix;
  262.  
  263.     init_counter(0, (int)ysz, 10, NULL);
  264.     npix=0;
  265.     lastnormal=(1<<bitsperpixel)-1;
  266.     ncodes=nextcodes();
  267.     if (!ncodes)
  268.         ncodes=nextcodes();
  269.     while (ncodes>0) {
  270.         curfree=(1<<codesize)+2;
  271.         cp=codes;
  272.         sp=stack;
  273.         finchar=oldcode= *cp++;
  274.         if (--npix<0) {
  275.             npix=nextrow(0);
  276.             pp=gpp;
  277.         }
  278.         *pp++ =cm[finchar];
  279.         ncodes-=2;
  280.         do {
  281.             incode= *cp++;
  282.             if (incode>=curfree) {
  283.                 curcode=oldcode;
  284.                 *sp++ =finchar;
  285.             } else
  286.                 curcode=incode;
  287.             while (curcode>lastnormal) {
  288.                 *sp++ =suffix[curcode];
  289.                 curcode=prefix[curcode];
  290.             }
  291.             finchar=curcode;
  292.             if (--npix<0) {
  293.                 npix=nextrow(0);
  294.                 pp=gpp;
  295.             }
  296.             *pp++ =cm[finchar];
  297.             while (sp!=stack) {
  298.                 if (--npix<0) {
  299.                     npix=nextrow(0);
  300.                     pp=gpp;
  301.                 }
  302.                 *pp++ =cm[*--sp];
  303.             }
  304.             prefix[curfree]=oldcode;
  305.             suffix[curfree]=finchar;
  306.             oldcode=incode;
  307.             ++curfree;
  308.         } while (--ncodes>=0);
  309.         ncodes=nextcodes();
  310.     }
  311.     gpp=pp;
  312.     (void)nextrow(1);
  313. }
  314.  
  315.  
  316. #ifdef __STDC__
  317. PRIVATE short fill_masks(short startbit, short nbits)
  318. #else
  319. PRIVATE short fill_masks(startbit, nbits)
  320. short startbit;
  321. short nbits;
  322. #endif
  323. {
  324.     u_short *m, *m2;
  325.     short start, length, n, loopc;
  326.     u_long mask;
  327.  
  328.     m=masks;
  329.     start=startbit;
  330.     length=nbits;
  331.     n=0;
  332.     do {
  333.         if (start+length>16) { /* in two parts */
  334.             mask=1<<(15-start);
  335.             loopc=14-start;
  336.             if (loopc>=0) {
  337.                 do {
  338.                     mask|=mask>>1;
  339.                 } while (--loopc>=0);
  340.             }
  341.             *m++ = -start;
  342.             *m++ =mask;
  343.             mask=1<<15;
  344.             loopc=length+start-18;
  345.             if (loopc>=0) {
  346.                 do {
  347.                     mask|=mask>>1;
  348.                 } while (--loopc>=0);
  349.             }
  350.             *m++ =16-start;
  351.             *m++ =mask;
  352.             n+=2;
  353.         } else {               /* in one part */
  354.             mask=1<<(15-start);
  355.             loopc=length-2;
  356.             if (loopc>=0) {
  357.                 do {
  358.                     mask|=mask>>1;
  359.                 } while (--loopc>=0);
  360.             }
  361.             *m++ = -start;
  362.             *m++ =mask;
  363.             ++n;
  364.         }
  365.         start=(start+length)&15;
  366.     } while (start!=startbit);
  367.     for (start=NMASKS/2/n-2; start>=0; --start) {
  368.         m2=masks;
  369.         loopc=n-1;
  370.         do {
  371.             *m++ = *m2++;
  372.             *m++ = *m2++;
  373.         } while (--loopc>=0);
  374.     }
  375.     n=NMASKS/2/n*n;
  376.     return n;
  377. }
  378.  
  379.  
  380. #ifdef __STDC__
  381. PRIVATE short nextcodes(void)
  382. #else
  383. PRIVATE short nextcodes()
  384. #endif
  385. {
  386. #define NC_EC_INIT  0
  387. #define NC_EC_CLEAR 1
  388. #define NC_EC_EOF   2
  389.     static int endcode=NC_EC_INIT;
  390.     u_short *ip; static u_short *sip;
  391.     short nushorts; static short snushorts=0;
  392.     static short bitpos=0, csz;
  393.     short tonextcsz;
  394.     static int ok=1;
  395.     short nmasks, inmasks; u_short *m;
  396.     u_short eofcode, clearcode;
  397.     short ncodes; u_short *cp;
  398.     u_short input, output; static u_short sinput;
  399.     short shift;
  400.     u_char *tc;
  401.  
  402.     assert(ok);
  403.     if (endcode==NC_EC_EOF) {
  404.         ok=0;
  405.         return 0;
  406.     }
  407.     ip=sip;
  408.     nushorts=snushorts;
  409.     input=sinput;
  410.     csz=codesize+1;
  411.     clearcode=1<<codesize;
  412.     eofcode=clearcode+1;
  413.     tonextcsz=(1<<csz)-eofcode-1;
  414.     ncodes=NCODES;
  415.     cp=codes;
  416.     tc=transchars;
  417.     inmasks=fill_masks(bitpos, csz);
  418.     do {
  419. nc_restart:
  420.         m=masks;
  421.         nmasks=inmasks-2;
  422.         shift= *m++;
  423.         if (shift>=0) {
  424.             if (--nushorts<0) {
  425.                 nushorts=nextubytes();
  426.                 if (nushorts==0) {
  427.                     ok=0;
  428.                     return 0;
  429.                 }
  430.                 ip=(u_short *)ubytes;
  431.                 nushorts=(nushorts+1)/2-1;
  432.             }
  433.             input= *ip++;
  434.             output=(u_long)(input & *m++)>>(u_short)shift;
  435.         } else
  436.             output=(u_long)(input & *m++)<<(u_short)(-shift);
  437.         do {
  438.             shift= *m++;
  439.             if (shift<=0) {
  440.                 /* put output into the output stream, this code is repeated below */
  441.                 output=(tc[output&0xff]<<8)|tc[((u_long)output>>8)&0xff];
  442.                 if (output==eofcode) {
  443.                     endcode=NC_EC_EOF;
  444.                     bitpos= -shift;
  445.                     goto nc_end;
  446.                 } 
  447.                 if (output==clearcode) {
  448.                     endcode=NC_EC_CLEAR;
  449.                     bitpos= -shift;
  450.                     goto nc_end;
  451.                 } 
  452.                 if (--tonextcsz<0) {
  453.                     if (csz<12)
  454.                         ++csz;
  455.                     tonextcsz= (1<<(csz-1))-1;
  456.                     if (ncodes<tonextcsz)
  457.                         error0(E0_WARNING, E1_GIF, E2_FORMAT, E3_POT_CODE_OVERFLOW);
  458.                     bitpos= -shift;
  459.                     inmasks=fill_masks(bitpos, csz);
  460.                     *cp++ =output;
  461.                     --ncodes;
  462.                     goto nc_restart;
  463.                 }
  464.                 *cp++ =output;
  465.                 --ncodes;
  466.                 /* end of output code */
  467.             } 
  468.             if (shift>=0) {
  469.                 if (--nushorts<0) {
  470.                     nushorts=nextubytes();
  471.                     if (nushorts==0) {
  472.                         ok=0;
  473.                         return 0;
  474.                     }
  475.                     ip=(u_short *)ubytes;
  476.                     nushorts=(nushorts+1)/2-1;
  477.                 }
  478.                 input= *ip++;
  479.             }
  480.             if (shift<=0)
  481.                 output=(u_long)(input & *m++)<<(u_short)(-shift);
  482.             else
  483.                 output|=(u_long)(input & *m++)>>(u_short)shift;
  484.         } while (--nmasks>=0);
  485.         /* put output into the output stream, this code is repeated above */
  486.         output=(tc[output&0xff]<<8)|tc[((u_long)output>>8)&0xff];
  487.         if (output==eofcode) {
  488.             endcode=NC_EC_EOF;
  489.             goto nc_end;
  490.         } 
  491.         if (output==clearcode) {
  492.             endcode=NC_EC_CLEAR;
  493.             goto nc_end;
  494.         } 
  495.         if (--tonextcsz<0) {
  496.             if (csz<12)
  497.                 ++csz;
  498.             tonextcsz= (1<<(csz-1))-1;
  499.             if (ncodes<tonextcsz)
  500.                 error0(E0_WARNING, E1_GIF, E2_FORMAT, E3_POT_CODE_OVERFLOW);
  501.             inmasks=fill_masks(bitpos, csz);
  502.         }
  503.         *cp++ =output;
  504.         --ncodes;
  505.         /* end of output code */
  506.     } while (1);
  507. nc_end:
  508.     sip=ip;
  509.     snushorts=nushorts;
  510.     sinput=input;
  511.     return NCODES-ncodes;
  512. }
  513.  
  514.  
  515. #ifdef __STDC__
  516. PRIVATE short nextubytes(void)
  517. #else
  518. PRIVATE short nextubytes()
  519. #endif
  520. {
  521.     static int ok=1;
  522.     short dec;
  523.     u_char *bp; static u_char *sbp=NULL;
  524.     u_char *up, *tc;
  525.     short inbuf; static short sinbuf;
  526.     short inblock; static short sinblock;
  527.     short inubytes;
  528.  
  529.     assert(ok);
  530.     bp=sbp;
  531.     up=(u_char *)ubytes;
  532.     tc=transchars;
  533.     inbuf=sinbuf;
  534.     inblock=sinblock;
  535.     inubytes=NUBYTES;
  536.     if (!sbp) {
  537.         dec=0;
  538.         inblock=0;
  539.         inbuf=0;
  540.     } else {
  541.         if (inblock<inbuf)
  542.             dec=inblock;
  543.         else
  544.             dec=inbuf;
  545.         if (inubytes<dec)
  546.             dec=inubytes;
  547.         inblock-=dec;
  548.         inbuf-=dec;
  549.         inubytes-=dec;
  550.     }
  551.     do {
  552.         if (--dec>=0) {
  553.             do {
  554.                 *up++ = tc[*bp++];
  555.             } while (--dec>=0);
  556.         }
  557.         if (inblock==0 && inbuf>0) {
  558.             inblock= *bp++;
  559.             --inbuf;
  560.             if (!inblock) { /* zero bytecount encountered, repeated below */
  561.                 ok=0;
  562.                 lseek(infd, (long)-inbuf, 1);
  563.                 break;
  564.             }
  565.         }
  566.         if (inbuf==0) {
  567.             inbuf=read(infd, buf, NBUF);
  568.             if (inbuf<0)
  569.         error1(E0_FATAL, E1_IO, E2_READ, E3_ERRNO, infilename);
  570.             else if (inbuf==0) {
  571.         error1(E0_ERROR, E1_IO, E2_READ, E3_UNEXPEOF_GIF, infilename);
  572.                 ok=0;
  573.                 return 0;
  574.             }
  575.             bp=buf;
  576.         }
  577.         if (inblock==0) {
  578.             inblock= *bp++;
  579.             --inbuf;
  580.         assert(inbuf>0);
  581.             if (!inblock) { /* zero bytecount encountered, repeated above */
  582.                 ok=0;
  583.                 lseek(infd, (long)-inbuf, 1);
  584.                 break;
  585.             }
  586.         }
  587.         if (inubytes==0) {
  588.             break;
  589.         }
  590.         if (inblock<inbuf)
  591.             dec=inblock;
  592.         else
  593.             dec=inbuf;
  594.         if (inubytes<dec)
  595.             dec=inubytes;
  596.         inblock-=dec;
  597.         inbuf-=dec;
  598.         inubytes-=dec;
  599.     } while (1);
  600.     sbp=bp;
  601.     sinbuf=inbuf;
  602.     sinblock=inblock;
  603.     return NUBYTES-inubytes;
  604. }
  605.  
  606.  
  607. #ifdef __STDC__
  608. PRIVATE fill_transchars(void)
  609. #else
  610. PRIVATE fill_transchars()
  611. #endif
  612. {
  613.     u_char *tc;
  614.     u_char c, maskout;
  615.     short i, maskin;
  616.  
  617.     tc=transchars;
  618.     for (i=0; i<NTRANSCHARS; ++i) {
  619.         c=0;
  620.         for (maskout=0x80, maskin=1; maskout; maskin<<=1, maskout=(u_long)maskout>>1) {
  621.             if (i&maskin)
  622.                 c|=maskout;
  623.         }
  624.         *tc++ =c;
  625.     }
  626. }
  627.