1 /* cgif.c -- a merge of some GIF-decoding files from giflib by E.S.Raymond
2  * by pts@fazekas.hu at Wed Feb 27 13:18:04 CET 2002
3 
4 The GIFLIB distribution is Copyright (c) 1997  Eric S. Raymond
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23  */
24 
25 /*The creators of the GIF format require the following
26   acknowledgement:
27   The Graphics Interchange Format(c) is the Copyright property of
28   CompuServe Incorporated. GIF(sm) is a Service Mark property of
29   CompuServe Incorporated.
30 */
31 
32 #ifdef __GNUC__
33 #ifndef __clang__
34 #pragma implementation
35 #endif
36 #endif
37 
38 /**** pts: not an ANSI C function */
39 #undef EXTERN_C
40 #ifdef __cplusplus
41 #define EXTERN_C extern "C"
42 #define CGIFFF CGIF::
43 #else
44 #define EXTERN_C extern
45 #define CGIFFF
46 #endif
47 #if OBJDEP
48 #  warning PROVIDES: cgif
49 #endif
50 
51 #if 0
52 EXTERN_C FILE *fdopen (int fildes, const char *mode); /* GCC 3.0 SUXX */
53 #else
54 #undef  _POSIX_SOURCE
55 #define _POSIX_SOURCE 1
56 #undef  _POSIX_C_SOURCE
57 #define _POSIX_C_SOURCE 2
58 #endif
59 
60 /* --- gifalloc.c */
61 
62 /*****************************************************************************
63 *   "Gif-Lib" - Yet another gif library.				     *
64 *									     *
65 * Written by:  Gershon Elber				Ver 0.1, Jun. 1989   *
66 * Extensively hacked by: Eric S. Raymond		Ver 1.?, Sep 1992    *
67 ******************************************************************************
68 * GIF construction tools						      *
69 ******************************************************************************
70 * History:								     *
71 * 15 Sep 92 - Version 1.0 by Eric Raymond.				     *
72 *****************************************************************************/
73 
74 // #undef __STRICT_ANSI__ /* for MINGW32 open() !! */
75 #include <stdio.h>
76 #include "cgif.h"
77 
78 /**** pts ****/
79 #include <stdlib.h> /* malloc(), calloc(), free(), realloc() */
80 #include <string.h> /* memset() */
81 
82 
83 //#include <unistd.h>
84 
85 #if USE_CGIF_FDOPEN
86 #include <fcntl.h> /* open() */
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #  if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER)
90 #    undef __STRICT_ANSI__
91 #    include <io.h>
92      /*#define open _open*/
93 #  endif
94 #endif
95 
96 /* --- gif_err.c */
97 
98 /*****************************************************************************
99 *   "Gif-Lib" - Yet another gif library.				     *
100 *									     *
101 * Written by:  Gershon Elber			IBM PC Ver 0.1,	Jun. 1989    *
102 ******************************************************************************
103 * Handle error reporting for the GIF library.				     *
104 ******************************************************************************
105 * History:								     *
106 * 17 Jun 89 - Version 1.0 by Gershon Elber.				     *
107 *****************************************************************************/
108 
109 /* #include <stdio.h> already */
110 /* #include "gif_lib.h" already */
111 
112 /* --- dgif_lib.c */
113 
114 /******************************************************************************
115 *   "Gif-Lib" - Yet another gif library.				      *
116 *									      *
117 * Written by:  Gershon Elber			IBM PC Ver 1.1,	Aug. 1990     *
118 *******************************************************************************
119 * The kernel of the GIF Decoding process can be found here.		      *
120 *******************************************************************************
121 * History:								      *
122 * 16 Jun 89 - Version 1.0 by Gershon Elber.				      *
123 *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
124 ******************************************************************************/
125 
126 #ifdef __MSDOS__
127 #include <io.h>
128 #include <alloc.h>
129 #include <stdlib.h>
130 #include <sys\stat.h>
131 #else
132 #include <sys/types.h>
133 #include <sys/stat.h>
134 #endif /* __MSDOS__ */
135 
136 #include <fcntl.h>
137 /* #include <stdio.h> already */
138 /* #include <string.h> already */
139 /* #include "gif_lib.h" already */
140 
141 /* #include <stdlib.h> already */ /* malloc(), free() */
142 #include <assert.h>
143 
144 /* ---- */
145 
146 /* --- gif_err.c */
147 
148 /* #define PROGRAM_NAME	"GIF_LIBRARY" */
149 
150 int CGIFFF _GifError = 0;
151 
152 /*****************************************************************************
153 * Return the last GIF error (0 if none) and reset the error.		     *
154 *****************************************************************************/
GifLastError(void)155 int CGIFFF GifLastError(void)
156 {
157     int i = _GifError;
158 
159     _GifError = 0;
160 
161     return i;
162 }
163 
164 /**** pts ****/
165 /** May return NULL. */
GetGifError(void)166 PTS_const char *CGIFFF GetGifError(void)
167 {
168     PTS_const char *Err;
169 
170     switch(_GifError) {
171 #if 0 /**** pts ****/
172 	case E_GIF_ERR_OPEN_FAILED:
173 	    Err = "Failed to open given file";
174 	    break;
175 	case E_GIF_ERR_WRITE_FAILED:
176 	    Err = "Failed to Write to given file";
177 	    break;
178 	case E_GIF_ERR_HAS_SCRN_DSCR:
179 	    Err = "Screen Descriptor already been set";
180 	    break;
181 	case E_GIF_ERR_HAS_IMAG_DSCR:
182 	    Err = "Image Descriptor is still active";
183 	    break;
184 	case E_GIF_ERR_NO_COLOR_MAP:
185 	    Err = "Neither Global Nor Local color map";
186 	    break;
187 	case E_GIF_ERR_DATA_TOO_BIG:
188 	    Err = "#Pixels bigger than Width * Height";
189 	    break;
190 	case E_GIF_ERR_NOT_ENOUGH_MEM:
191 	    Err = "Fail to allocate required memory";
192 	    break;
193 	case E_GIF_ERR_DISK_IS_FULL:
194 	    Err = "Write failed (disk full?)";
195 	    break;
196 	case E_GIF_ERR_CLOSE_FAILED:
197 	    Err = "Failed to close given file";
198 	    break;
199 	case E_GIF_ERR_NOT_WRITEABLE:
200 	    Err = "Given file was not opened for write";
201 	    break;
202 #endif
203 	case D_GIF_ERR_OPEN_FAILED:
204 	    Err = "Failed to open given file";
205 	    break;
206 	case D_GIF_ERR_READ_FAILED:
207 	    Err = "Failed to Read from given file";
208 	    break;
209 	case D_GIF_ERR_NOT_GIF_FILE:
210 	    Err = "Given file is NOT GIF file";
211 	    break;
212 	case D_GIF_ERR_NO_SCRN_DSCR:
213 	    Err = "No Screen Descriptor detected";
214 	    break;
215 	case D_GIF_ERR_NO_IMAG_DSCR:
216 	    Err = "No Image Descriptor detected";
217 	    break;
218 	case D_GIF_ERR_NO_COLOR_MAP:
219 	    Err = "Neither Global Nor Local color map";
220 	    break;
221 	case D_GIF_ERR_WRONG_RECORD:
222 	    Err = "Wrong record type detected";
223 	    break;
224 	case D_GIF_ERR_DATA_TOO_BIG:
225 	    Err = "#Pixels bigger than Width * Height";
226 	    break;
227 	case D_GIF_ERR_NOT_ENOUGH_MEM:
228 	    Err = "Fail to allocate required memory";
229 	    break;
230 	case D_GIF_ERR_CLOSE_FAILED:
231 	    Err = "Failed to close given file";
232 	    break;
233 	case D_GIF_ERR_NOT_READABLE:
234 	    Err = "Given file was not opened for read";
235 	    break;
236 	case D_GIF_ERR_IMAGE_DEFECT:
237 	    Err = "Image is defective, decoding aborted";
238 	    break;
239 	case D_GIF_ERR_EOF_TOO_SOON:
240 	    Err = "Image EOF detected, before image complete";
241 	    break;
242 	default:
243 	    Err = NULL;
244 	    break;
245     }
246     return Err;
247 }
248 
249 /*****************************************************************************
250 * Print the last GIF error to stderr.					     *
251 *****************************************************************************/
PrintGifError(void)252 void CGIFFF PrintGifError(void)
253 {
254     PTS_const char *Err=GetGifError();
255     if (Err != NULL)
256 	fprintf(stderr, "\nGIF-LIB error: %s.\n", Err);
257     else
258 	fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError);
259 }
260 
261 /* --- gifalloc.c */
262 
263 #define MAXGIF(x, y)	(((x) > (y)) ? (x) : (y))
264 
265 /******************************************************************************
266 * Miscellaneous utility functions					      *
267 ******************************************************************************/
268 
BitSize(int n)269 static int BitSize(int n)
270 /* return smallest bitfield size n will fit in */
271 {
272     register	int i;
273 
274     for (i = 1; i <= 8; i++)
275 	if ((1 << i) >= n)
276 	    break;
277     return(i);
278 }
279 
280 
281 /******************************************************************************
282 * Color map object functions						      *
283 ******************************************************************************/
284 
MakeMapObject(int ColorCount,GifColorType * ColorMap)285 CGIFFF ColorMapObject *CGIFFF MakeMapObject(int ColorCount, GifColorType *ColorMap)
286 /*
287  * Allocate a color map of given size; initialize with contents of
288  * ColorMap if that pointer is non-NULL.
289  */
290 {
291     ColorMapObject *Object;
292 
293     if (ColorCount != (1 << BitSize(ColorCount)))
294 	return((ColorMapObject *)NULL);
295 
296     Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
297     if (Object == (ColorMapObject *)NULL)
298 	return((ColorMapObject *)NULL);
299 
300     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
301     if (Object->Colors == (GifColorType *)NULL)
302 	return((ColorMapObject *)NULL);
303 
304     Object->ColorCount = ColorCount;
305     Object->BitsPerPixel = BitSize(ColorCount);
306 
307     if (ColorMap)
308 	memcpy((char *)Object->Colors,
309 	       (char *)ColorMap, ColorCount * sizeof(GifColorType));
310 
311     return(Object);
312 }
313 
FreeMapObject(CGIFFF ColorMapObject * Object)314 void CGIFFF FreeMapObject(CGIFFF ColorMapObject *Object)
315 /*
316  * Free a color map object
317  */
318 {
319     free(Object->Colors);
320     free(Object);
321 }
322 
323 #if 0
324 void DumpColorMap(ColorMapObject *Object, FILE *fp)
325 {
326     if (Object)
327     {
328 	int i, j, Len = Object->ColorCount;
329 
330 	for (i = 0; i < Len; i+=4) {
331 	    for (j = 0; j < 4 && j < Len; j++) {
332 		fprintf(fp,
333 			"%3d: %02x %02x %02x   ", i + j,
334 		       Object->Colors[i + j].Red,
335 		       Object->Colors[i + j].Green,
336 		       Object->Colors[i + j].Blue);
337 	    }
338 	    fprintf(fp, "\n");
339 	}
340     }
341 }
342 #endif /* DEBUG */
343 
344 #if 0
345 ColorMapObject *CGIFFF UnionColorMap(
346 			 ColorMapObject *ColorIn1,
347 			 ColorMapObject *ColorIn2,
348 			 GifPixelType ColorTransIn2[])
349 /*
350  * Compute the union of two given color maps and return it.  If result can't
351  * fit into 256 colors, NULL is returned, the allocated union otherwise.
352  * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
353  * copied iff they didn't exist before.  ColorTransIn2 maps the old
354  * ColorIn2 into ColorUnion color map table.
355  */
356 {
357     int i, j, CrntSlot, RoundUpTo, NewBitSize;
358     ColorMapObject *ColorUnion;
359 
360     /*
361      * Allocate table which will hold the result for sure.
362      */
363     ColorUnion
364 	= MakeMapObject(MAXGIF(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL);
365 
366     if (ColorUnion == NULL)
367 	return(NULL);
368 
369     /* Copy ColorIn1 to ColorUnionSize; */
370     for (i = 0; i < ColorIn1->ColorCount; i++)
371 	ColorUnion->Colors[i] = ColorIn1->Colors[i];
372     CrntSlot = ColorIn1->ColorCount;
373 
374     /*
375      * Potentially obnoxious hack:
376      *
377      * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
378      * of table 1.  This is very useful if your display is limited to
379      * 16 colors.
380      */
381     while (ColorIn1->Colors[CrntSlot-1].Red == 0
382 	   && ColorIn1->Colors[CrntSlot-1].Green == 0
383 	   && ColorIn1->Colors[CrntSlot-1].Red == 0)
384 	CrntSlot--;
385 
386     /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
387     for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++)
388     {
389 	/* Let's see if this color already exists: */
390 	for (j = 0; j < ColorIn1->ColorCount; j++)
391 	    if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0)
392 		break;
393 
394 	if (j < ColorIn1->ColorCount)
395 	    ColorTransIn2[i] = j;	/* color exists in Color1 */
396 	else
397 	{
398 	    /* Color is new - copy it to a new slot: */
399 	    ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
400 	    ColorTransIn2[i] = CrntSlot++;
401 	}
402     }
403 
404     if (CrntSlot > 256)
405     {
406 	FreeMapObject(ColorUnion);
407 	return((ColorMapObject *)NULL);
408     }
409 
410     NewBitSize = BitSize(CrntSlot);
411     RoundUpTo = (1 << NewBitSize);
412 
413     if (RoundUpTo != ColorUnion->ColorCount)
414     {
415 	register GifColorType	*Map = ColorUnion->Colors;
416 
417 	/*
418 	 * Zero out slots up to next power of 2.
419 	 * We know these slots exist because of the way ColorUnion's
420 	 * start dimension was computed.
421 	 */
422 	for (j = CrntSlot; j < RoundUpTo; j++)
423 	    Map[j].Red = Map[j].Green = Map[j].Blue = 0;
424 
425 	/* perhaps we can shrink the map? */
426 	if (RoundUpTo < ColorUnion->ColorCount)
427 	    ColorUnion->Colors
428 		= (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo);
429     }
430 
431     ColorUnion->ColorCount = RoundUpTo;
432     ColorUnion->BitsPerPixel = NewBitSize;
433 
434     return(ColorUnion);
435 }
436 void ApplyTranslation(SavedImage *Image, GifPixelType Translation[])
437 /*
438  * Apply a given color translation to the raster bits of an image
439  */
440 {
441     register int i;
442     register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
443 
444     for (i = 0; i < RasterSize; i++)
445 	Image->RasterBits[i] = Translation[Image->RasterBits[i]];
446 }
447 #endif
448 
449 /******************************************************************************
450 * Extension record functions						      *
451 ******************************************************************************/
452 
453 #if 0 /**** pts ****/
454 void MakeExtension(SavedImage *New, int Function)
455 {
456     New->Function = Function;
457     /*
458      * Someday we might have to deal with multiple extensions.
459      */
460 }
461 #endif
462 
AddExtensionBlock(CGIFFF SavedImage * New,int Len,CGIFFF GifByteType ExtData[])463 int CGIFFF AddExtensionBlock(CGIFFF SavedImage *New, int Len, CGIFFF GifByteType ExtData[])
464 {
465     ExtensionBlock	*ep;
466 
467     if (New->ExtensionBlocks == NULL)
468 	New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
469     else
470 	New->ExtensionBlocks =
471 	    (ExtensionBlock *)realloc(New->ExtensionBlocks,
472 		      sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
473 
474     if (New->ExtensionBlocks == NULL)
475 	return(GIF_ERROR);
476 
477     ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
478 
479     if ((ep->Bytes = (GifByteType *)malloc(ep->ByteCount = Len)) == NULL)
480 	return(GIF_ERROR);
481 
482     if (ExtData)
483 	memcpy(ep->Bytes, ExtData, Len);
484 
485     return(GIF_OK);
486 }
487 
FreeExtension(CGIFFF SavedImage * Image)488 void CGIFFF FreeExtension(CGIFFF SavedImage *Image)
489 {
490     ExtensionBlock	*ep;
491 
492     for (ep = Image->ExtensionBlocks;
493 	 ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
494 	 ep++)
495 	(void) free((char *)ep->Bytes);
496     free((char *)Image->ExtensionBlocks);
497     Image->ExtensionBlocks = NULL;
498 }
499 
500 /******************************************************************************
501 * Image block allocation functions					      *
502 ******************************************************************************/
MakeSavedImage(CGIFFF GifFileType * GifFile,CGIFFF SavedImage * CopyFrom)503 CGIFFF SavedImage *CGIFFF MakeSavedImage(CGIFFF GifFileType *GifFile, CGIFFF SavedImage *CopyFrom)
504 /*
505  * Append an image block to the SavedImages array
506  */
507 {
508     SavedImage	*sp;
509 
510     if (GifFile->SavedImages == NULL)
511 	GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
512     else
513 	GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
514 				sizeof(SavedImage) * (GifFile->ImageCount+1));
515 
516     if (GifFile->SavedImages == NULL)
517 	return((SavedImage *)NULL);
518     else
519     {
520 	sp = &GifFile->SavedImages[GifFile->ImageCount++];
521 	memset((char *)sp, '\0', sizeof(SavedImage));
522 
523 	if (CopyFrom)
524 	{
525 	    memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
526 
527 	    /*
528 	     * Make our own allocated copies of the heap fields in the
529 	     * copied record.  This guards against potential aliasing
530 	     * problems.
531 	     */
532 
533 	    /* first, the local color map */
534 	    if (sp->ImageDesc.ColorMap)
535 		sp->ImageDesc.ColorMap =
536 		    MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
537 				  CopyFrom->ImageDesc.ColorMap->Colors);
538 
539 	    /* next, the raster */
540 	    sp->RasterBits = (GifPixelType *)malloc(sizeof(GifPixelType)
541 				* CopyFrom->ImageDesc.Height
542 				* CopyFrom->ImageDesc.Width);
543 	    memcpy(sp->RasterBits,
544 		   CopyFrom->RasterBits,
545 		   sizeof(GifPixelType)
546 			* CopyFrom->ImageDesc.Height
547 			* CopyFrom->ImageDesc.Width);
548 
549 	    /* finally, the extension blocks */
550 	    if (sp->ExtensionBlocks)
551 	    {
552 		sp->ExtensionBlocks
553 		    = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
554 					      * CopyFrom->ExtensionBlockCount);
555 		memcpy(sp->ExtensionBlocks,
556 		   CopyFrom->ExtensionBlocks,
557 		   sizeof(ExtensionBlock)
558 		   	* CopyFrom->ExtensionBlockCount);
559 
560 		/*
561 		 * For the moment, the actual blocks can take their
562 		 * chances with free().  We'll fix this later.
563 		 */
564 	    }
565 	}
566 
567 	return(sp);
568     }
569 }
570 
FreeSavedImages(CGIFFF GifFileType * GifFile)571 void CGIFFF FreeSavedImages(CGIFFF GifFileType *GifFile)
572 {
573     SavedImage	*sp;
574 
575     for (sp = GifFile->SavedImages;
576 	 sp < GifFile->SavedImages + GifFile->ImageCount;
577 	 sp++)
578     {
579 	if (sp->ImageDesc.ColorMap)
580 	    FreeMapObject(sp->ImageDesc.ColorMap);
581 
582 	if (sp->RasterBits)
583 	    free((char *)sp->RasterBits);
584 
585 	if (sp->ExtensionBlocks)
586 	    FreeExtension(sp);
587     }
588     free((char *) GifFile->SavedImages);
589 }
590 
591 /* --- dgif_lib.c */
592 
593 #define GIF_FILE_BUFFER_SIZE 16384  /* Files uses bigger buffers than usual. */
594 
595 /* #define PROGRAM_NAME	"GIFLIB" */
596 
597 #define COMMENT_EXT_FUNC_CODE	0xfe /* Extension function code for comment. */
598 #define GIF_STAMP	"GIFVER"	 /* First chars in file - GIF stamp. */
599 #define GIF_STAMP_LEN	sizeof(GIF_STAMP) - 1
600 #define GIF_VERSION_POS	3		/* Version first character in stamp. */
601 
602 #define LZ_MAX_CODE	4095		/* Biggest code possible in 12 bits. */
603 #define LZ_BITS		12
604 
605 #define FILE_STATE_READ		0x01/* 1 write, 0 read - EGIF_LIB compatible.*/
606 
607 #define FLUSH_OUTPUT		4096    /* Impossible code, to signal flush. */
608 #define FIRST_CODE		4097    /* Impossible code, to signal first. */
609 #define NO_SUCH_CODE		4098    /* Impossible code, to signal empty. */
610 
611 #define IS_READABLE(Private)	(!(Private->FileState & FILE_STATE_READ))
612 
613 typedef struct GifFilePrivateType {
614     int FileState,
615 	/*FileHandle,*/			     /* Where all this data goes to! */
616 	BitsPerPixel,	    /* Bits per pixel (Codes uses at list this + 1). */
617 	ClearCode,				       /* The CLEAR LZ code. */
618 	EOFCode,				         /* The EOF LZ code. */
619 	RunningCode,		    /* The next code algorithm can generate. */
620 	RunningBits,/* The number of bits required to represent RunningCode. */
621 	MaxCode1,  /* 1 bigger than max. possible code, in RunningBits bits. */
622 	LastCode,		        /* The code before the current code. */
623 	CrntCode,				  /* Current algorithm code. */
624 	StackPtr,		         /* For character stack (see below). */
625 	CrntShiftState;		        /* Number of bits in CrntShiftDWord. */
626     unsigned long CrntShiftDWord;     /* For bytes decomposition into codes. */
627     unsigned long PixelCount;		       /* Number of pixels in image. */
628     FILE *File;						  /* File as stream. */
629     CGIFFF GifByteType Buf[256];	       /* Compressed input is buffered here. */
630     CGIFFF GifByteType Stack[LZ_MAX_CODE];	 /* Decoded pixels are stacked here. */
631     CGIFFF GifByteType Suffix[LZ_MAX_CODE+1];	       /* So we can trace the codes. */
632     unsigned int Prefix[LZ_MAX_CODE+1];
633 } GifFilePrivateType;
634 
635 /* extern int _GifError; */
636 
637 static int DGifGetWord(FILE *File, int *Word);
638 static int DGifSetupDecompress(CGIFFF GifFileType *GifFile);
639 static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line,
640 								int LineLen);
641 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
642 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code);
643 static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf,
644 						     CGIFFF GifByteType *NextByte);
645 
646 /******************************************************************************
647 *   Open a new gif file for read, given by its name.			      *
648 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
649 * info record. _GifError is cleared if succesfull.			      *
650 ******************************************************************************/
DGifOpenFileName(const char * FileName)651 CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName) {
652 #if 0 /**** pts ****/
653 CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName)
654 {
655     int FileHandle;
656 
657     if ((FileHandle = open(FileName, O_RDONLY
658 #ifdef __MSDOS__
659 			           | O_BINARY
660 #endif /* __MSDOS__ */
661 			                     )) == -1) {
662 	_GifError = D_GIF_ERR_OPEN_FAILED;
663 	return NULL;
664     }
665 
666     return DGifOpenFileHandle(FileHandle);
667 #else
668   FILE *f;
669   if (NULL==(f=fopen(FileName,"rb"))) { _GifError=D_GIF_ERR_OPEN_FAILED; return NULL; }
670   return DGifOpenFILE(f);
671 #endif
672 }
673 
674 #if USE_CGIF_FDOPEN
675 
676 /******************************************************************************
677 *   Update a new gif file, given its file handle.			      *
678 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
679 * info record. _GifError is cleared if succesfull.			      *
680 ******************************************************************************/
681 CGIFFF GifFileType *CGIFFF DGifOpenFileHandle(int FileHandle)
682 {
683     FILE *f;
684 
685 #ifdef __MSDOS__
686     setmode(FileHandle, O_BINARY);	  /* Make sure it is in binary mode. */
687     f = fdopen(FileHandle, "rb");		   /* Make it into a stream: */
688     setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
689 #else
690     f = fdopen(FileHandle, "rb");		   /* Make it into a stream: */
691 #endif /* __MSDOS__ */
692     return DGifOpenFILE(f);
693 }
694 #endif
695 
696 /**** pts ****/
697 CGIFFF GifFileType *CGIFFF DGifOpenFILE(void/*FILE*/ *f) {
698     char Buf[GIF_STAMP_LEN+1];
699     GifFileType *GifFile;
700     GifFilePrivateType *Private;
701     if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
702 	_GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
703 	return NULL;
704     }
705 
706     memset(GifFile, '\0', sizeof(GifFileType));
707 
708     if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
709 	== NULL) {
710 	_GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
711 	free((char *) GifFile);
712 	return NULL;
713     }
714     GifFile->Private = (VoidPtr) Private;
715     /* Private->FileHandle = FileHandle; */
716     Private->File = (FILE*)f;
717     Private->FileState = 0;   /* Make sure bit 0 = 0 (File open for read). */
718 
719     /* Let's see if this is a GIF file: */
720     if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) {
721 	_GifError = D_GIF_ERR_READ_FAILED;
722 	free((char *) Private);
723 	free((char *) GifFile);
724 	return NULL;
725     }
726 
727     /* The GIF Version number is ignored at this time. Maybe we should do    */
728     /* something more useful with it.					     */
729     Buf[GIF_STAMP_LEN] = 0;
730     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
731 	_GifError = D_GIF_ERR_NOT_GIF_FILE;
732 	free((char *) Private);
733 	free((char *) GifFile);
734 	return NULL;
735     }
736 
737     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
738 	free((char *) Private);
739 	free((char *) GifFile);
740 	return NULL;
741     }
742 
743     _GifError = 0;
744 
745     return GifFile;
746 }
747 
748 /******************************************************************************
749 *   This routine should be called before any other DGif calls. Note that      *
750 * this routine is called automatically from DGif file open routines.	      *
751 ******************************************************************************/
752 int CGIFFF DGifGetScreenDesc(CGIFFF GifFileType *GifFile)
753 {
754     int i, BitsPerPixel;
755     GifByteType Buf[3];
756     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
757 
758     if (!IS_READABLE(Private)) {
759 	/* This file was NOT open for reading: */
760 	_GifError = D_GIF_ERR_NOT_READABLE;
761 	return GIF_ERROR;
762     }
763 
764     /* Put the screen descriptor into the file: */
765     if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR ||
766 	DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR)
767 	return GIF_ERROR;
768 
769     if (fread(Buf, 1, 3, Private->File) != 3) {
770 	_GifError = D_GIF_ERR_READ_FAILED;
771 	return GIF_ERROR;
772     }
773     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
774     BitsPerPixel = (Buf[0] & 0x07) + 1;
775     GifFile->SBackGroundColor = Buf[1];
776     // fprintf(stderr, "colres=%d bpp=%d bgcol=%d\n", GifFile->SColorResolution, BitsPerPixel, GifFile->SBackGroundColor);
777     if (Buf[0] & 0x80) {		     /* Do we have global color map? */
778         // fprintf(stderr, "have gcolormap\n");
779 	GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
780 
781 	/* Get the global color map: */
782 	for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
783 	    if (fread(Buf, 1, 3, Private->File) != 3) {
784 		_GifError = D_GIF_ERR_READ_FAILED;
785 		return GIF_ERROR;
786 	    }
787 	    GifFile->SColorMap->Colors[i].Red = Buf[0];
788 	    GifFile->SColorMap->Colors[i].Green = Buf[1];
789 	    GifFile->SColorMap->Colors[i].Blue = Buf[2];
790 	}
791     }
792 
793     return GIF_OK;
794 }
795 
796 /******************************************************************************
797 *   This routine should be called before any attemp to read an image.         *
798 ******************************************************************************/
799 int CGIFFF DGifGetRecordType(CGIFFF GifFileType *GifFile, CGIFFF GifRecordType *Type)
800 {
801     GifByteType Buf;
802     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
803 
804     if (!IS_READABLE(Private)) {
805 	/* This file was NOT open for reading: */
806 	_GifError = D_GIF_ERR_NOT_READABLE;
807 	return GIF_ERROR;
808     }
809 
810     if (fread(&Buf, 1, 1, Private->File) != 1) {
811 	_GifError = D_GIF_ERR_READ_FAILED;
812 	return GIF_ERROR;
813     }
814 
815     // fprintf(stderr, "record %d at offset %ld\n", Buf&255, ftell(Private->File));
816     switch (Buf) {
817 	case ',': *Type = IMAGE_DESC_RECORD_TYPE; break;
818 	case '!': *Type = EXTENSION_RECORD_TYPE;  break;
819 	case ';': *Type = TERMINATE_RECORD_TYPE;  break;
820 	default:  *Type = UNDEFINED_RECORD_TYPE;
821 	    // fprintf(stderr, "wrong record %d at offset %ld\n", Buf&255, ftell(Private->File));
822 	    _GifError = D_GIF_ERR_WRONG_RECORD;
823 	    return GIF_ERROR;
824     }
825 
826     return GIF_OK;
827 }
828 
829 /******************************************************************************
830 *   This routine should be called before any attemp to read an image.         *
831 *   Note it is assumed the Image desc. header (',') has been read.	      *
832 ******************************************************************************/
833 int CGIFFF DGifGetImageDesc(CGIFFF GifFileType *GifFile)
834 {
835     int i, BitsPerPixel;
836     GifByteType Buf[3];
837     GifImageDesc Image;
838     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
839     memset(&Image, 0, sizeof(Image));
840 
841     if (!IS_READABLE(Private)) {
842 	/* This file was NOT open for reading: */
843 	_GifError = D_GIF_ERR_NOT_READABLE;
844 	return GIF_ERROR;
845     }
846 
847     if (DGifGetWord(Private->File, &Image.Left) == GIF_ERROR ||
848 	DGifGetWord(Private->File, &Image.Top) == GIF_ERROR ||
849 	DGifGetWord(Private->File, &Image.Width) == GIF_ERROR ||
850 	DGifGetWord(Private->File, &Image.Height) == GIF_ERROR)
851 	return GIF_ERROR;
852     if (fread(Buf, 1, 1, Private->File) != 1) {
853 	_GifError = D_GIF_ERR_READ_FAILED;
854 	return GIF_ERROR;
855     }
856     BitsPerPixel = (Buf[0] & 0x07) + 1;
857     Image.Interlace = (Buf[0] & 0x40);
858     if (Buf[0] & 0x80) {	    /* Does this image have local color map? */
859 
860 	if (Image.ColorMap && GifFile->SavedImages == NULL)
861 	    FreeMapObject(Image.ColorMap);
862 
863 	Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
864 
865 	/* Get the image local color map: */
866 	for (i = 0; i < Image.ColorMap->ColorCount; i++) {
867 	    if (fread(Buf, 1, 3, Private->File) != 3) {
868 		_GifError = D_GIF_ERR_READ_FAILED;
869 		return GIF_ERROR;
870 	    }
871 	    Image.ColorMap->Colors[i].Red = Buf[0];
872 	    Image.ColorMap->Colors[i].Green = Buf[1];
873 	    Image.ColorMap->Colors[i].Blue = Buf[2];
874 	}
875     }
876 
877     /**** pts ****/
878     if (NULL!=GifFile->SavedImages) {
879       GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
880 		    sizeof(SavedImage) * (GifFile->ImageCount + 1));
881     } else {
882       assert(GifFile->ImageCount==0);
883       GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
884     }
885     if (NULL==GifFile->SavedImages) {
886         _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
887         return GIF_ERROR;
888     }
889 
890     {
891 	SavedImage	*sp;
892 	sp = &GifFile->SavedImages[GifFile->ImageCount];
893 	memcpy(&sp->ImageDesc, &Image, sizeof(GifImageDesc));
894 	sp->RasterBits = (GifPixelType *)NULL;
895 	sp->ExtensionBlockCount = 0;
896 	sp->ExtensionBlocks = (ExtensionBlock *)NULL;
897         sp->delay=0;
898         sp->dispose=0;
899         sp->iter=1;
900         sp->transp=(-1);
901     }
902 
903     GifFile->ImageCount++;
904 
905     Private->PixelCount = (long) Image.Width *
906 			    (long) Image.Height;
907 
908     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
909 
910     return GIF_OK;
911 }
912 
913 /******************************************************************************
914 *  Get one full scanned line (Line) of length LineLen from GIF file.	      *
915 ******************************************************************************/
916 int CGIFFF DGifGetLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line, int LineLen)
917 {
918     GifByteType *Dummy;
919     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
920 
921     if (!IS_READABLE(Private)) {
922 	/* This file was NOT open for reading: */
923 	_GifError = D_GIF_ERR_NOT_READABLE;
924 	return GIF_ERROR;
925     }
926 
927     /**** pts ****/
928     /* if (!LineLen) LineLen = GifFile->Image.Width; */
929 
930 #if defined(__MSDOS__) || defined(__GNUC__)
931     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
932 #else
933     if ((Private->PixelCount -= LineLen) > 0xffff0000) {
934 #endif /* __MSDOS__ */
935 	_GifError = D_GIF_ERR_DATA_TOO_BIG;
936 	return GIF_ERROR;
937     }
938 
939     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
940 	if (Private->PixelCount == 0) {
941 	    /* We probably would not be called any more, so lets clean 	     */
942 	    /* everything before we return: need to flush out all rest of    */
943 	    /* image until empty block (size 0) detected. We use GetCodeNext.*/
944 	    do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
945 		return GIF_ERROR;
946 	    while (Dummy != NULL);
947 	}
948 	return GIF_OK;
949     }
950     else
951 	return GIF_ERROR;
952 }
953 
954 /******************************************************************************
955 * Put one pixel (Pixel) into GIF file.					      *
956 ******************************************************************************/
957 int CGIFFF DGifGetPixel(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType Pixel)
958 {
959     GifByteType *Dummy;
960     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
961 
962     if (!IS_READABLE(Private)) {
963 	/* This file was NOT open for reading: */
964 	_GifError = D_GIF_ERR_NOT_READABLE;
965 	return GIF_ERROR;
966     }
967 
968 #if defined(__MSDOS__) || defined(__GNUC__)
969     if (--Private->PixelCount > 0xffff0000UL)
970 #else
971     if (--Private->PixelCount > 0xffff0000)
972 #endif /* __MSDOS__ */
973     {
974 	_GifError = D_GIF_ERR_DATA_TOO_BIG;
975 	return GIF_ERROR;
976     }
977 
978     if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
979 	if (Private->PixelCount == 0) {
980 	    /* We probably would not be called any more, so lets clean 	     */
981 	    /* everything before we return: need to flush out all rest of    */
982 	    /* image until empty block (size 0) detected. We use GetCodeNext.*/
983 	    do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
984 		return GIF_ERROR;
985 	    while (Dummy != NULL);
986 	}
987 	return GIF_OK;
988     }
989     else
990 	return GIF_ERROR;
991 }
992 
993 /******************************************************************************
994 *   Get an extension block (see GIF manual) from gif file. This routine only  *
995 * returns the first data block, and DGifGetExtensionNext shouldbe called      *
996 * after this one until NULL extension is returned.			      *
997 *   The Extension should NOT be freed by the user (not dynamically allocated).*
998 *   Note it is assumed the Extension desc. header ('!') has been read.	      *
999 ******************************************************************************/
1000 int CGIFFF DGifGetExtension(CGIFFF GifFileType *GifFile, int *ExtCode,
1001 						    CGIFFF GifByteType **Extension)
1002 {
1003     GifByteType Buf;
1004     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1005 
1006 
1007     if (!IS_READABLE(Private)) {
1008 	/* This file was NOT open for reading: */
1009 	_GifError = D_GIF_ERR_NOT_READABLE;
1010 	return GIF_ERROR;
1011     }
1012 
1013     if (fread(&Buf, 1, 1, Private->File) != 1) {
1014 	_GifError = D_GIF_ERR_READ_FAILED;
1015 	return GIF_ERROR;
1016     }
1017     *ExtCode = Buf;
1018 
1019     return DGifGetExtensionNext(GifFile, Extension);
1020 }
1021 
1022 /******************************************************************************
1023 *   Get a following extension block (see GIF manual) from gif file. This      *
1024 * routine sould be called until NULL Extension is returned.		      *
1025 *   The Extension should NOT be freed by the user (not dynamically allocated).*
1026 ******************************************************************************/
1027 int CGIFFF DGifGetExtensionNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **Extension)
1028 {
1029     GifByteType Buf;
1030     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1031 
1032     if (fread(&Buf, 1, 1, Private->File) != 1) {
1033 	_GifError = D_GIF_ERR_READ_FAILED;
1034 	return GIF_ERROR;
1035     }
1036     if (Buf > 0) {
1037 	*Extension = Private->Buf;           /* Use private unused buffer. */
1038 	(*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
1039 	if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) {
1040 	    _GifError = D_GIF_ERR_READ_FAILED;
1041 	    return GIF_ERROR;
1042 	}
1043     }
1044     else
1045 	*Extension = NULL;
1046 
1047     return GIF_OK;
1048 }
1049 
1050 /******************************************************************************
1051 *   This routine should be called last, to close the GIF file.		      *
1052 ******************************************************************************/
1053 int CGIFFF DGifCloseFile(CGIFFF GifFileType *GifFile)
1054 {
1055     GifFilePrivateType *Private;
1056 
1057     if (GifFile == NULL) return GIF_ERROR;
1058 
1059     Private = (GifFilePrivateType *) GifFile->Private;
1060 
1061     if (!IS_READABLE(Private)) {
1062 	/* This file was NOT open for reading: */
1063 	_GifError = D_GIF_ERR_NOT_READABLE;
1064 	return GIF_ERROR;
1065     }
1066 
1067     #if 0 /**** pts ****/
1068     if (GifFile->Image.ColorMap)
1069 	FreeMapObject(GifFile->Image.ColorMap);
1070     #endif
1071     if (GifFile->SColorMap)
1072 	FreeMapObject(GifFile->SColorMap);
1073     if (Private)
1074 	free((char *) Private);
1075     if (GifFile->SavedImages)
1076 	FreeSavedImages(GifFile);
1077     free(GifFile);
1078 
1079 #if 0 /**** pts ****/
1080     if (fclose(File) != 0) {
1081 	_GifError = D_GIF_ERR_CLOSE_FAILED;
1082 	return GIF_ERROR;
1083     }
1084 #endif
1085     return GIF_OK;
1086 }
1087 
1088 /******************************************************************************
1089 *   Get 2 bytes (word) from the given file:				      *
1090 ******************************************************************************/
1091 static int DGifGetWord(FILE *File, int *Word)
1092 {
1093     unsigned char c[2];
1094 
1095     if (fread(c, 1, 2, File) != 2) {
1096 	CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
1097 	return GIF_ERROR;
1098     }
1099 
1100     *Word = (((unsigned int) c[1]) << 8) + c[0];
1101     return GIF_OK;
1102 }
1103 
1104 /******************************************************************************
1105 *   Get the image code in compressed form.  his routine can be called if the  *
1106 * information needed to be piped out as is. Obviously this is much faster     *
1107 * than decoding and encoding again. This routine should be followed by calls  *
1108 * to DGifGetCodeNext, until NULL block is returned.			      *
1109 *   The block should NOT be freed by the user (not dynamically allocated).    *
1110 ******************************************************************************/
1111 int CGIFFF DGifGetCode(CGIFFF GifFileType *GifFile, int *CodeSize, CGIFFF GifByteType **CodeBlock)
1112 {
1113     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1114 
1115     if (!IS_READABLE(Private)) {
1116 	/* This file was NOT open for reading: */
1117 	_GifError = D_GIF_ERR_NOT_READABLE;
1118 	return GIF_ERROR;
1119     }
1120 
1121     *CodeSize = Private->BitsPerPixel;
1122 
1123     return DGifGetCodeNext(GifFile, CodeBlock);
1124 }
1125 
1126 /******************************************************************************
1127 *   Continue to get the image code in compressed form. This routine should be *
1128 * called until NULL block is returned.					      *
1129 *   The block should NOT be freed by the user (not dynamically allocated).    *
1130 ******************************************************************************/
1131 int CGIFFF DGifGetCodeNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **CodeBlock)
1132 {
1133     GifByteType Buf;
1134     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1135 
1136     if (fread(&Buf, 1, 1, Private->File) != 1) {
1137 	_GifError = D_GIF_ERR_READ_FAILED;
1138 	return GIF_ERROR;
1139     }
1140 
1141     if (Buf > 0) {
1142 	*CodeBlock = Private->Buf;	       /* Use private unused buffer. */
1143 	(*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
1144 	if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) {
1145 	    _GifError = D_GIF_ERR_READ_FAILED;
1146 	    return GIF_ERROR;
1147 	}
1148     }
1149     else {
1150 	*CodeBlock = NULL;
1151 	Private->Buf[0] = 0;		   /* Make sure the buffer is empty! */
1152 	Private->PixelCount = 0;   /* And local info. indicate image read. */
1153     }
1154 
1155     return GIF_OK;
1156 }
1157 
1158 /******************************************************************************
1159 *   Setup the LZ decompression for this image:				      *
1160 ******************************************************************************/
1161 static int DGifSetupDecompress(CGIFFF GifFileType *GifFile)
1162 {
1163     int i, BitsPerPixel;
1164     CGIFFF GifByteType CodeSize;
1165     unsigned int *Prefix;
1166     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1167 
1168     if (fread(&CodeSize, 1, 1, Private->File) != 1)  /* Read Code size from file. */
1169       return GIF_ERROR;
1170     BitsPerPixel = CodeSize;
1171 
1172     Private->Buf[0] = 0;			      /* Input Buffer empty. */
1173     Private->BitsPerPixel = BitsPerPixel;
1174     Private->ClearCode = (1 << BitsPerPixel);
1175     Private->EOFCode = Private->ClearCode + 1;
1176     Private->RunningCode = Private->EOFCode + 1;
1177     Private->RunningBits = BitsPerPixel + 1;	 /* Number of bits per code. */
1178     Private->MaxCode1 = 1 << Private->RunningBits;     /* Max. code + 1. */
1179     Private->StackPtr = 0;		    /* No pixels on the pixel stack. */
1180     Private->LastCode = NO_SUCH_CODE;
1181     Private->CrntShiftState = 0;	/* No information in CrntShiftDWord. */
1182     Private->CrntShiftDWord = 0;
1183 
1184     Prefix = Private->Prefix;
1185     for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
1186 
1187     return GIF_OK;
1188 }
1189 
1190 /******************************************************************************
1191 *   The LZ decompression routine:					      *
1192 *   This version decompress the given gif file into Line of length LineLen.   *
1193 *   This routine can be called few times (one per scan line, for example), in *
1194 * order the complete the whole image.					      *
1195 ******************************************************************************/
1196 static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line,
1197 								int LineLen)
1198 {
1199     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
1200     CGIFFF GifByteType *Stack, *Suffix;
1201     unsigned int *Prefix;
1202     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1203 
1204     StackPtr = Private->StackPtr;
1205     Prefix = Private->Prefix;
1206     Suffix = Private->Suffix;
1207     Stack = Private->Stack;
1208     EOFCode = Private->EOFCode;
1209     ClearCode = Private->ClearCode;
1210     LastCode = Private->LastCode;
1211 
1212     if (StackPtr != 0) {
1213 	/* Let pop the stack off before continueing to read the gif file: */
1214 	while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
1215     }
1216 
1217     while (i < LineLen) {			    /* Decode LineLen items. */
1218 	if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR)
1219     	    return GIF_ERROR;
1220 
1221         /*fprintf(stderr,"CrntCode=0x%x\n",CrntCode);*/
1222 	if (CrntCode == EOFCode) {
1223 	    /* Note however that usually we will not be here as we will stop */
1224 	    /* decoding as soon as we got all the pixel, or EOF code will    */
1225 	    /* not be read at all, and DGifGetLine/Pixel clean everything.   */
1226 	    if (i != LineLen - 1 || Private->PixelCount != 0) {
1227 		CGIFFF _GifError = D_GIF_ERR_EOF_TOO_SOON;
1228 		return GIF_ERROR;
1229 	    }
1230 	    i++;
1231 	}
1232 	else if (CrntCode == ClearCode) {
1233 	    /* We need to start over again: */
1234 	    for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
1235 	    Private->RunningCode = Private->EOFCode + 1;
1236 	    Private->RunningBits = Private->BitsPerPixel + 1;
1237 	    Private->MaxCode1 = 1 << Private->RunningBits;
1238 	    LastCode = Private->LastCode = NO_SUCH_CODE;
1239 	}
1240 	else {
1241 	    /* Its regular code - if in pixel range simply add it to output  */
1242 	    /* stream, otherwise trace to codes linked list until the prefix */
1243 	    /* is in pixel range:					     */
1244 	    if (CrntCode < ClearCode) {
1245 		/* This is simple - its pixel scalar, so add it to output:   */
1246 		Line[i++] = CrntCode;
1247 	    }
1248 	    else {
1249 		/* Its a code to needed to be traced: trace the linked list  */
1250 		/* until the prefix is a pixel, while pushing the suffix     */
1251 		/* pixels on our stack. If we done, pop the stack in reverse */
1252 		/* (thats what stack is good for!) order to output.	     */
1253 		if (Prefix[CrntCode] == NO_SUCH_CODE) {
1254 		    /* Only allowed if CrntCode is exactly the running code: */
1255 		    /* In that case CrntCode = XXXCode, CrntCode or the	     */
1256 		    /* prefix code is last code and the suffix char is	     */
1257 		    /* exactly the prefix of last code!			     */
1258 		    if (CrntCode == Private->RunningCode - 2) {
1259 			CrntPrefix = LastCode;
1260 			Suffix[Private->RunningCode - 2] =
1261 			Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
1262 							LastCode, ClearCode);
1263 		    }
1264 		    else {
1265 			CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT;
1266 			return GIF_ERROR;
1267 		    }
1268 		}
1269 		else
1270 		    CrntPrefix = CrntCode;
1271 
1272 		/* Now (if image is O.K.) we should not get an NO_SUCH_CODE  */
1273 		/* During the trace. As we might loop forever, in case of    */
1274 		/* defective image, we count the number of loops we trace    */
1275 		/* and stop if we got LZ_MAX_CODE. obviously we can not      */
1276 		/* loop more than that.					     */
1277 		j = 0;
1278 		while (j++ <= LZ_MAX_CODE &&
1279 		       CrntPrefix > ClearCode &&
1280 		       CrntPrefix <= LZ_MAX_CODE) {
1281 		    Stack[StackPtr++] = Suffix[CrntPrefix];
1282 		    CrntPrefix = Prefix[CrntPrefix];
1283 		}
1284 		if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
1285 		    CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT;
1286 		    return GIF_ERROR;
1287 		}
1288 		/* Push the last character on stack: */
1289 		Stack[StackPtr++] = CrntPrefix;
1290 
1291 		/* Now lets pop all the stack into output: */
1292 		while (StackPtr != 0 && i < LineLen)
1293 		    Line[i++] = Stack[--StackPtr];
1294 	    }
1295 	    if (LastCode != NO_SUCH_CODE) {
1296 		Prefix[Private->RunningCode - 2] = LastCode;
1297 
1298 		if (CrntCode == Private->RunningCode - 2) {
1299 		    /* Only allowed if CrntCode is exactly the running code: */
1300 		    /* In that case CrntCode = XXXCode, CrntCode or the	     */
1301 		    /* prefix code is last code and the suffix char is	     */
1302 		    /* exactly the prefix of last code!			     */
1303 		    Suffix[Private->RunningCode - 2] =
1304 			DGifGetPrefixChar(Prefix, LastCode, ClearCode);
1305 		}
1306 		else {
1307 		    Suffix[Private->RunningCode - 2] =
1308 			DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
1309 		}
1310 	    }
1311 	    LastCode = CrntCode;
1312 	}
1313     }
1314 
1315     Private->LastCode = LastCode;
1316     Private->StackPtr = StackPtr;
1317 
1318     return GIF_OK;
1319 }
1320 
1321 /******************************************************************************
1322 * Routine to trace the Prefixes linked list until we get a prefix which is    *
1323 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
1324 * If image is defective, we might loop here forever, so we limit the loops to *
1325 * the maximum possible if image O.k. - LZ_MAX_CODE times.		      *
1326 ******************************************************************************/
1327 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
1328 {
1329     int i = 0;
1330 
1331     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
1332     return Code;
1333 }
1334 
1335 /******************************************************************************
1336 *   Interface for accessing the LZ codes directly. Set Code to the real code  *
1337 * (12bits), or to -1 if EOF code is returned.				      *
1338 ******************************************************************************/
1339 int CGIFFF DGifGetLZCodes(CGIFFF GifFileType *GifFile, int *Code)
1340 {
1341     GifByteType *CodeBlock;
1342     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1343 
1344     if (!IS_READABLE(Private)) {
1345 	/* This file was NOT open for reading: */
1346 	_GifError = D_GIF_ERR_NOT_READABLE;
1347 	return GIF_ERROR;
1348     }
1349 
1350     if (DGifDecompressInput(Private, Code) == GIF_ERROR)
1351 	return GIF_ERROR;
1352 
1353     if (*Code == Private->EOFCode) {
1354 	/* Skip rest of codes (hopefully only NULL terminating block): */
1355 	do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
1356     	    return GIF_ERROR;
1357 	while (CodeBlock != NULL);
1358 
1359 	*Code = -1;
1360     }
1361     else if (*Code == Private->ClearCode) {
1362 	/* We need to start over again: */
1363 	Private->RunningCode = Private->EOFCode + 1;
1364 	Private->RunningBits = Private->BitsPerPixel + 1;
1365 	Private->MaxCode1 = 1 << Private->RunningBits;
1366     }
1367 
1368     return GIF_OK;
1369 }
1370 
1371 /******************************************************************************
1372 *   The LZ decompression input routine:					      *
1373 *   This routine is responsable for the decompression of the bit stream from  *
1374 * 8 bits (bytes) packets, into the real codes.				      *
1375 *   Returns GIF_OK if read succesfully.					      *
1376 ******************************************************************************/
1377 static int DGifDecompressInput(GifFilePrivateType *Private, int *Code)
1378 {
1379     CGIFFF GifByteType NextByte;
1380     static unsigned int CodeMasks[] = {
1381 	0x0000, 0x0001, 0x0003, 0x0007,
1382 	0x000f, 0x001f, 0x003f, 0x007f,
1383 	0x00ff, 0x01ff, 0x03ff, 0x07ff,
1384 	0x0fff
1385     };
1386 
1387     while (Private->CrntShiftState < Private->RunningBits) {
1388 	/* Needs to get more bytes from input stream for next code: */
1389 	if (DGifBufferedInput(Private->File, Private->Buf, &NextByte)
1390 	    == GIF_ERROR) {
1391 	    return GIF_ERROR;
1392 	}
1393 	Private->CrntShiftDWord |=
1394 		((unsigned long) NextByte) << Private->CrntShiftState;
1395 	Private->CrntShiftState += 8;
1396     }
1397     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1398 
1399     Private->CrntShiftDWord >>= Private->RunningBits;
1400     Private->CrntShiftState -= Private->RunningBits;
1401 
1402     /* If code cannt fit into RunningBits bits, must raise its size. Note */
1403     /* however that codes above 4095 are used for special signaling.      */
1404     if (++Private->RunningCode > Private->MaxCode1 &&
1405 	Private->RunningBits < LZ_BITS) {
1406 	Private->MaxCode1 <<= 1;
1407 	Private->RunningBits++;
1408     }
1409     return GIF_OK;
1410 }
1411 
1412 /******************************************************************************
1413 *   This routines read one gif data block at a time and buffers it internally *
1414 * so that the decompression routine could access it.			      *
1415 *   The routine returns the next byte from its internal buffer (or read next  *
1416 * block in if buffer empty) and returns GIF_OK if succesful.		      *
1417 ******************************************************************************/
1418 static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf,
1419 						      CGIFFF GifByteType *NextByte)
1420 {
1421     if (Buf[0] == 0) {
1422 	/* Needs to read the next buffer - this one is empty: */
1423 	if (fread(Buf, 1, 1, File) != 1)
1424 	{
1425 	    CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
1426 	    return GIF_ERROR;
1427 	}
1428 	if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
1429 	{
1430 	    CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
1431 	    return GIF_ERROR;
1432 	}
1433 	*NextByte = Buf[1];
1434 	Buf[1] = 2;	   /* We use now the second place as last char read! */
1435 	Buf[0]--;
1436     }
1437     else {
1438 	*NextByte = Buf[Buf[1]++];
1439 	Buf[0]--;
1440     }
1441 
1442     return GIF_OK;
1443 }
1444 
1445 /******************************************************************************
1446 * This routine reads an entire GIF into core, hanging all its state info off  *
1447 * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()   *
1448 * first to initialize I/O.  Its inverse is EGifSpew().			      *
1449 ******************************************************************************/
1450 int CGIFFF DGifSlurp(CGIFFF GifFileType *GifFile)
1451 {
1452     static unsigned InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
1453                     InterlacedJumps[] = { 8, 8, 4, 2 };  /* be read - offsets and jumps... */
1454     /**** pts: unused vars ****/
1455     /* int i, j, Error, ImageSize; */
1456     int ext_code;
1457 
1458     GifRecordType RecordType;
1459     /**** pts ****/
1460     SavedImage *sp=0; /**** pts: avoid gcc warning */
1461     /** Extension info of next SavedImage */
1462     SavedImage ext;
1463     /** No-extension info */
1464     SavedImage noext;
1465 
1466     GifByteType *ExtData;
1467 
1468     /**** pts ****/
1469     memset(&noext, 0, sizeof(noext));
1470     noext.delay=0;
1471     noext.dispose=0;
1472     noext.iter=1;
1473     noext.transp=(-1);
1474     noext.ExtensionBlocks=NULL;
1475     noext.ExtensionBlockCount=0;
1476     ext=noext;
1477 
1478     /**** pts ****/
1479     GifFile->SavedImages=0;
1480 
1481     do {
1482 	if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1483 	    return(GIF_ERROR);
1484 
1485 	switch (RecordType) {
1486 	    case IMAGE_DESC_RECORD_TYPE:
1487 		if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1488 		    return(GIF_ERROR);
1489 
1490                 /**** pts: DGifGetImageDesc has already allocated the mem ****/
1491 		sp = &GifFile->SavedImages[GifFile->ImageCount-1];
1492 		/**** pts: apply extensions to the image just read */
1493 		ext.RasterBits=sp->RasterBits;
1494 		ext.ImageDesc=sp->ImageDesc;
1495 		*sp=ext;
1496 		ext=noext;
1497 
1498 		/**** pts ****/
1499 		sp->RasterBits = (GifPixelType*) malloc((0L+sp->ImageDesc.Width) * sp->ImageDesc.Height * sizeof(GifPixelType));
1500 		if (sp->RasterBits==NULL) { _GifError=D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; }
1501 		if (sp->ImageDesc.Interlace) {
1502 		  unsigned i, j, Height=sp->ImageDesc.Height, Width=sp->ImageDesc.Width;
1503 		  /* Need to perform 4 passes on the images: */
1504  		  for (i = 0; i < 4; i++)
1505 		    for (j = InterlacedOffset[i]; j < Height; j += InterlacedJumps[i])
1506 		      if (DGifGetLine(GifFile, sp->RasterBits+Width*j, Width) != GIF_OK) return GIF_ERROR;
1507 		} else {
1508 		  if (DGifGetLine(GifFile, sp->RasterBits, (0L+sp->ImageDesc.Width) * sp->ImageDesc.Height)
1509 		      == GIF_ERROR)
1510 		      return(GIF_ERROR);
1511 		}
1512 		break;
1513 
1514 	    case EXTENSION_RECORD_TYPE:
1515 
1516 		if (DGifGetExtension(GifFile,&ext_code,&ExtData)==GIF_ERROR)
1517 		    return(GIF_ERROR);
1518 		if (ExtData!=NULL) {
1519 		    #if 0 /**** pts ****/
1520 		      ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++];
1521 		      ep->ByteCount = ExtData[0];
1522 		      ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
1523 		      memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char));
1524 		    #else
1525                       /**** pts ****/
1526                       if (0xf9==(unsigned char)(ext_code)) {
1527                         assert(ExtData[0]>=4);
1528                         ext.dispose=ExtData[1]>>2;
1529                         ext.delay=(ExtData[3] << 8) | ExtData[2];
1530                         if ((ExtData[1] & 0x01) == 1) ext.transp=ExtData[4];
1531                       } else if (0xff==(unsigned char)(ext_code)) {
1532                         assert(ExtData[0]>=3);
1533                         ext.iter=(ExtData[3] << 8) | ExtData[2];
1534                       } else {
1535                         AddExtensionBlock(&ext, ExtData[0], ExtData+1);
1536                         ext.ExtensionBlocks[ext.ExtensionBlockCount-1].code=ext_code;
1537                       }
1538 		    #endif
1539 		    while (1) {
1540 		        if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1541 			  return(GIF_ERROR);
1542 		        #if 0 /**** pts ****/
1543   			  ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++];
1544   			  ep->ByteCount = ExtData[0];
1545   			  ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
1546   			  memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char));
1547   			#else
1548   			  if (ExtData==NULL) break;
1549   			  AddExtensionBlock(sp, ExtData[0], ExtData+1);
1550   			#endif
1551 		    }
1552 		}
1553 		break;
1554 
1555 	    case TERMINATE_RECORD_TYPE:
1556 		break;
1557 
1558 	    default:	/* Should be trapped by DGifGetRecordType */
1559 		break;
1560 	}
1561     }
1562     while
1563 	(RecordType != TERMINATE_RECORD_TYPE);
1564 
1565     return(GIF_OK);
1566 }
1567 
1568 /* __END__ */
1569