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