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