home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Graphics / ToyViewer-2.6a / src / gifbmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-11  |  4.7 KB  |  185 lines

  1. /*
  2.     gifbmap.h
  3.  
  4.     gifheader.c, gifbmap.c, and gif.h are based on "giftoppm"
  5.     of David Koblas.
  6.     They are modified by T. Ogihara. (1995)
  7. */
  8.  
  9. /* +-------------------------------------------------------------------+ */
  10. /* | Copyright 1990, David Koblas.                                     | */
  11. /* |   Permission to use, copy, modify, and distribute this software   | */
  12. /* |   and its documentation for any purpose and without fee is hereby | */
  13. /* |   granted, provided that the above copyright notice appear in all | */
  14. /* |   copies and that both that copyright notice and this permission  | */
  15. /* |   notice appear in supporting documentation.  This software is    | */
  16. /* |   provided "as is" without express or implied warranty.           | */
  17. /* +-------------------------------------------------------------------+ */
  18.  
  19. #include  <signal.h>
  20. #include  <setjmp.h>
  21. #include  "gif.h"
  22. #include  "strfunc.h"
  23.  
  24. static int ReadColorMap(FILE *, gifHeader *);
  25. static int DoExtension(FILE *, gifHeader *);
  26. static int ReadImage(FILE *, const gifHeader *, unsigned char **);
  27.  
  28. static void (*sav_violation)() = NULL;
  29. static void (*sav_buserror)() = NULL;
  30. static jmp_buf sav_env;
  31.  
  32. static void
  33. catch_violation(int sig)
  34. {
  35.     longjmp(sav_env, sig);
  36. }
  37.  
  38. int gifGetImage(FILE *fp, gifHeader *gh, unsigned char **planes)
  39. {
  40.     int    c, rtn = 0;
  41.  
  42.     if (gh->colormap) {    /* Global Colormap */
  43.         if (ReadColorMap(fp, gh) == 0)
  44.             return Err_FORMAT;
  45.     }
  46.  
  47.     while ((c = getc(fp)) != ',' ) {    /* start character */
  48.         if (c == EOF || c == ';')    /* GIF terminator */
  49.             return Err_SHORT;
  50.         if (c == '!') {     /* Extension */
  51.             if (DoExtension(fp, gh) < 0)
  52.                 return Err_ILLG;
  53.         }
  54.         /* other chars are illegal... ignore */
  55.     }
  56.  
  57.     (void)get_long(fp); /* skip 4 bytes */
  58.     gh->width = get_short(fp);
  59.     gh->height = get_short(fp);
  60.     c = getc(fp);
  61.     gh->interlace = BitSet(c, INTERLACE);
  62.     if (BitSet(c, LOCALCOLORMAP)) { /* Use Local Color Map */
  63.         gh->colors = 2 << (c & 0x07);
  64.         if (ReadColorMap(fp, gh) == 0)
  65.             return Err_FORMAT;
  66.     }
  67.     if (gh->transp >= 0) {
  68.         unsigned char *p = (unsigned char *)gh->palette[gh->transp];
  69.         p[RED] = p[GREEN] = p[BLUE] = 255;
  70.         if (gh->colors - 1 == gh->transp)
  71.             --gh->colors;    /* if last of palette is transp. */
  72.     }
  73.     gh->bits = howManyBits(gh->palette, gh->colors);
  74.     gh->isgray = isGray(gh->palette, gh->colors);
  75.     /* Initialize the Compression routines */
  76.     if (initGifLZW(fp) == EOF)
  77.         return Err_SHORT;
  78.  
  79.     sav_violation = signal(SIGSEGV, catch_violation);
  80.     sav_buserror = signal(SIGBUS, catch_violation);
  81.     if (setjmp(sav_env) == 0)
  82.         rtn = ReadImage(fp, gh, planes);
  83.     else /* return from Segmentation Error */
  84.         rtn = Err_FORMAT;
  85.     (void) signal(SIGSEGV, sav_violation);
  86.     (void) signal(SIGBUS, sav_buserror);
  87.     return rtn;
  88. }
  89.  
  90. static int
  91. ReadColorMap(FILE *fd, gifHeader *gh)
  92. {
  93.     int i, j, number;
  94.     unsigned char    *p, *q;
  95.  
  96.     number = gh->colors;
  97.     for (i = 0; i < number; ++i) {
  98.         p = (unsigned char *)gh->palette[i];
  99.         p[RED] = getc(fd);
  100.         p[GREEN] = getc(fd);
  101.         p[BLUE] = getc(fd);
  102.         if (feof(fd))
  103.             return 0;
  104.     }
  105.     for (i = number - 1; i > 0; --i) {    /* skip stab */
  106.         p = (unsigned char *)gh->palette[i];
  107.         q = (unsigned char *)gh->palette[i - 1];
  108.         for (j = 0; j < 3; j++)
  109.             if (p[j] != q[j]) goto EXIT;
  110.     }
  111. EXIT:
  112.     gh->colors = i + 1;
  113.     return 1;
  114. }
  115.  
  116. static int
  117. DoExtension(FILE *fd, gifHeader *gh)
  118. {
  119.     int cc;
  120.     unsigned char    buf[256];
  121.  
  122.     switch (cc = getc(fd)) {
  123.     case 0x01:        /* Plain Text Extension */
  124.     case 0x2c:        /* Image Descriptor */
  125.     case 0x3b:        /* Trailer */
  126.     case 0xff:        /* Application Extension */
  127.         break;
  128.     case 0xf9:        /* Graphic Control Extension */
  129.         while (GetDataBlock(fd, buf) != 0) {
  130.             if (BitSet(buf[0], TRANSPARENCY))
  131.             gh->transp = buf[3];    /* Transparent Index */
  132.         }
  133.         return cc;
  134.     case 0xfe:        /* Comment Extension */
  135.         while (GetDataBlock(fd, buf) != 0) {
  136.             if (gh->memo == NULL)
  137.             gh->memo = (unsigned char *)str_dup(buf);
  138.         }
  139.         return cc;
  140.     default:
  141.         return -1;    /* ERROR */
  142.     }
  143.     while (GetDataBlock(fd, buf) != 0)
  144.         ;
  145.     return cc;
  146. }
  147.  
  148. static int
  149. ReadImage(FILE *fd, const gifHeader *gh, unsigned char **planes)
  150. {
  151.     int    i, xpos, ypos, xbyte, pass, pn, err;
  152.     long    wd;
  153.     unsigned char    *map[MAXPLANE];
  154.     unsigned char    buffer[MAXWidth];
  155.  
  156.     pn = (gh->isgray ? 1:3) + ((gh->transp >= 0) ? 1 : 0);
  157.     err = allocImage(planes, gh->width, gh->height, gh->bits, pn);
  158.     if (err)
  159.         return err;
  160.     pass = 0;
  161.     xbyte = byte_length(gh->bits, gh->width);
  162.  
  163.     for (ypos = 0; ; ) {
  164.         for (xpos = 0; xpos < gh->width; xpos++)
  165.             buffer[xpos] = LWZReadByte(fd);
  166.         map[0] = planes[0] + (wd = xbyte * ypos);
  167.         for (i = 1; i < pn; i++)
  168.             map[i] = planes[i] + wd;
  169.         expandImage(map, buffer, (const paltype *)gh->palette,
  170.             gh->bits, gh->width, gh->isgray, gh->transp);
  171.         if (gh->interlace) {
  172.             ypos += pass ? (0x10 >> pass) : 0x08;
  173.             if (ypos >= gh->height) {
  174.                 if (++pass > 3)
  175.                     break;
  176.                 ypos = 8 >> pass;
  177.             }
  178.         }else {
  179.             if (++ypos >= gh->height)
  180.                 break;
  181.         }
  182.     }
  183.     return 0;
  184. }
  185.