home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / gifload.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  28.6 KB  |  1,189 lines

  1. /* GIF loading file filter for The GIMP version 1.0/1.1
  2.  *
  3.  *    - Adam D. Moss
  4.  *    - Peter Mattis
  5.  *    - Spencer Kimball
  6.  *
  7.  *      Based around original GIF code by David Koblas.
  8.  *
  9.  *
  10.  * Version 1.0.3 - 2000/03/31
  11.  *                        Adam D. Moss - <adam@gimp.org> <adam@foxbox.org>
  12.  */
  13. /*
  14.  * This filter uses code taken from the "giftopnm" and "ppmtogif" programs
  15.  *    which are part of the "netpbm" package.
  16.  */
  17. /*
  18.  *  "The Graphics Interchange Format(c) is the Copyright property of
  19.  *  CompuServe Incorporated.  GIF(sm) is a Service Mark property of
  20.  *  CompuServe Incorporated." 
  21.  */
  22.  
  23. /*
  24.  * REVISION HISTORY
  25.  *
  26.  * 2000/03/31
  27.  * 1.00.03 - Just mildly more useful comments/messages concerning frame
  28.  *     disposals.
  29.  *
  30.  * 99/11/20
  31.  * 1.00.02 - Fixed a couple of possible infinite loops where an
  32.  *     error condition was not being checked.  Also changed some g_message()s
  33.  *     back to g_warning()s as they should be (don't get carried away with
  34.  *     the user feedback fellahs, no-one wants to be told of every single
  35.  *     corrupt byte and block in its own little window.  :-( ).
  36.  *
  37.  * 99/11/11
  38.  * 1.00.01 - Fixed an uninitialized variable which has been around
  39.  *     forever... thanks to jrb@redhat.com for noticing that there
  40.  *     was a problem somewhere!
  41.  *
  42.  * 99/03/20
  43.  * 1.00.00 - GIF load-only code split from main GIF plugin.
  44.  *
  45.  * For previous revision information, please consult the comments
  46.  * in the 'gif' plugin.
  47.  */
  48.  
  49. /*
  50.  * TODO (more *'s means more important!)
  51.  *
  52.  * - PDB stuff for comments
  53.  *
  54.  * - Remove unused colourmap entries for GRAYSCALE images.
  55.  */
  56.  
  57. /* Copyright notice for code which this plugin was long ago derived from */
  58. /* +-------------------------------------------------------------------+ */
  59. /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
  60. /* |   Permission to use, copy, modify, and distribute this software   | */
  61. /* |   and its documentation for any purpose and without fee is hereby | */
  62. /* |   granted, provided that the above copyright notice appear in all | */
  63. /* |   copies and that both that copyright notice and this permission  | */
  64. /* |   notice appear in supporting documentation.  This software is    | */
  65. /* |   provided "as is" without express or implied warranty.           | */
  66. /* +-------------------------------------------------------------------+ */
  67.  
  68. #include "config.h"
  69.  
  70. #include <stdio.h>
  71. #include <stdlib.h>
  72. #include <string.h>
  73. #include <ctype.h>
  74.  
  75. #include <gtk/gtk.h>
  76.  
  77. #include <libgimp/gimp.h>
  78.  
  79. #include "libgimp/stdplugins-intl.h"
  80.  
  81.  
  82. /* uncomment the line below for a little debugging info */
  83. /* #define GIFDEBUG yesplease */
  84.  
  85.  
  86. /* Does the version of GIMP we're compiling for support
  87.    data attachments to images?  ('Parasites') */
  88. #ifdef GIMP_HAVE_PARASITES
  89. #define FACEHUGGERS aieee
  90. #endif
  91. /* PS: I know that technically facehuggers aren't parasites,
  92.    the pupal-forms are.  But facehuggers are ky00te. */
  93.  
  94.  
  95. /* Declare some local functions.
  96.  */
  97. static void   query      (void);
  98. static void   run        (gchar   *name,
  99.                           gint     nparams,
  100.                           GimpParam  *param,
  101.                           gint    *nreturn_vals,
  102.                           GimpParam **return_vals);
  103. static gint32 load_image (gchar   *filename);
  104.  
  105.  
  106. static guchar   used_cmap[3][256];
  107. static GimpRunModeType run_mode;
  108. static guchar   highest_used_index;
  109. static gboolean promote_to_rgb   = FALSE;
  110. static guchar   gimp_cmap[768];
  111. #ifdef FACEHUGGERS
  112. GimpParasite*      comment_parasite = NULL;
  113. #endif
  114.  
  115.  
  116. GimpPlugInInfo PLUG_IN_INFO =
  117. {
  118.   NULL,  /* init_proc  */
  119.   NULL,  /* quit_proc  */
  120.   query, /* query_proc */
  121.   run,   /* run_proc   */
  122. };
  123.  
  124.  
  125. MAIN ()
  126.  
  127. static void
  128. query (void)
  129. {
  130.   static GimpParamDef load_args[] =
  131.   {
  132.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  133.     { GIMP_PDB_STRING, "filename", "The name of the file to load" },
  134.     { GIMP_PDB_STRING, "raw_filename", "The name entered" }
  135.   };
  136.   static GimpParamDef load_return_vals[] =
  137.   {
  138.     { GIMP_PDB_IMAGE, "image", "Output image" }
  139.   };
  140.   static gint nload_args = sizeof (load_args) / sizeof (load_args[0]);
  141.   static gint nload_return_vals = (sizeof (load_return_vals) /
  142.                    sizeof (load_return_vals[0]));
  143.  
  144.   gimp_install_procedure ("file_gif_load",
  145.                           "loads files of Compuserve GIF file format",
  146.                           "FIXME: write help for gif_load",
  147.                           "Spencer Kimball, Peter Mattis, Adam Moss, David Koblas",
  148.                           "Spencer Kimball, Peter Mattis, Adam Moss, David Koblas",
  149.                           "1995-1997",
  150.                           "<Load>/GIF",
  151.               NULL,
  152.                           GIMP_PLUGIN,
  153.                           nload_args, nload_return_vals,
  154.                           load_args, load_return_vals);
  155.  
  156.   gimp_register_magic_load_handler ("file_gif_load",
  157.                     "gif",
  158.                     "",
  159.                     "0,string,GIF8");
  160. }
  161.  
  162.  
  163. static void
  164. run (gchar   *name,
  165.      gint     nparams,
  166.      GimpParam  *param,
  167.      gint    *nreturn_vals,
  168.      GimpParam **return_vals)
  169. {
  170.   static GimpParam values[2];
  171.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  172.   gint32        image_ID;
  173.  
  174.   run_mode = param[0].data.d_int32;
  175.  
  176.   *nreturn_vals = 1;
  177.   *return_vals  = values;
  178.   values[0].type          = GIMP_PDB_STATUS;
  179.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  180.  
  181.   if (strcmp (name, "file_gif_load") == 0)
  182.     {
  183.       INIT_I18N_UI();
  184.  
  185.       image_ID = load_image (param[1].data.d_string);
  186.  
  187.       /* The GIF format only tells you how many bits per pixel
  188.        *  are in the image, not the actual number of used indices (D'OH!)
  189.        *
  190.        * So if we're not careful, repeated load/save of a transparent GIF
  191.        *  without intermediate indexed->RGB->indexed pumps up the number of
  192.        *  bits used, as we add an index each time for the transparent
  193.        *  colour.  Ouch.  We either do some heavier analysis at save-time,
  194.        *  or trim down the number of GIMP colours at load-time.  We do the
  195.        *  latter for now.
  196.        */
  197. #ifdef GIFDEBUG
  198.       g_print ("GIF: Highest used index is %d\n", highest_used_index);
  199. #endif
  200.       if (!promote_to_rgb)
  201.     {
  202.       gimp_image_set_cmap (image_ID, gimp_cmap, highest_used_index+1);
  203.     }
  204.  
  205.       if (image_ID != -1)
  206.         {
  207.       *nreturn_vals = 2;
  208.           values[1].type         = GIMP_PDB_IMAGE;
  209.           values[1].data.d_image = image_ID;
  210.         }
  211.       else
  212.         {
  213.           status = GIMP_PDB_EXECUTION_ERROR;
  214.         }
  215.     }
  216.   else
  217.     {
  218.       status = GIMP_PDB_CALLING_ERROR;
  219.     }
  220.  
  221.   values[0].data.d_status = status;
  222. }
  223.  
  224.  
  225. #define MAXCOLORMAPSIZE  256
  226.  
  227. #define CM_RED           0
  228. #define CM_GREEN         1
  229. #define CM_BLUE          2
  230.  
  231. #define MAX_LZW_BITS     12
  232.  
  233. #define INTERLACE          0x40
  234. #define LOCALCOLORMAP      0x80
  235. #define BitSet(byte, bit)  (((byte) & (bit)) == (bit))
  236.  
  237. #define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
  238. #define LM_to_uint(a,b)         (((b)<<8)|(a))
  239.  
  240. #define GRAYSCALE        1
  241. #define COLOR            2
  242.  
  243. typedef unsigned char CMap[3][MAXCOLORMAPSIZE];
  244.  
  245. static struct
  246. {
  247.   unsigned int Width;
  248.   unsigned int Height;
  249.   CMap ColorMap;
  250.   unsigned int BitPixel;
  251.   unsigned int ColorResolution;
  252.   unsigned int Background;
  253.   unsigned int AspectRatio;
  254.   /*
  255.    **
  256.    */
  257.   int GrayScale;
  258. } GifScreen;
  259.  
  260. static struct
  261. {
  262.   int transparent;
  263.   int delayTime;
  264.   int inputFlag;
  265.   int disposal;
  266. } Gif89 = { -1, -1, -1, 0 };
  267.  
  268. int verbose = FALSE;
  269. int showComment = TRUE;
  270. char *globalcomment = NULL;
  271. gint globalusecomment = TRUE;
  272.  
  273. static int ReadColorMap (FILE *, int, CMap, int *);
  274. static int DoExtension (FILE *, int);
  275. static int GetDataBlock (FILE *, unsigned char *);
  276. static int GetCode (FILE *, int, int);
  277. static int LZWReadByte (FILE *, int, int);
  278. static gint32 ReadImage (FILE *, char *, int, int, CMap, int, int, int, int,
  279.              guint, guint, guint, guint);
  280.  
  281.  
  282. static gint32
  283. load_image (gchar *filename)
  284. {
  285.   FILE *fd;
  286.   char * name_buf;
  287.   unsigned char buf[16];
  288.   unsigned char c;
  289.   CMap localColorMap;
  290.   int grayScale;
  291.   int useGlobalColormap;
  292.   int bitPixel;
  293.   int imageCount = 0;
  294.   char version[4];
  295.   gint32 image_ID = -1;
  296.  
  297.   fd = fopen (filename, "rb");
  298.   if (!fd)
  299.     {
  300.       g_message ("GIF: can't open \"%s\"\n", filename);
  301.       return -1;
  302.     }
  303.  
  304.   if (run_mode != GIMP_RUN_NONINTERACTIVE)
  305.     {
  306.       name_buf = g_strdup_printf (_("Loading %s:"), filename);
  307.       gimp_progress_init (name_buf);
  308.       g_free (name_buf);
  309.     }
  310.  
  311.   if (!ReadOK (fd, buf, 6))
  312.     {
  313.       g_message ("GIF: error reading magic number\n");
  314.       return -1;
  315.     }
  316.  
  317.   if (strncmp ((char *) buf, "GIF", 3) != 0)
  318.     {
  319.       g_message ("GIF: not a GIF file\n");
  320.       return -1;
  321.     }
  322.  
  323.   strncpy (version, (char *) buf + 3, 3);
  324.   version[3] = '\0';
  325.  
  326.   if ((strcmp (version, "87a") != 0) && (strcmp (version, "89a") != 0))
  327.     {
  328.       g_message ("GIF: bad version number, not '87a' or '89a'\n");
  329.       return -1;
  330.     }
  331.  
  332.   if (!ReadOK (fd, buf, 7))
  333.     {
  334.       g_message ("GIF: failed to read screen descriptor\n");
  335.       return -1;
  336.     }
  337.  
  338.   GifScreen.Width = LM_to_uint (buf[0], buf[1]);
  339.   GifScreen.Height = LM_to_uint (buf[2], buf[3]);
  340.   GifScreen.BitPixel = 2 << (buf[4] & 0x07);
  341.   GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
  342.   GifScreen.Background = buf[5];
  343.   GifScreen.AspectRatio = buf[6];
  344.  
  345.   if (BitSet (buf[4], LOCALCOLORMAP))
  346.     {
  347.       /* Global Colormap */
  348.       if (ReadColorMap (fd, GifScreen.BitPixel, GifScreen.ColorMap, &GifScreen.GrayScale))
  349.     {
  350.       g_message ("GIF: error reading global colormap\n");
  351.       return -1;
  352.     }
  353.     }
  354.  
  355.   if (GifScreen.AspectRatio != 0 && GifScreen.AspectRatio != 49)
  356.     {
  357.       g_message ("GIF: warning - non-square pixels\n");
  358.     }
  359.  
  360.  
  361.   highest_used_index = 0;
  362.       
  363.  
  364.   for (;;)
  365.     {
  366.       if (!ReadOK (fd, &c, 1))
  367.     {
  368.       g_message ("GIF: EOF / read error on image data\n");
  369.       return image_ID; /* will be -1 if failed on first image! */
  370.     }
  371.  
  372.       if (c == ';')
  373.     {
  374.       /* GIF terminator */
  375.       return image_ID;
  376.     }
  377.  
  378.       if (c == '!')
  379.     {
  380.       /* Extension */
  381.       if (!ReadOK (fd, &c, 1))
  382.         {
  383.           g_message ("GIF: EOF / read error on extension function code\n");
  384.           return image_ID; /* will be -1 if failed on first image! */
  385.         }
  386.       DoExtension (fd, c);
  387.       continue;
  388.     }
  389.  
  390.       if (c != ',')
  391.     {
  392.       /* Not a valid start character */
  393.       g_warning ("GIF: bogus character 0x%02x, ignoring\n", (int) c);
  394.       continue;
  395.     }
  396.  
  397.       ++imageCount;
  398.  
  399.       if (!ReadOK (fd, buf, 9))
  400.     {
  401.       g_message ("GIF: couldn't read left/top/width/height\n");
  402.       return image_ID; /* will be -1 if failed on first image! */
  403.     }
  404.  
  405.       useGlobalColormap = !BitSet (buf[8], LOCALCOLORMAP);
  406.  
  407.       bitPixel = 1 << ((buf[8] & 0x07) + 1);
  408.  
  409.       if (!useGlobalColormap)
  410.     {
  411.       if (ReadColorMap (fd, bitPixel, localColorMap, &grayScale))
  412.         {
  413.           g_message ("GIF: error reading local colormap\n");
  414.           return image_ID; /* will be -1 if failed on first image! */
  415.         }
  416.       image_ID = ReadImage (fd, filename, LM_to_uint (buf[4], buf[5]),
  417.                 LM_to_uint (buf[6], buf[7]),
  418.                 localColorMap, bitPixel,
  419.                 grayScale,
  420.                 BitSet (buf[8], INTERLACE), imageCount,
  421.                 (guint) LM_to_uint (buf[0], buf[1]),
  422.                 (guint) LM_to_uint (buf[2], buf[3]),
  423.                 GifScreen.Width,
  424.                 GifScreen.Height
  425.                 );
  426.     }
  427.       else
  428.     {
  429.       image_ID = ReadImage (fd, filename, LM_to_uint (buf[4], buf[5]),
  430.                 LM_to_uint (buf[6], buf[7]),
  431.                 GifScreen.ColorMap, GifScreen.BitPixel,
  432.                 GifScreen.GrayScale,
  433.                 BitSet (buf[8], INTERLACE), imageCount,
  434.                 (guint) LM_to_uint (buf[0], buf[1]),
  435.                 (guint) LM_to_uint (buf[2], buf[3]),
  436.                 GifScreen.Width,
  437.                 GifScreen.Height
  438.                 );
  439.     }
  440.  
  441. #ifdef FACEHUGGERS
  442.       if (comment_parasite != NULL)
  443.     {
  444.       gimp_image_parasite_attach (image_ID, comment_parasite);
  445.       gimp_parasite_free (comment_parasite);
  446.       comment_parasite = NULL;
  447.     }
  448. #endif
  449.  
  450.     }
  451.  
  452.   return image_ID;
  453. }
  454.  
  455. static int
  456. ReadColorMap (FILE *fd,
  457.           int   number,
  458.           CMap  buffer,
  459.           int  *format)
  460. {
  461.   int i;
  462.   unsigned char rgb[3];
  463.   int flag;
  464.  
  465.   flag = TRUE;
  466.  
  467.   for (i = 0; i < number; ++i)
  468.     {
  469.       if (!ReadOK (fd, rgb, sizeof (rgb)))
  470.     {
  471.       g_message ("GIF: bad colormap\n");
  472.       return TRUE;
  473.     }
  474.  
  475.       buffer[CM_RED][i] = rgb[0];
  476.       buffer[CM_GREEN][i] = rgb[1];
  477.       buffer[CM_BLUE][i] = rgb[2];
  478.  
  479.       flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
  480.     }
  481.  
  482.   *format = (flag) ? GRAYSCALE : COLOR;
  483.  
  484.   return FALSE;
  485. }
  486.  
  487. static int
  488. DoExtension (FILE *fd,
  489.          int   label)
  490. {
  491.   static guchar buf[256];
  492.   char *str;
  493.  
  494.   switch (label)
  495.     {
  496.     case 0x01:            /* Plain Text Extension */
  497.       str = "Plain Text Extension";
  498. #ifdef notdef
  499.       if (GetDataBlock (fd, (unsigned char *) buf) == 0)
  500.     ;
  501.  
  502.       lpos = LM_to_uint (buf[0], buf[1]);
  503.       tpos = LM_to_uint (buf[2], buf[3]);
  504.       width = LM_to_uint (buf[4], buf[5]);
  505.       height = LM_to_uint (buf[6], buf[7]);
  506.       cellw = buf[8];
  507.       cellh = buf[9];
  508.       foreground = buf[10];
  509.       background = buf[11];
  510.  
  511.       while (GetDataBlock (fd, (unsigned char *) buf) > 0)
  512.     {
  513.       PPM_ASSIGN (image[ypos][xpos],
  514.               cmap[CM_RED][v],
  515.               cmap[CM_GREEN][v],
  516.               cmap[CM_BLUE][v]);
  517.       ++index;
  518.     }
  519.  
  520.       return FALSE;
  521. #else
  522.       break;
  523. #endif
  524.     case 0xff:            /* Application Extension */
  525.       str = "Application Extension";
  526.       break;
  527.     case 0xfe:            /* Comment Extension */
  528.       str = "Comment Extension";
  529.       while (GetDataBlock (fd, (unsigned char *) buf) > 0)
  530.     {
  531. #ifdef FACEHUGGERS
  532.       if (comment_parasite != NULL)
  533.         {
  534.           gimp_parasite_free (comment_parasite);
  535.         }
  536.         
  537.       comment_parasite = gimp_parasite_new ("gimp-comment",GIMP_PARASITE_PERSISTENT,
  538.                         strlen(buf)+1, (void*)buf);
  539. #else
  540.       if (showComment)
  541.         g_print ("GIF: gif comment: %s\n", buf);
  542. #endif
  543.     }
  544.       return TRUE;
  545.       break;
  546.     case 0xf9:            /* Graphic Control Extension */
  547.       str = "Graphic Control Extension";
  548.       (void) GetDataBlock (fd, (unsigned char *) buf);
  549.       Gif89.disposal = (buf[0] >> 2) & 0x7;
  550.       Gif89.inputFlag = (buf[0] >> 1) & 0x1;
  551.       Gif89.delayTime = LM_to_uint (buf[1], buf[2]);
  552.       if ((buf[0] & 0x1) != 0)
  553.     Gif89.transparent = buf[3];
  554.       else
  555.     Gif89.transparent = -1;
  556.  
  557.       while (GetDataBlock (fd, (unsigned char *) buf) > 0)
  558.     ;
  559.       return FALSE;
  560.       break;
  561.     default:
  562.       str = (char *)buf;
  563.       sprintf ((char *)buf, "UNKNOWN (0x%02x)", label);
  564.       break;
  565.     }
  566.  
  567. #ifdef GIFDEBUG
  568.   g_print ("GIF: got a '%s'\n", str);
  569. #endif
  570.  
  571.   while (GetDataBlock (fd, (unsigned char *) buf) > 0)
  572.     ;
  573.  
  574.   return FALSE;
  575. }
  576.  
  577. int ZeroDataBlock = FALSE;
  578.  
  579. static int
  580. GetDataBlock (FILE          *fd,
  581.           unsigned char *buf)
  582. {
  583.   unsigned char count;
  584.  
  585.   if (!ReadOK (fd, &count, 1))
  586.     {
  587.       g_message ("GIF: error in getting DataBlock size\n");
  588.       return -1;
  589.     }
  590.  
  591.   ZeroDataBlock = count == 0;
  592.  
  593.   if ((count != 0) && (!ReadOK (fd, buf, count)))
  594.     {
  595.       g_message ("GIF: error in reading DataBlock\n");
  596.       return -1;
  597.     }
  598.  
  599.   return count;
  600. }
  601.  
  602. static int
  603. GetCode (FILE *fd,
  604.      int   code_size,
  605.      int   flag)
  606. {
  607.   static unsigned char buf[280];
  608.   static int curbit, lastbit, done, last_byte;
  609.   int i, j, ret;
  610.   unsigned char count;
  611.  
  612.   if (flag)
  613.     {
  614.       curbit = 0;
  615.       lastbit = 0;
  616.       done = FALSE;
  617.       last_byte = 2;
  618.       return 0;
  619.     }
  620.  
  621.   if ((curbit + code_size) >= lastbit)
  622.     {
  623.       if (done)
  624.     {
  625.       if (curbit >= lastbit)
  626.         {
  627.           g_message ("GIF: ran off the end of my bits\n");
  628.           gimp_quit ();
  629.         }
  630.       return -1;
  631.     }
  632.  
  633.       buf[0] = buf[last_byte - 2];
  634.       buf[1] = buf[last_byte - 1];
  635.  
  636.       if ((count = GetDataBlock (fd, &buf[2])) <= 0)
  637.     done = TRUE;
  638.  
  639.       last_byte = 2 + count;
  640.       curbit = (curbit - lastbit) + 16;
  641.       lastbit = (2 + count) * 8;
  642.     }
  643.  
  644.   ret = 0;
  645.   for (i = curbit, j = 0; j < code_size; ++i, ++j)
  646.     ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
  647.  
  648.   curbit += code_size;
  649.  
  650.   return ret;
  651. }
  652.  
  653. static int
  654. LZWReadByte (FILE *fd,
  655.          int   flag,
  656.          int   input_code_size)
  657. {
  658.   static int fresh = FALSE;
  659.   int code, incode;
  660.   static int code_size, set_code_size;
  661.   static int max_code, max_code_size;
  662.   static int firstcode, oldcode;
  663.   static int clear_code, end_code;
  664.   static int table[2][(1 << MAX_LZW_BITS)];
  665.   static int stack[(1 << (MAX_LZW_BITS)) * 2], *sp;
  666.   register int i;
  667.  
  668.   if (flag)
  669.     {
  670.       set_code_size = input_code_size;
  671.       code_size = set_code_size + 1;
  672.       clear_code = 1 << set_code_size;
  673.       end_code = clear_code + 1;
  674.       max_code_size = 2 * clear_code;
  675.       max_code = clear_code + 2;
  676.  
  677.       GetCode (fd, 0, TRUE);
  678.  
  679.       fresh = TRUE;
  680.  
  681.       for (i = 0; i < clear_code; ++i)
  682.     {
  683.       table[0][i] = 0;
  684.       table[1][i] = i;
  685.     }
  686.       for (; i < (1 << MAX_LZW_BITS); ++i)
  687.     table[0][i] = table[1][0] = 0;
  688.  
  689.       sp = stack;
  690.  
  691.       return 0;
  692.     }
  693.   else if (fresh)
  694.     {
  695.       fresh = FALSE;
  696.       do
  697.     {
  698.       firstcode = oldcode =
  699.         GetCode (fd, code_size, FALSE);
  700.     }
  701.       while (firstcode == clear_code);
  702.       return firstcode;
  703.     }
  704.  
  705.   if (sp > stack)
  706.     return *--sp;
  707.  
  708.   while ((code = GetCode (fd, code_size, FALSE)) >= 0)
  709.     {
  710.       if (code == clear_code)
  711.     {
  712.       for (i = 0; i < clear_code; ++i)
  713.         {
  714.           table[0][i] = 0;
  715.           table[1][i] = i;
  716.         }
  717.       for (; i < (1 << MAX_LZW_BITS); ++i)
  718.         table[0][i] = table[1][i] = 0;
  719.       code_size = set_code_size + 1;
  720.       max_code_size = 2 * clear_code;
  721.       max_code = clear_code + 2;
  722.       sp = stack;
  723.       firstcode = oldcode =
  724.         GetCode (fd, code_size, FALSE);
  725.       return firstcode;
  726.     }
  727.       else if (code == end_code)
  728.     {
  729.       int count;
  730.       unsigned char buf[260];
  731.  
  732.       if (ZeroDataBlock)
  733.         return -2;
  734.  
  735.       while ((count = GetDataBlock (fd, buf)) > 0)
  736.         ;
  737.  
  738.       if (count != 0)
  739.         g_print ("GIF: missing EOD in data stream (common occurence)");
  740.       return -2;
  741.     }
  742.  
  743.       incode = code;
  744.  
  745.       if (code >= max_code)
  746.     {
  747.       *sp++ = firstcode;
  748.       code = oldcode;
  749.     }
  750.  
  751.       while (code >= clear_code)
  752.     {
  753.       *sp++ = table[1][code];
  754.       if (code == table[0][code])
  755.         {
  756.           g_message ("GIF: circular table entry BIG ERROR\n");
  757.           gimp_quit ();
  758.         }
  759.       code = table[0][code];
  760.     }
  761.  
  762.       *sp++ = firstcode = table[1][code];
  763.  
  764.       if ((code = max_code) < (1 << MAX_LZW_BITS))
  765.     {
  766.       table[0][code] = oldcode;
  767.       table[1][code] = firstcode;
  768.       ++max_code;
  769.       if ((max_code >= max_code_size) &&
  770.           (max_code_size < (1 << MAX_LZW_BITS)))
  771.         {
  772.           max_code_size *= 2;
  773.           ++code_size;
  774.         }
  775.     }
  776.  
  777.       oldcode = incode;
  778.  
  779.       if (sp > stack)
  780.     return *--sp;
  781.     }
  782.   return code;
  783. }
  784.  
  785. static gint32
  786. ReadImage (FILE *fd,
  787.        char *filename,
  788.        int   len,
  789.        int   height,
  790.        CMap  cmap,
  791.        int   ncols,
  792.        int   format,
  793.        int   interlace,
  794.        int   number,
  795.        guint   leftpos,
  796.        guint   toppos,
  797.        guint screenwidth,
  798.        guint screenheight)
  799. {
  800.   static gint32 image_ID;
  801.   static gint frame_number = 1;
  802.  
  803.   gint32 layer_ID;
  804.   GimpPixelRgn pixel_rgn;
  805.   GimpDrawable *drawable;
  806.   guchar *dest, *temp;
  807.   guchar c;
  808.   gint xpos = 0, ypos = 0, pass = 0;
  809.   gint cur_progress, max_progress;
  810.   gint v;
  811.   gint i, j;
  812.   gchar *framename;
  813.   gchar *framename_ptr;
  814.   gboolean alpha_frame = FALSE;
  815.   static int previous_disposal;
  816.  
  817.  
  818.  
  819.   /*
  820.    **  Initialize the Compression routines
  821.    */
  822.   if (!ReadOK (fd, &c, 1))
  823.     {
  824.       g_message ("GIF: EOF / read error on image data\n");
  825.       return -1;
  826.     }
  827.  
  828.   if (LZWReadByte (fd, TRUE, c) < 0)
  829.     {
  830.       g_message ("GIF: error while reading\n");
  831.       return -1;
  832.     }
  833.  
  834.   if (frame_number == 1 )
  835.     {
  836.       image_ID = gimp_image_new (screenwidth, screenheight, GIMP_INDEXED);
  837.       gimp_image_set_filename (image_ID, filename);
  838.  
  839.       for (i = 0, j = 0; i < ncols; i++)
  840.     {
  841.       used_cmap[0][i] = gimp_cmap[j++] = cmap[0][i];
  842.       used_cmap[1][i] = gimp_cmap[j++] = cmap[1][i];
  843.       used_cmap[2][i] = gimp_cmap[j++] = cmap[2][i];
  844.     }
  845.  
  846.       gimp_image_set_cmap (image_ID, gimp_cmap, ncols);
  847.  
  848.       if (Gif89.delayTime < 0)
  849.     framename = g_strdup (_("Background"));
  850.       else
  851.     framename = g_strdup_printf (_("Background (%dms)"), 10*Gif89.delayTime);
  852.  
  853.       previous_disposal = Gif89.disposal;
  854.  
  855.       if (Gif89.transparent == -1)
  856.     {
  857.       layer_ID = gimp_layer_new (image_ID, framename,
  858.                      len, height,
  859.                      GIMP_INDEXED_IMAGE, 100, GIMP_NORMAL_MODE);
  860.     }
  861.       else
  862.     {
  863.       layer_ID = gimp_layer_new (image_ID, framename,
  864.                      len, height,
  865.                      GIMP_INDEXEDA_IMAGE, 100, GIMP_NORMAL_MODE);
  866.       alpha_frame=TRUE;
  867.     }
  868.  
  869.       g_free (framename);
  870.     }
  871.   else /* NOT FIRST FRAME */
  872.     {
  873.       /* If the colourmap is now different, we have to promote to
  874.      RGB! */
  875.       if (!promote_to_rgb)
  876.     {
  877.       for (i=0;i<ncols;i++)
  878.         {
  879.           if (
  880.           (used_cmap[0][i] != cmap[0][i]) ||
  881.           (used_cmap[1][i] != cmap[1][i]) ||
  882.           (used_cmap[2][i] != cmap[2][i])
  883.           )
  884.         { /* Everything is RGB(A) from now on... sigh. */
  885.           promote_to_rgb = TRUE;
  886.           
  887.           /* Promote everything we have so far into RGB(A) */
  888. #ifdef GIFDEBUG
  889.           g_print ("GIF: Promoting image to RGB...\n");
  890. #endif
  891.           gimp_convert_rgb (image_ID);
  892.  
  893.           break;
  894.         }
  895.         }
  896.     }
  897.  
  898.       if (Gif89.delayTime < 0)
  899.     framename = g_strdup_printf (_("Frame %d"), frame_number);
  900.       else
  901.     framename = g_strdup_printf (_("Frame %d (%dms)"), frame_number, 10*Gif89.delayTime);
  902.  
  903.       switch (previous_disposal)
  904.     {
  905.     case 0x00: 
  906.       break; /* 'don't care' */
  907.     case 0x01: 
  908.       framename_ptr = framename;
  909.       framename = g_strconcat (framename, " (combine)", NULL);
  910.       g_free (framename_ptr);
  911.       break;
  912.     case 0x02: 
  913.       framename_ptr = framename;
  914.       framename = g_strconcat (framename, " (replace)", NULL); 
  915.       g_free (framename_ptr);
  916.       break;
  917.     case 0x03:  /* Rarely-used, and unhandled by many
  918.                loaders/players (including GIMP: we treat as
  919.                'combine' mode). */
  920.       framename_ptr = framename;
  921.       framename = g_strconcat (framename, " (combine) (!)", NULL); 
  922.       g_free (framename_ptr);
  923.       break;
  924.     case 0x04: /* I've seen a composite of this type. stvo_online_banner2.gif */
  925.     case 0x05:
  926.     case 0x06: /* I've seen a composite of this type. bn31.Gif */
  927.     case 0x07:
  928.       framename_ptr = framename;
  929.       framename = g_strconcat (framename, " (unknown disposal)", NULL);
  930.       g_free (framename_ptr);
  931.       g_message ("GIF: Hmm... Composite type %d.  Interesting.\n"
  932.                      "Please forward this GIF to the "
  933.              "GIF plugin author!\n  (adam@foxbox.org)\n",
  934.                      previous_disposal);
  935.       break;
  936.     default: 
  937.       g_message ("GIF: Something got corrupted.\n");
  938.       break;
  939.     }
  940.       previous_disposal = Gif89.disposal;
  941.  
  942.       layer_ID = gimp_layer_new (image_ID, framename,
  943.                  len, height,
  944.                  promote_to_rgb ? GIMP_RGBA_IMAGE : GIMP_INDEXEDA_IMAGE,
  945.                  100, GIMP_NORMAL_MODE);
  946.       alpha_frame = TRUE;
  947.       g_free (framename);
  948.     }
  949.  
  950.   frame_number++;
  951.  
  952.   gimp_image_add_layer (image_ID, layer_ID, 0);
  953.   gimp_layer_translate (layer_ID, (gint)leftpos, (gint)toppos);
  954.  
  955.   drawable = gimp_drawable_get (layer_ID);
  956.  
  957.   cur_progress = 0;
  958.   max_progress = height;
  959.  
  960.   if (alpha_frame)
  961.     dest = (guchar *) g_malloc (len * height *
  962.                 (promote_to_rgb ? 4 : 2));
  963.   else
  964.     dest = (guchar *) g_malloc (len * height);
  965.  
  966.   if (verbose)
  967.     g_print ("GIF: reading %d by %d%s GIF image, ncols=%d\n",
  968.          len, height, interlace ? " interlaced" : "", ncols);
  969.  
  970.   if (!alpha_frame && promote_to_rgb)
  971.     {
  972.       g_message ("GIF: Ouchie!  Can't handle non-alpha RGB frames.\n     Please mail the plugin author.  (adam@gimp.org)\n");
  973.       gimp_quit();
  974.     }
  975.  
  976.   while ((v = LZWReadByte (fd, FALSE, c)) >= 0)
  977.     {
  978.       if (alpha_frame)
  979.     {
  980.       if (((guchar)v > highest_used_index) && !(v == Gif89.transparent))
  981.         highest_used_index = (guchar)v;
  982.  
  983.       if (promote_to_rgb)
  984.         {
  985.           temp = dest + ( (ypos * len) + xpos ) * 4;
  986.           *(temp  ) = (guchar) cmap[0][v];
  987.           *(temp+1) = (guchar) cmap[1][v];
  988.           *(temp+2) = (guchar) cmap[2][v];
  989.           *(temp+3) = (guchar) ((v == Gif89.transparent) ? 0 : 255);
  990.         }
  991.       else
  992.         {
  993.           temp = dest + ( (ypos * len) + xpos ) * 2;
  994.           *temp = (guchar) v;
  995.           *(temp+1) = (guchar) ((v == Gif89.transparent) ? 0 : 255);
  996.         }
  997.     }
  998.       else
  999.     {
  1000.       if ((guchar)v > highest_used_index)
  1001.         highest_used_index = (guchar)v;
  1002.  
  1003.       temp = dest + (ypos * len) + xpos;
  1004.       *temp = (guchar) v;
  1005.     }
  1006.  
  1007.       xpos++;
  1008.       if (xpos == len)
  1009.     {
  1010.       xpos = 0;
  1011.       if (interlace)
  1012.         {
  1013.           switch (pass)
  1014.         {
  1015.         case 0:
  1016.         case 1:
  1017.           ypos += 8;
  1018.           break;
  1019.         case 2:
  1020.           ypos += 4;
  1021.           break;
  1022.         case 3:
  1023.           ypos += 2;
  1024.           break;
  1025.         }
  1026.  
  1027.           if (ypos >= height)
  1028.         {
  1029.           pass++;
  1030.           switch (pass)
  1031.             {
  1032.             case 1:
  1033.               ypos = 4;
  1034.               break;
  1035.             case 2:
  1036.               ypos = 2;
  1037.               break;
  1038.             case 3:
  1039.               ypos = 1;
  1040.               break;
  1041.             default:
  1042.               goto fini;
  1043.             }
  1044.         }
  1045.         }
  1046.       else
  1047.         {
  1048.           ypos++;
  1049.         }
  1050.  
  1051.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  1052.         {
  1053.           cur_progress++;
  1054.           if ((cur_progress % 16) == 0)
  1055.         gimp_progress_update ((double) cur_progress / (double) max_progress);
  1056.         }
  1057.     }
  1058.       if (ypos >= height)
  1059.     break;
  1060.     }
  1061.  
  1062. fini:
  1063.   if (LZWReadByte (fd, FALSE, c) >= 0)
  1064.     g_print ("GIF: too much input data, ignoring extra...\n");
  1065.  
  1066.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE);
  1067.   gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, 0, drawable->width, drawable->height);
  1068.  
  1069.   g_free (dest);
  1070.  
  1071.   gimp_drawable_flush (drawable);
  1072.   gimp_drawable_detach (drawable);
  1073.  
  1074.   return image_ID;
  1075. }
  1076.  
  1077.  
  1078.  
  1079. /* ppmtogif.c - read a portable pixmap and produce a GIF file
  1080. **
  1081. ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
  1082. ** Lempel-Zim compression based on "compress".
  1083. **
  1084. ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
  1085. **
  1086. **
  1087. ** Copyright (C) 1989 by Jef Poskanzer.
  1088. **
  1089. ** Permission to use, copy, modify, and distribute this software and its
  1090. ** documentation for any purpose and without fee is hereby granted, provided
  1091. ** that the above copyright notice appear in all copies and that both that
  1092. ** copyright notice and this permission notice appear in supporting
  1093. ** documentation.  This software is provided "as is" without express or
  1094. ** implied warranty.
  1095. **
  1096. ** The Graphics Interchange Format(c) is the Copyright property of
  1097. ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
  1098. ** CompuServe Incorporated.
  1099. */
  1100.  
  1101. #define MAXCOLORS 256
  1102.  
  1103. /*
  1104.  * Pointer to function returning an int
  1105.  */
  1106. typedef int (*ifunptr) (int, int);
  1107.  
  1108. /*
  1109.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  1110.  */
  1111. typedef int code_int;
  1112.  
  1113. #ifdef SIGNED_COMPARE_SLOW
  1114. typedef unsigned long int count_int;
  1115. typedef unsigned short int count_short;
  1116. #else /*SIGNED_COMPARE_SLOW */
  1117. typedef long int count_int;
  1118. #endif /*SIGNED_COMPARE_SLOW */
  1119.  
  1120.  
  1121.  
  1122. int rowstride;
  1123. guchar *pixels;
  1124. int cur_progress;
  1125. int max_progress;
  1126.  
  1127.  
  1128.  
  1129.  
  1130. /* public */
  1131.  
  1132.  
  1133.  
  1134. /***************************************************************************
  1135.  *
  1136.  *  GIFCOMPR.C       - GIF Image compression routines
  1137.  *
  1138.  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
  1139.  *  David Rowley (mgardi@watdcsu.waterloo.edu)
  1140.  *
  1141.  ***************************************************************************/
  1142.  
  1143. /*
  1144.  * General DEFINEs
  1145.  */
  1146.  
  1147. #define GIF_BITS    12
  1148.  
  1149. #define HSIZE  5003        /* 80% occupancy */
  1150.  
  1151. #ifdef NO_UCHAR
  1152. typedef char char_type;
  1153. #else /*NO_UCHAR */
  1154. typedef unsigned char char_type;
  1155. #endif /*NO_UCHAR */
  1156.  
  1157. /*
  1158.  
  1159.  * GIF Image compression - modified 'compress'
  1160.  *
  1161.  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  1162.  *
  1163.  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  1164.  *              Jim McKie               (decvax!mcvax!jim)
  1165.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  1166.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  1167.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  1168.  *              Joe Orost               (decvax!vax135!petsd!joe)
  1169.  *
  1170.  */
  1171. #include <ctype.h>
  1172.  
  1173. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  1174.  
  1175. #ifdef COMPATIBLE        /* But wrong! */
  1176. #define MAXCODE(Mn_bits)        ((code_int) 1 << (Mn_bits) - 1)
  1177. #else /*COMPATIBLE */
  1178. #define MAXCODE(Mn_bits)        (((code_int) 1 << (Mn_bits)) - 1)
  1179. #endif /*COMPATIBLE */
  1180.  
  1181.  
  1182. const code_int hsize = HSIZE;    /* the original reason for this being
  1183.                    variable was "for dynamic table sizing",
  1184.                    but since it was never actually changed
  1185.                    I made it const   --Adam. */
  1186.  
  1187.  
  1188. /* The End */
  1189.