home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga Shareware Floppies / ma01.dms / ma01.adf / wasp / src / readgif.c < prev    next >
C/C++ Source or Header  |  1991-12-28  |  14KB  |  589 lines

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