home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / graphics / gifbla20.zip / SOURCE / GIFCODE.C < prev    next >
C/C++ Source or Header  |  1992-12-15  |  5KB  |  285 lines

  1.  
  2. /* gifcode.c - GIF encoder/decoder routines. */
  3.  
  4. #include <stdio.h>
  5. #include <string.h>
  6.  
  7. #include "uffile.h"
  8. #include "gifcode.h"
  9.  
  10. static void
  11. init_coder(gc,ff,datasize)
  12. GIF_CODER *gc; FFILE *ff; int datasize;
  13. {
  14.     int c;
  15.  
  16.     gc->ff = ff;
  17.     gc->curblocksize = gc->curblockpos = 0;
  18.     gc->nbits = 0;
  19.     gc->bits = 0L;
  20.     gc->datasize = datasize;
  21.     gc->clear = (1<<datasize);
  22.     gc->eoi = gc->clear+1;
  23.     for (c=0; c<gc->clear; c++) {
  24.         gc->prefix[c] = -1;
  25.         gc->suffix[c] = c;
  26.     }
  27. }
  28.  
  29. static void
  30. reset_codesize(gc)
  31. GIF_CODER *gc;
  32. {
  33.     gc->codesize = gc->datasize+1;
  34.     gc->codemask = (1<<gc->codesize)-1;
  35.     gc->avail = gc->eoi+1;
  36. }
  37.  
  38. static void
  39. inc_codesize(gc)
  40. GIF_CODER *gc;
  41. {
  42.     gc->codesize++;
  43.     gc->codemask = (1<<gc->codesize)-1;
  44. }
  45.  
  46. static void
  47. clear_encoder(gc)
  48. GIF_CODER *gc;
  49. {
  50.     reset_codesize(gc);
  51.     memset(gc->u.e.sl_ptr,0,GIF_MAXCODES*sizeof(int));
  52.     gc->u.e.sl_index = 1;
  53. }
  54.  
  55. static void
  56. clear_decoder(gc)
  57. GIF_CODER *gc;
  58. {
  59.     reset_codesize(gc);
  60.     gc->u.d.prevc = -1;
  61. }
  62.  
  63. void
  64. gif_start_encoding(gc,ff,datasize)
  65. GIF_CODER *gc; FFILE *ff; int datasize;
  66. {
  67.     init_coder(gc,ff,datasize);
  68.     clear_encoder(gc);
  69.     gc->u.e.curprefix = -1;
  70. }
  71.  
  72. static int
  73. putcurblock(gc)
  74. GIF_CODER *gc;
  75. {
  76.     if (ff_putc(gc->curblocksize,gc->ff)==EOF
  77.         || ff_write(gc->curblock,gc->curblocksize,gc->ff)!=gc->curblocksize)
  78.         return -1;
  79.     gc->curblocksize = 0;
  80.     return 0;
  81. }
  82.  
  83. static int
  84. putcode(c,gc)
  85. int c; GIF_CODER *gc;
  86. {
  87.     gc->bits |= (((long)(c&gc->codemask))<<gc->nbits);
  88.     gc->nbits += gc->codesize;
  89.     while (gc->nbits >= 8) {
  90.         gc->curblock[gc->curblocksize++] = (gc->bits&0xFF);
  91.         gc->bits >>= 8;
  92.         gc->nbits -= 8;
  93.         if (gc->curblocksize==254 && putcurblock(gc)<0)
  94.             return -1;
  95.     }
  96.     return 0;
  97. }
  98.  
  99. static int
  100. end_putcode(gc)
  101. GIF_CODER *gc;
  102. {
  103.     if (putcode(gc->eoi,gc) < 0)
  104.         return -1;
  105.     if (gc->nbits > 0)
  106.         gc->curblock[gc->curblocksize++] = (gc->bits&0xFF);
  107.     if (gc->curblocksize>0 && putcurblock(gc)<0)
  108.         return -1;
  109.     if (ff_putc(0,gc->ff) == EOF)
  110.         return -1;
  111.     return 0;
  112. }
  113.  
  114. static int
  115. getcode(gc)
  116. GIF_CODER *gc;
  117. {
  118.     int size,c;
  119.  
  120.     while (gc->nbits < gc->codesize) {
  121.         if (gc->curblockpos < gc->curblocksize) {
  122.             gc->bits |= (((long)gc->curblock[gc->curblockpos++])<<gc->nbits);
  123.             gc->nbits += 8;
  124.         } else if ((size=ff_getc(gc->ff))==EOF || size==0
  125.             || ff_read(gc->curblock,size,gc->ff)!=size)
  126.             return -1;
  127.         else {
  128.             gc->curblocksize = size;
  129.             gc->curblockpos = 0;
  130.         }
  131.     }
  132.     c = (int)(gc->bits&gc->codemask);
  133.     gc->bits >>= gc->codesize;
  134.     gc->nbits -= gc->codesize;
  135.     return c;
  136. }
  137.  
  138. static int
  139. end_getcode(gc)
  140. GIF_CODER *gc;
  141. {
  142.     int size;
  143.  
  144.     if (gc->curblockpos == gc->curblocksize) {
  145.         if ((size=ff_getc(gc->ff)) == 0)
  146.             return 0;
  147.         else if (size==EOF || ff_read(gc->curblock,size,gc->ff)!=size)
  148.             return -1;
  149.         else {
  150.             gc->curblocksize = size;
  151.             gc->curblockpos = 0;
  152.         }
  153.     }
  154.     if (getcode(gc) != gc->eoi)
  155.         return -1;
  156.     if (ff_getc(gc->ff) == 0)
  157.         return 0;
  158.     else
  159.         return -1;
  160. }
  161.  
  162. static int
  163. check_codetable(gc,c)
  164. GIF_CODER *gc; int c;
  165. {
  166.     int ind;
  167.  
  168.     ind = gc->u.e.sl_ptr[gc->u.e.curprefix];
  169.     while (ind != 0)
  170.         if (c == gc->u.e.sl_suffix[ind])
  171.             return gc->u.e.sl_newprefix[ind];
  172.         else
  173.             ind = gc->u.e.sl_next[ind];
  174.     return -1;
  175. }
  176.  
  177. static void
  178. add_to_codetable(gc,newc)
  179. GIF_CODER *gc; int newc;
  180. {
  181.     int ind;
  182.  
  183.     ind = gc->u.e.sl_index++;
  184.     gc->u.e.sl_next[ind] = gc->u.e.sl_ptr[gc->prefix[newc]];
  185.     gc->u.e.sl_ptr[gc->prefix[newc]] = ind;
  186.     gc->u.e.sl_suffix[ind] = gc->suffix[newc];
  187.     gc->u.e.sl_newprefix[ind] = newc;
  188. }
  189.  
  190. int
  191. gif_encode_c(c,gc)
  192. int c; GIF_CODER *gc;
  193. {
  194.      int newpref,newc;
  195.  
  196.     if (gc->u.e.curprefix < 0) {
  197.         gc->u.e.curprefix = c;
  198.         return putcode(gc->clear,gc);
  199.     } else if ((newpref=check_codetable(gc,c)) >= 0) {
  200.         gc->u.e.curprefix = newpref;
  201.         return 0;
  202.     }
  203.     newc = gc->avail++;
  204.     gc->prefix[newc] = gc->u.e.curprefix;
  205.     gc->suffix[newc] = c;
  206.     add_to_codetable(gc,newc);
  207.     if (putcode(gc->u.e.curprefix,gc) < 0)
  208.         return -1;
  209.     gc->u.e.curprefix = c;
  210.     if (gc->avail == GIF_MAXCODES) {
  211.         if (putcode(gc->clear,gc) < 0)
  212.             return -1;
  213.         clear_encoder(gc);
  214.     } else if (gc->codemask < newc)
  215.         inc_codesize(gc);
  216.     return 0;
  217. }
  218.  
  219. int
  220. gif_end_encoding(gc)
  221. GIF_CODER *gc;
  222. {
  223.     if ((gc->u.e.curprefix>=0 && putcode(gc->u.e.curprefix,gc)<0)
  224.         || end_putcode(gc)<0)
  225.         return -1;
  226.     else
  227.         return 0;
  228. }
  229.  
  230. void
  231. gif_start_decoding(gc,ff,datasize)
  232. GIF_CODER *gc; FFILE *ff; int datasize;
  233. {
  234.     int c;
  235.  
  236.     init_coder(gc,ff,datasize);
  237.     clear_decoder(gc);
  238.     for (c=0; c<gc->clear; c++)
  239.         gc->u.d.first[c] = c;
  240.     gc->u.d.csttop = 0;
  241. }
  242.  
  243. int
  244. gif___f_decode_c(gc)
  245. GIF_CODER *gc;
  246. {
  247.     int c,newc;
  248.  
  249.     for (;;) {
  250.         if (gc->u.d.csttop > 0)
  251.             return gc->u.d.cstack[--gc->u.d.csttop];
  252.         else if ((c=getcode(gc))<0 || c==gc->eoi || gc->avail<c)
  253.             return -1;
  254.         else if (c == gc->clear)
  255.             clear_decoder(gc);
  256.         else {
  257.             if (gc->u.d.prevc>=0 && gc->avail<GIF_MAXCODES) {
  258.                 newc = gc->avail++;
  259.                 gc->prefix[newc] = gc->u.d.prevc;
  260.                 gc->u.d.first[newc] = gc->u.d.first[gc->u.d.prevc];
  261.                 gc->suffix[newc] = gc->u.d.first[c];
  262.                 if (gc->codemask<gc->avail && gc->avail<GIF_MAXCODES)
  263.                     inc_codesize(gc);
  264.             }
  265.             if (c == gc->avail)
  266.                 return -1;
  267.             gc->u.d.prevc = c;
  268.             do {
  269.                 gc->u.d.cstack[gc->u.d.csttop++] = gc->suffix[c];
  270.                 c = gc->prefix[c];
  271.             } while (c >= 0);
  272.         }
  273.     }
  274. }
  275.  
  276. int
  277. gif_end_decoding(gc)
  278. GIF_CODER *gc;
  279. {
  280.     if (end_getcode(gc) < 0)
  281.         return -1;
  282.     else
  283.         return 0;
  284. }
  285.