home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / gif.c < prev    next >
C/C++ Source or Header  |  1993-10-21  |  15KB  |  626 lines

  1. /* gif.c:
  2.  *
  3.  * adapted from code by kirk johnson (tuna@athena.mit.edu).  most of this
  4.  * code is unchanged. -- jim frost 12.31.89
  5.  *
  6.  * gifin.c
  7.  * kirk johnson
  8.  * november 1989
  9.  *
  10.  * routines for reading GIF files
  11.  *
  12.  * Copyright 1989 Kirk L. Johnson (see the included file
  13.  * "kljcpyrght.h" for complete copyright information)
  14.  */
  15.  
  16. #include "image.h"
  17. #include "gif.h"
  18. #include "kljcpyrght.h"
  19.  
  20. /****
  21.  **
  22.  ** local #defines
  23.  **
  24.  ****/
  25.  
  26. #define PUSH_PIXEL(p)                                       \
  27. {                                                           \
  28.   if (pstk_idx == PSTK_SIZE)                                \
  29.     gifin_fatal("pixel stack overflow in PUSH_PIXEL()");    \
  30.   else                                                      \
  31.     pstk[pstk_idx++] = (p);                                 \
  32. }
  33.  
  34.  
  35. /****
  36.  **
  37.  ** local variables
  38.  **
  39.  ****/
  40.  
  41. static int interlace_start[4]= { /* start line for interlacing */
  42.   0, 4, 2, 1
  43. };
  44.  
  45. static int interlace_rate[4]= { /* rate at which we accelerate vertically */
  46.   8, 8, 4, 2
  47. };
  48.  
  49. static BYTE file_open  = 0;     /* status flags */
  50. static BYTE image_open = 0;
  51.  
  52. static ZFILE *ins;              /* input stream */
  53.  
  54. static int  root_size;          /* root code size */
  55. static int  clr_code;           /* clear code */
  56. static int  eoi_code;           /* end of information code */
  57. static int  code_size;          /* current code size */
  58. static int  code_mask;          /* current code mask */
  59. static int  prev_code;          /* previous code */
  60.  
  61. /*
  62.  * NOTE: a long is assumed to be at least 32 bits wide
  63.  */
  64. static long work_data;          /* working bit buffer */
  65. static int  work_bits;          /* working bit count */
  66.  
  67. static BYTE buf[256];           /* byte buffer */
  68. static int  buf_cnt;            /* byte count */
  69. static int  buf_idx;            /* buffer index */
  70.  
  71. static int table_size;          /* string table size */
  72. static int prefix[STAB_SIZE];   /* string table : prefixes */
  73. static int extnsn[STAB_SIZE];   /* string table : extensions */
  74.  
  75. static BYTE pstk[PSTK_SIZE];    /* pixel stack */
  76. static int  pstk_idx;           /* pixel stack pointer */
  77.  
  78.  
  79. /****
  80.  **
  81.  ** global variables
  82.  **
  83.  ****/
  84.  
  85. static int  gifin_rast_width;          /* raster width */
  86. static int  gifin_rast_height;         /* raster height */
  87. static BYTE gifin_g_cmap_flag;         /* global colormap flag */
  88. static int  gifin_g_pixel_bits;        /* bits per pixel, global colormap */
  89. static int  gifin_g_ncolors;           /* number of colors, global colormap */
  90. static BYTE gifin_g_cmap[3][256];      /* global colormap */
  91. static int  gifin_bg_color;            /* background color index */
  92. static int  gifin_color_bits;          /* bits of color resolution */
  93.  
  94. static int  gifin_img_left;            /* image position on raster */
  95. static int  gifin_img_top;             /* image position on raster */
  96. static int  gifin_img_width;           /* image width */
  97. static int  gifin_img_height;          /* image height */
  98. static BYTE gifin_l_cmap_flag;         /* local colormap flag */
  99. static int  gifin_l_pixel_bits;        /* bits per pixel, local colormap */
  100. static int  gifin_l_ncolors;           /* number of colors, local colormap */
  101. static BYTE gifin_l_cmap[3][256];      /* local colormap */
  102. static BYTE gifin_interlace_flag;      /* interlace image format flag */
  103.  
  104. /*
  105.  * open a GIF file, using s as the input stream
  106.  */
  107.  
  108. static int gifin_open_file(s)
  109.      ZFILE *s;
  110. {
  111.   /* make sure there isn't already a file open */
  112.   if (file_open)
  113.     return GIFIN_ERR_FAO;
  114.  
  115.   /* remember that we've got this file open */
  116.   file_open = 1;
  117.   ins       = s;
  118.  
  119.   /* check GIF signature */
  120.   if (zread(ins, buf, GIF_SIG_LEN) != GIF_SIG_LEN)
  121.     return GIFIN_ERR_EOF;
  122.  
  123.   buf[GIF_SIG_LEN] = '\0';
  124.   if ((strcmp((char *) buf, GIF_SIG) != 0) &&
  125.       (strcmp((char *) buf, GIF_SIG_89) != 0))
  126.     return GIFIN_ERR_BAD_SIG;
  127.  
  128.   /* read screen descriptor */
  129.   if (zread(ins, buf, GIF_SD_SIZE) != GIF_SD_SIZE)
  130.     return GIFIN_ERR_EOF;
  131.  
  132.   /* decode screen descriptor */
  133.   gifin_rast_width   = (buf[1] << 8) + buf[0];
  134.   gifin_rast_height  = (buf[3] << 8) + buf[2];
  135.   gifin_g_cmap_flag  = (buf[4] & 0x80) ? 1 : 0;
  136.   gifin_color_bits   = ((buf[4] & 0x70) >> 4) + 1;
  137.   gifin_g_pixel_bits = (buf[4] & 0x07) + 1;
  138.   gifin_bg_color     = buf[5];
  139.  
  140.   if (buf[6] != 0)
  141.     return GIFIN_ERR_BAD_SD;
  142.  
  143.   /* load global colormap */
  144.   if (gifin_g_cmap_flag)
  145.   {
  146.     gifin_g_ncolors = (1 << gifin_g_pixel_bits);
  147.  
  148.     if (gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors) != GIFIN_SUCCESS)
  149.       return GIFIN_ERR_EOF;
  150.   }
  151.   else
  152.   {
  153.     gifin_g_ncolors = 0;
  154.   }
  155.  
  156.   /* done! */
  157.   return GIFIN_SUCCESS;
  158. }
  159.  
  160.  
  161. /*
  162.  * open next GIF image in the input stream; returns GIFIN_SUCCESS if
  163.  * successful. if there are no more images, returns GIFIN_DONE. (might
  164.  * also return various GIFIN_ERR codes.)
  165.  */
  166.  
  167. static int gifin_open_image()
  168. {
  169.   int i;
  170.   int separator;
  171.  
  172.   /* make sure there's a file open */
  173.   if (!file_open)
  174.     return GIFIN_ERR_NFO;
  175.  
  176.   /* make sure there isn't already an image open */
  177.   if (image_open)
  178.     return GIFIN_ERR_IAO;
  179.  
  180.   /* remember that we've got this image open */
  181.   image_open = 1;
  182.  
  183.   /* skip over any extension blocks */
  184.   do
  185.   {
  186.     separator = zgetc(ins);
  187.     if (separator == GIF_EXTENSION)
  188.     {
  189.       if (gifin_skip_extension() != GIFIN_SUCCESS)
  190.         return GIFIN_ERR_EOF;
  191.     }
  192.   }
  193.   while (separator == GIF_EXTENSION);
  194.  
  195.   /* check for end of file marker */
  196.   if (separator == GIF_TERMINATOR)
  197.     return GIFIN_DONE;
  198.  
  199.   /* make sure we've got an image separator */
  200.   if (separator != GIF_SEPARATOR)
  201.     return GIFIN_ERR_BAD_SEP;
  202.  
  203.   /* read image descriptor */
  204.   if (zread(ins, buf, GIF_ID_SIZE) != GIF_ID_SIZE)
  205.     return GIFIN_ERR_EOF;
  206.  
  207.   /* decode image descriptor */
  208.   gifin_img_left       = (buf[1] << 8) + buf[0];
  209.   gifin_img_top        = (buf[3] << 8) + buf[2];
  210.   gifin_img_width      = (buf[5] << 8) + buf[4];
  211.   gifin_img_height     = (buf[7] << 8) + buf[6];
  212.   gifin_l_cmap_flag    = (buf[8] & 0x80) ? 1 : 0;
  213.   gifin_interlace_flag = (buf[8] & 0x40) ? 1 : 0;
  214.   gifin_l_pixel_bits   = (buf[8] & 0x07) + 1;
  215.  
  216.   /* load local colormap */
  217.   if (gifin_l_cmap_flag)
  218.   {
  219.     gifin_l_ncolors = (1 << gifin_l_pixel_bits);
  220.  
  221.     if (gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors) != GIFIN_SUCCESS)
  222.       return GIFIN_ERR_EOF;
  223.   }
  224.   else
  225.   {
  226.     gifin_l_ncolors = 0;
  227.   }
  228.  
  229.   /* initialize raster data stream decoder */
  230.   root_size = zgetc(ins);
  231.   clr_code  = 1 << root_size;
  232.   eoi_code  = clr_code + 1;
  233.   code_size = root_size + 1;
  234.   code_mask = (1 << code_size) - 1;
  235.   work_bits = 0;
  236.   work_data = 0;
  237.   buf_cnt   = 0;
  238.   buf_idx   = 0;
  239.  
  240.   /* initialize string table */
  241.   for (i=0; i<STAB_SIZE; i++)
  242.   {
  243.     prefix[i] = NULL_CODE;
  244.     extnsn[i] = i;
  245.   }
  246.  
  247.   /* initialize pixel stack */
  248.   pstk_idx = 0;
  249.  
  250.   /* done! */
  251.   return GIFIN_SUCCESS;
  252. }
  253.  
  254. /*
  255.  * try to read next pixel from the raster, return result in *pel
  256.  */
  257.  
  258. static int gifin_get_pixel(pel)
  259.      int *pel;
  260. {
  261.   int  code;
  262.   int  first;
  263.   int  place;
  264.  
  265.   /* decode until there are some pixels on the pixel stack */
  266.   while (pstk_idx == 0)
  267.   {
  268.     /* load bytes until we have enough bits for another code */
  269.     while (work_bits < code_size)
  270.     {
  271.       if (buf_idx == buf_cnt)
  272.       {
  273.         /* read a new data block */
  274.         if (gifin_read_data_block() != GIFIN_SUCCESS)
  275.           return GIFIN_ERR_EOF;
  276.  
  277.         if (buf_cnt == 0)
  278.           return GIFIN_ERR_EOD;
  279.       }
  280.  
  281.       work_data |= ((long) buf[buf_idx++]) << work_bits;
  282.       work_bits += 8;
  283.     }
  284.  
  285.     /* get the next code */
  286.     code        = work_data & code_mask;
  287.     work_data >>= code_size;
  288.     work_bits  -= code_size;
  289.  
  290.     /* interpret the code */
  291.     if (code == clr_code)
  292.     {
  293.       /* reset decoder stream */
  294.       code_size  = root_size + 1;
  295.       code_mask  = (1 << code_size) - 1;
  296.       prev_code  = NULL_CODE;
  297.       table_size = eoi_code + 1;
  298.     }
  299.     else if (code == eoi_code)
  300.     {
  301.       /* Ooops! no more pixels */
  302.       return GIFIN_ERR_EOF;
  303.     }
  304.     else if (prev_code == NULL_CODE)
  305.     {
  306.       gifin_push_string(code);
  307.       prev_code = code;
  308.     }
  309.     else
  310.     {
  311.       if (code < table_size)
  312.       {
  313.         first = gifin_push_string(code);
  314.       }
  315.       else
  316.       {
  317.         place = pstk_idx;
  318.         PUSH_PIXEL(NULL_CODE);
  319.         first = gifin_push_string(prev_code);
  320.         pstk[place] = first;
  321.       }
  322.  
  323.       gifin_add_string(prev_code, first);
  324.       prev_code = code;
  325.     }
  326.   }
  327.  
  328.   /* pop a pixel off the pixel stack */
  329.   *pel = (int) pstk[--pstk_idx];
  330.  
  331.   /* done! */
  332.   return GIFIN_SUCCESS;
  333. }
  334.  
  335. #if 0
  336. /*
  337.  * close an open GIF image
  338.  */
  339.  
  340. static int gifin_close_image()
  341. {
  342.   /* make sure there's an image open */
  343.   if (!image_open)
  344.     return GIFIN_ERR_NIO;
  345.  
  346.   /* skip any remaining raster data */
  347.   do
  348.   {
  349.     if (gifin_read_data_block() != GIFIN_SUCCESS)
  350.       return GIFIN_ERR_EOF;
  351.   }
  352.   while (buf_cnt > 0);
  353.  
  354.   /* mark image as closed */
  355.   image_open = 0;
  356.  
  357.   /* done! */
  358.   return GIFIN_SUCCESS;
  359. }
  360. #endif
  361.  
  362. /*
  363.  * close an open GIF file
  364.  */
  365.  
  366. static int gifin_close_file()
  367. {
  368.   /* make sure there's a file open */
  369.   if (!file_open)
  370.     return GIFIN_ERR_NFO;
  371.  
  372.   /* mark file (and image) as closed */
  373.   file_open  = 0;
  374.   image_open = 0;
  375.  
  376.   /* done! */
  377.   return GIFIN_SUCCESS;
  378. }
  379.  
  380. /*
  381.  * load a colormap from the input stream
  382.  */
  383.  
  384. static int gifin_load_cmap(cmap, ncolors)
  385.      BYTE cmap[3][256];
  386.      int  ncolors;
  387. {
  388.   int i;
  389.  
  390.   for (i=0; i<ncolors; i++)
  391.   {
  392.     if (zread(ins, buf, 3) != 3)
  393.       return GIFIN_ERR_EOF;
  394.     
  395.     cmap[GIF_RED][i] = buf[GIF_RED];
  396.     cmap[GIF_GRN][i] = buf[GIF_GRN];
  397.     cmap[GIF_BLU][i] = buf[GIF_BLU];
  398.   }
  399.  
  400.   /* done! */
  401.   return GIFIN_SUCCESS;
  402. }
  403.  
  404. /*
  405.  * skip an extension block in the input stream
  406.  */
  407.  
  408. static int gifin_skip_extension()
  409. {
  410.  
  411.   /* get the extension function byte */
  412.   zgetc(ins);
  413.  
  414.   /* skip any remaining raster data */
  415.   do
  416.   {
  417.     if (gifin_read_data_block() != GIFIN_SUCCESS)
  418.       return GIFIN_ERR_EOF;
  419.   }
  420.   while (buf_cnt > 0);
  421.  
  422.   /* done! */
  423.   return GIFIN_SUCCESS;
  424. }
  425.  
  426. /*
  427.  * read a new data block from the input stream
  428.  */
  429.  
  430. static int gifin_read_data_block()
  431. {
  432.   /* read the data block header */
  433.   buf_cnt = zgetc(ins);
  434.  
  435.   /* read the data block body */
  436.   if (zread(ins, buf, buf_cnt) != buf_cnt)
  437.     return GIFIN_ERR_EOF;
  438.  
  439.   buf_idx = 0;
  440.  
  441.   /* done! */
  442.   return GIFIN_SUCCESS;
  443. }
  444.  
  445. /*
  446.  * push a string (denoted by a code) onto the pixel stack
  447.  * (returns the code of the first pixel in the string)
  448.  */
  449.  
  450. static int gifin_push_string(code)
  451.      int code;
  452. {
  453.   int rslt;
  454.  
  455.   while (prefix[code] != NULL_CODE)
  456.   {
  457.     PUSH_PIXEL(extnsn[code]);
  458.     code = prefix[code];
  459.   }
  460.  
  461.   PUSH_PIXEL(extnsn[code]);
  462.   rslt = extnsn[code];
  463.  
  464.   return rslt;
  465. }
  466.  
  467. /*
  468.  * add a new string to the string table
  469.  */
  470.  
  471. static gifin_add_string(p, e)
  472.      int p;
  473.      int e;
  474. {
  475.   prefix[table_size] = p;
  476.   extnsn[table_size] = e;
  477.  
  478.   if ((table_size == code_mask) && (code_size < 12))
  479.   {
  480.     code_size += 1;
  481.     code_mask  = (1 << code_size) - 1;
  482.   }
  483.  
  484.   table_size += 1;
  485. }
  486.  
  487. /*
  488.  * semi-graceful fatal error mechanism
  489.  */
  490.  
  491. static gifin_fatal(msg)
  492.      char *msg;
  493. {
  494.   printf("Error reading GIF file: %s\n", msg);
  495.   exit(0);
  496. }
  497.  
  498. /* these are the routines added for interfacing to xloadimage
  499.  */
  500.  
  501. /* tell someone what the image we're loading is.  this could be a little more
  502.  * descriptive but I don't care
  503.  */
  504.  
  505. static void tellAboutImage(name)
  506.      char *name;
  507. {
  508.   printf("%s is a %dx%d %sGIF image with %d colors\n", name,
  509.      gifin_img_width, gifin_img_height,
  510.      (gifin_interlace_flag ? "interlaced " : ""),
  511.      (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors));
  512. }
  513.  
  514. Image *gifLoad(fullname, name, verbose)
  515.      char         *fullname, *name;
  516.      unsigned int  verbose;
  517. { ZFILE *zf;
  518.   Image *image;
  519.   int    x, y, pixel, pass, scanlen;
  520.   byte  *pixptr, *pixline;
  521.  
  522.   if (! (zf= zopen(fullname)))
  523.     return(NULL);
  524.   if ((gifin_open_file(zf) != GIFIN_SUCCESS) || /* read GIF header */
  525.       (gifin_open_image() != GIFIN_SUCCESS)) {  /* read image header */
  526.     gifin_close_file();
  527.     zclose(zf);
  528.     return(NULL);
  529.   }
  530.   if (verbose)
  531.     tellAboutImage(name);
  532.   znocache(zf);
  533.   image= newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ?
  534.                              gifin_l_pixel_bits :
  535.                              gifin_g_pixel_bits));
  536.   for (x= 0; x < gifin_g_ncolors; x++) {
  537.     image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8;
  538.     image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8;
  539.     image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8;
  540.   }
  541.   image->rgb.used= gifin_g_ncolors;
  542.  
  543.   /* if image has a local colormap, override global colormap
  544.    */
  545.  
  546.   if (gifin_l_cmap_flag) {
  547.     for (x= 0; x < image->rgb.size; x++) {
  548.       image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8;
  549.       image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8;
  550.       image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8;
  551.     }
  552.     image->rgb.used= gifin_l_ncolors;
  553.   }
  554.  
  555.   /* interlaced image -- futz with the vertical trace.  i wish i knew what
  556.    * kind of drugs the GIF people were on when they decided that they
  557.    * needed to support interlacing.
  558.    */
  559.  
  560.   if (gifin_interlace_flag) {
  561.     scanlen= image->height * image->pixlen;
  562.  
  563.     /* interlacing takes four passes to read, each starting at a different
  564.      * vertical point.
  565.      */
  566.  
  567.     for (pass= 0; pass < 4; pass++) {
  568.       y= interlace_start[pass];
  569.       scanlen= image->width * image->pixlen * interlace_rate[pass];
  570.       pixline= image->data + (y * image->width * image->pixlen);
  571.       while (y < gifin_img_height) {
  572.     pixptr= pixline;
  573.     for (x= 0; x < gifin_img_width; x++) {
  574.       if (gifin_get_pixel(&pixel) != GIFIN_SUCCESS) {
  575.         printf("%s: Short read within image data\n", fullname);
  576.         y = gifin_img_height; x = gifin_img_width;
  577.       }
  578.       valToMem(pixel, pixptr, image->pixlen);
  579.       pixptr += image->pixlen;
  580.     }
  581.     y += interlace_rate[pass];
  582.     pixline += scanlen;
  583.       }
  584.     }
  585.   }
  586.  
  587.   /* not an interlaced image, just read in sequentially
  588.    */
  589.  
  590.   else {
  591.     pixptr= image->data;
  592.     for (y= 0; y < gifin_img_height; y++)
  593.       for (x= 0; x < gifin_img_width; x++) {
  594.     if (gifin_get_pixel(&pixel) != GIFIN_SUCCESS) {
  595.       printf("%s: Short read within image data\n", fullname);
  596.       y = gifin_img_height; x = gifin_img_width;
  597.     }
  598.     valToMem(pixel, pixptr, image->pixlen);
  599.     pixptr += image->pixlen;
  600.       }
  601.   }
  602.   gifin_close_file();
  603.   zclose(zf);
  604.   image->title= dupString(name);
  605.   return(image);
  606. }
  607.  
  608. int gifIdent(fullname, name)
  609.      char *fullname, *name;
  610. { ZFILE        *zf;
  611.   unsigned int  ret;
  612.  
  613.   if (! (zf= zopen(fullname)))
  614.     return(0);
  615.   if ((gifin_open_file(zf) == GIFIN_SUCCESS) &&
  616.       (gifin_open_image() == GIFIN_SUCCESS)) {
  617.     tellAboutImage(name);
  618.     ret= 1;
  619.   }
  620.   else
  621.     ret= 0;
  622.   gifin_close_file();
  623.   zclose(zf);
  624.   return(ret);
  625. }
  626.