XEmacs 21.4.17 "Jumbo Shrimp".
[chise/xemacs-chise.git.1] / src / dgif_lib.c
1 /******************************************************************************
2 *   "Gif-Lib" - Yet another gif library.                                      *
3 *                                                                             *
4 * Written by:  Gershon Elber                    IBM PC Ver 1.1, Aug. 1990     *
5 *******************************************************************************
6 * The kernel of the GIF Decoding process can be found here.                   *
7 *******************************************************************************
8 * History:                                                                    *
9 * 16 Jun 89 - Version 1.0 by Gershon Elber.                                   *
10 *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
11 * 19 Feb 98 - Version 1.2 by Jareth Hein (Support for user specified I/O)     *
12 ******************************************************************************/
13
14 #include <config.h>
15 #include "lisp.h"
16
17 #include "sysfile.h"
18
19 #include "gifrlib.h"
20
21 #define PROGRAM_NAME    "GIFLIB"
22
23
24 static void DGifGetWord(GifFileType *GifFile, int *Word);
25 static void DGifSetupDecompress(GifFileType *GifFile);
26 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
27                                                                 int LineLen);
28 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
29 static void DGifDecompressInput(GifFileType *GifFile, int *Code);
30 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte);
31
32 /******************************************************************************
33 *   Open a new gif file for read, given by its name.                          *
34 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
35 * info record.                                                                *
36 ******************************************************************************/
37 void DGifOpenFileName(GifFileType *GifFile, const char *FileName)
38 {
39     FILE *f;
40
41     if ((f = fopen(FileName, 
42 #ifdef WIN32_NATIVE
43                              "rb"
44 #else
45                              "r"
46 #endif /* WIN32_NATIVE */
47                                              )) == NULL)
48         GifInternError(GifFile, D_GIF_ERR_OPEN_FAILED);
49
50     GifStdIOInit(GifFile, f, -1);
51     DGifInitRead(GifFile);
52 }
53
54 /******************************************************************************
55 *   Update a new gif file, given its file handle.                             *
56 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
57 * info record.                                                                *
58 ******************************************************************************/
59 void DGifOpenFileHandle(GifFileType *GifFile, int FileHandle)
60 {
61     FILE *f;
62
63 #ifdef WIN32_NATIVE
64     setmode(FileHandle, O_BINARY);        /* Make sure it is in binary mode. */
65     f = fdopen(FileHandle, "rb");                  /* Make it into a stream: */
66     setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
67 #else
68     f = fdopen(FileHandle, "r");                   /* Make it into a stream: */
69 #endif /* WIN32_NATIVE */
70
71     GifStdIOInit(GifFile, f, -1);
72     DGifInitRead(GifFile);
73 }
74
75 /******************************************************************************
76 *   Update a new gif file, given its file handle.                             *
77 *   Returns GifFileType pointer dynamically allocated which serves as the gif *
78 * info record. _GifError is cleared if succesfull.                            *
79 ******************************************************************************/
80 void DGifInitRead(GifFileType *GifFile)
81 {
82     GifByteType Buf[GIF_STAMP_LEN+1];
83     GifFilePrivateType *Private;
84
85     if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
86         == NULL) {
87         GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
88     }
89     memset(Private, '\0', sizeof(GifFilePrivateType));
90     GifFile->Private = (VoidPtr) Private;
91
92     Private->FileState = 0;   /* Make sure bit 0 = 0 (File open for read). */
93
94     /* Lets see if this is a GIF file: */
95     GifRead(Buf, GIF_STAMP_LEN, GifFile);
96
97     /* The GIF Version number is ignored at this time. Maybe we should do    */
98     /* something more useful with it.                                        */
99     Buf[GIF_STAMP_LEN] = 0;
100     if (strncmp(GIF_STAMP, (const char *) Buf, GIF_VERSION_POS) != 0) {
101         GifInternError(GifFile, D_GIF_ERR_NOT_GIF_FILE);
102       }
103
104     DGifGetScreenDesc(GifFile);
105 }
106
107 /******************************************************************************
108 *   This routine should be called before any other DGif calls. Note that      *
109 * this routine is called automatically from DGif file open routines.          *
110 ******************************************************************************/
111 void DGifGetScreenDesc(GifFileType *GifFile)
112 {
113     int i, BitsPerPixel;
114     GifByteType Buf[3];
115     GifFilePrivateType *Private = (GifFilePrivateType*) GifFile->Private;
116
117     if (!IS_READABLE(Private)) {
118         /* This file was NOT open for reading: */
119         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
120     }
121
122     /* Put the screen descriptor into the file: */
123     DGifGetWord(GifFile, &GifFile->SWidth);
124     DGifGetWord(GifFile, &GifFile->SHeight);
125
126     GifRead(Buf, 3, GifFile);
127     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
128     BitsPerPixel = (Buf[0] & 0x07) + 1;
129     GifFile->SBackGroundColor = Buf[1];
130     if (Buf[0] & 0x80) {                     /* Do we have global color map? */
131
132         GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
133
134         /* Get the global color map: */
135         for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
136             GifRead(Buf, 3, GifFile);
137             GifFile->SColorMap->Colors[i].Red = Buf[0];
138             GifFile->SColorMap->Colors[i].Green = Buf[1];
139             GifFile->SColorMap->Colors[i].Blue = Buf[2];
140         }
141     } else {
142         /* We should always have a colormap */
143         GifFile->SColorMap = MakeMapObject(2, NULL);
144         GifFile->SColorMap->Colors[0].Red = 0;
145         GifFile->SColorMap->Colors[0].Green = 0;
146         GifFile->SColorMap->Colors[0].Blue = 0;
147         GifFile->SColorMap->Colors[1].Red = 0xff;
148         GifFile->SColorMap->Colors[1].Green = 0xff;
149         GifFile->SColorMap->Colors[1].Blue = 0xff;
150     }
151 }
152
153 /******************************************************************************
154 *   This routine should be called before any attemp to read an image.         *
155 ******************************************************************************/
156 void DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
157 {
158     GifByteType Buf;
159     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
160     
161     if (!IS_READABLE(Private)) {
162         /* This file was NOT open for reading: */
163         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
164     }
165
166     GifRead(&Buf, 1, GifFile);
167
168     switch (Buf) {
169         case ',':
170             *Type = IMAGE_DESC_RECORD_TYPE;
171             break;
172         case '!':
173             *Type = EXTENSION_RECORD_TYPE;
174             break;
175         case ';':
176             *Type = TERMINATE_RECORD_TYPE;
177             break;
178         default:
179             *Type = UNDEFINED_RECORD_TYPE;
180             GifInternError(GifFile, D_GIF_ERR_WRONG_RECORD);
181     }
182 }
183
184 /******************************************************************************
185 *   This routine should be called before any attemp to read an image.         *
186 *   Note it is assumed the Image desc. header (',') has been read.            *
187 ******************************************************************************/
188 void DGifGetImageDesc(GifFileType *GifFile)
189 {
190     int i, BitsPerPixel;
191     GifByteType Buf[3];
192     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
193
194     if (!IS_READABLE(Private)) {
195         /* This file was NOT open for reading: */
196         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
197     }
198
199     DGifGetWord(GifFile, &GifFile->Image.Left);
200     DGifGetWord(GifFile, &GifFile->Image.Top);
201     DGifGetWord(GifFile, &GifFile->Image.Width);
202     DGifGetWord(GifFile, &GifFile->Image.Height);
203
204     GifRead(Buf, 1, GifFile);
205     BitsPerPixel = (Buf[0] & 0x07) + 1;
206     GifFile->Image.Interlace = (Buf[0] & 0x40);
207     if (Buf[0] & 0x80) {            /* Does this image have local color map? */
208
209         if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
210             FreeMapObject(GifFile->Image.ColorMap);
211
212         GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
213     
214         /* Get the image local color map: */
215         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
216             GifRead(Buf, 3, GifFile);
217             GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
218             GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
219             GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
220         }
221     }
222
223     if (GifFile->SavedImages) {
224         SavedImage      *sp;
225
226         if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
227                     sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) {
228             GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
229         }
230
231         sp = &GifFile->SavedImages[GifFile->ImageCount];
232         memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
233         if (GifFile->Image.ColorMap)
234           {
235             sp->ImageDesc.ColorMap =
236               MakeMapObject (GifFile->Image.ColorMap->ColorCount,
237                              GifFile->Image.ColorMap->Colors);
238           }
239         sp->RasterBits = NULL;
240         sp->ExtensionBlockCount = 0;
241         sp->ExtensionBlocks = (ExtensionBlock *)NULL;
242     }
243
244     GifFile->ImageCount++;
245
246     Private->PixelCount = (long) GifFile->Image.Width *
247                             (long) GifFile->Image.Height;
248
249     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
250 }
251
252 /******************************************************************************
253 *  Get one full scanned line (Line) of length LineLen from GIF file.          *
254 ******************************************************************************/
255 void DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
256 {
257     GifByteType *Dummy;
258     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
259
260     if (!IS_READABLE(Private)) {
261         /* This file was NOT open for reading: */
262         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
263     }
264
265     if (!LineLen) LineLen = GifFile->Image.Width;
266
267 #if defined(WIN32_NATIVE) || defined(__GNUC__)
268     if ((Private->PixelCount -= LineLen) > 0xffff0000UL)
269 #else
270     if ((Private->PixelCount -= LineLen) > 0xffff0000)
271 #endif /* WIN32_NATIVE */
272     {    
273         GifInternError(GifFile, D_GIF_ERR_DATA_TOO_BIG);
274     }
275
276     DGifDecompressLine(GifFile, Line, LineLen);
277     if (Private->PixelCount == 0) {
278         /* We probably would not be called any more, so lets clean           */
279         /* everything before we return: need to flush out all rest of    */
280         /* image until empty block (size 0) detected. We use GetCodeNext.*/
281         do
282             DGifGetCodeNext(GifFile, &Dummy);
283         while (Dummy != NULL);
284     }
285 }
286
287 /******************************************************************************
288 * Put one pixel (Pixel) into GIF file.                                        *
289 ******************************************************************************/
290 void DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
291 {
292     GifByteType *Dummy;
293     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
294
295     if (!IS_READABLE(Private)) {
296         /* This file was NOT open for reading: */
297         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
298     }
299
300 #if defined(WIN32_NATIVE) || defined(__GNUC__)
301     if (--Private->PixelCount > 0xffff0000UL)
302 #else
303     if (--Private->PixelCount > 0xffff0000)
304 #endif /* WIN32_NATIVE */
305     {
306         GifInternError(GifFile, D_GIF_ERR_DATA_TOO_BIG);
307     }
308
309     DGifDecompressLine(GifFile, &Pixel, 1);
310     if (Private->PixelCount == 0) {
311         /* We probably would not be called any more, so lets clean           */
312         /* everything before we return: need to flush out all rest of    */
313         /* image until empty block (size 0) detected. We use GetCodeNext.*/
314         do
315             DGifGetCodeNext(GifFile, &Dummy);
316         while (Dummy != NULL);
317     }
318 }
319
320 /******************************************************************************
321 *   Get an extension block (see GIF manual) from gif file. This routine only  *
322 * returns the first data block, and DGifGetExtensionNext shouldbe called      *
323 * after this one until NULL extension is returned.                            *
324 *   The Extension should NOT be freed by the user (not dynamically allocated).*
325 *   Note it is assumed the Extension desc. header ('!') has been read.        *
326 ******************************************************************************/
327 void DGifGetExtension(GifFileType *GifFile, int *ExtCode,
328                                                     GifByteType **Extension)
329 {
330     GifByteType Buf;
331     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
332
333     if (!IS_READABLE(Private)) {
334         /* This file was NOT open for reading: */
335         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
336     }
337
338     GifRead(&Buf, 1, GifFile);
339     *ExtCode = Buf;
340
341     DGifGetExtensionNext(GifFile, Extension);
342 }
343
344 /******************************************************************************
345 *   Get a following extension block (see GIF manual) from gif file. This      *
346 * routine sould be called until NULL Extension is returned.                   *
347 *   The Extension should NOT be freed by the user (not dynamically allocated).*
348 ******************************************************************************/
349 void DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
350 {
351     GifByteType Buf;
352     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
353
354     GifRead(&Buf, 1, GifFile);
355     if (Buf > 0) {
356         *Extension = Private->Buf;           /* Use private unused buffer. */
357         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
358         GifRead(&((*Extension)[1]), Buf, GifFile);
359     }
360     else
361         *Extension = NULL;
362 }
363
364 /******************************************************************************
365 *   This routine should be called second to last, to close the GIF file.      *
366 ******************************************************************************/
367 int DGifCloseFile(GifFileType *GifFile)
368 {
369     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
370
371     if (GifFile == NULL) return -1;
372
373     if (!IS_READABLE(Private))
374     {
375         /* This file was NOT open for reading: */
376         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
377     }
378
379     if (GifClose (GifFile))
380     {
381         GifInternError(GifFile, D_GIF_ERR_CLOSE_FAILED);
382     }
383     return 0;
384 }
385
386 /******************************************************************************
387 *   Get 2 bytes (word) from the given file:                                   *
388 ******************************************************************************/
389 static void DGifGetWord(GifFileType *GifFile, int *Word)
390 {
391     unsigned char c[2];
392
393     GifRead(c, 2, GifFile);
394
395     *Word = (((unsigned int) c[1]) << 8) + c[0];
396 }
397
398 /******************************************************************************
399 *   Get the image code in compressed form.  his routine can be called if the  *
400 * information needed to be piped out as is. Obviously this is much faster     *
401 * than decoding and encoding again. This routine should be followed by calls  *
402 * to DGifGetCodeNext, until NULL block is returned.                           *
403 *   The block should NOT be freed by the user (not dynamically allocated).    *
404 ******************************************************************************/
405 void DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
406 {
407     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
408
409     if (!IS_READABLE(Private)) {
410         /* This file was NOT open for reading: */
411         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
412     }
413
414     *CodeSize = Private->BitsPerPixel;
415
416     DGifGetCodeNext(GifFile, CodeBlock);
417 }
418
419 /******************************************************************************
420 *   Continue to get the image code in compressed form. This routine should be *
421 * called until NULL block is returned.                                        *
422 *   The block should NOT be freed by the user (not dynamically allocated).    *
423 ******************************************************************************/
424 void DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
425 {
426     GifByteType Buf;
427     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
428
429     GifRead(&Buf, 1, GifFile);
430
431     if (Buf > 0) {
432         *CodeBlock = Private->Buf;             /* Use private unused buffer. */
433         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
434         GifRead(&((*CodeBlock)[1]), Buf, GifFile);
435     }
436     else {
437         *CodeBlock = NULL;
438         Private->Buf[0] = 0;               /* Make sure the buffer is empty! */
439         Private->PixelCount = 0;   /* And local info. indicate image read. */
440     }
441
442 }
443
444 /******************************************************************************
445 *   Setup the LZ decompression for this image:                                *
446 ******************************************************************************/
447 static void DGifSetupDecompress(GifFileType *GifFile)
448 {
449     int i, BitsPerPixel;
450     GifByteType CodeSize;
451     unsigned int *Prefix;
452     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
453
454     GifRead(&CodeSize, 1, GifFile);    /* Read Code size from file. */
455     BitsPerPixel = CodeSize;
456
457     Private->Buf[0] = 0;                              /* Input Buffer empty. */
458     Private->BitsPerPixel = BitsPerPixel;
459     Private->ClearCode = (1 << BitsPerPixel);
460     Private->EOFCode = Private->ClearCode + 1;
461     Private->RunningCode = Private->EOFCode + 1;
462     Private->RunningBits = BitsPerPixel + 1;     /* Number of bits per code. */
463     Private->MaxCode1 = 1 << Private->RunningBits;     /* Max. code + 1. */
464     Private->StackPtr = 0;                  /* No pixels on the pixel stack. */
465     Private->LastCode = NO_SUCH_CODE;
466     Private->CrntShiftState = 0;        /* No information in CrntShiftDWord. */
467     Private->CrntShiftDWord = 0;
468
469     Prefix = Private->Prefix;
470     for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
471 }
472
473 /******************************************************************************
474 *   The LZ decompression routine:                                             *
475 *   This version decompress the given gif file into Line of length LineLen.   *
476 *   This routine can be called few times (one per scan line, for example), in *
477 * order the complete the whole image.                                         *
478 ******************************************************************************/
479 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
480                                                                 int LineLen)
481 {
482     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
483     GifByteType *Stack, *Suffix;
484     unsigned int *Prefix;
485     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
486
487     StackPtr = Private->StackPtr;
488     Prefix = Private->Prefix;
489     Suffix = Private->Suffix;
490     Stack = Private->Stack;
491     EOFCode = Private->EOFCode;
492     ClearCode = Private->ClearCode;
493     LastCode = Private->LastCode;
494
495     CrntPrefix = 0;
496     if (StackPtr != 0) {
497         /* Let pop the stack off before continueing to read the gif file: */
498         while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
499     }
500
501     while (i < LineLen) {                           /* Decode LineLen items. */
502         DGifDecompressInput(GifFile, &CrntCode);
503
504         if (CrntCode == EOFCode) {
505             /* Note however that usually we will not be here as we will stop */
506             /* decoding as soon as we got all the pixel, or EOF code will    */
507             /* not be read at all, and DGifGetLine/Pixel clean everything.   */
508             if (i != LineLen - 1 || Private->PixelCount != 0) {
509                 GifInternError(GifFile, D_GIF_ERR_EOF_TOO_SOON);
510             }
511             i++;
512         }
513         else if (CrntCode == ClearCode) {
514             /* We need to start over again: */
515             for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
516             Private->RunningCode = Private->EOFCode + 1;
517             Private->RunningBits = Private->BitsPerPixel + 1;
518             Private->MaxCode1 = 1 << Private->RunningBits;
519             LastCode = Private->LastCode = NO_SUCH_CODE;
520         }
521         else {
522             /* Its regular code - if in pixel range simply add it to output  */
523             /* stream, otherwise trace to codes linked list until the prefix */
524             /* is in pixel range:                                            */
525             if (CrntCode < ClearCode) {
526                 /* This is simple - its pixel scalar, so add it to output:   */
527                 Line[i++] = CrntCode;
528             }
529             else {
530                 /* Its a code to needed to be traced: trace the linked list  */
531                 /* until the prefix is a pixel, while pushing the suffix     */
532                 /* pixels on our stack. If we done, pop the stack in reverse */
533                 /* (thats what stack is good for!) order to output.          */
534                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
535                     /* Only allowed if CrntCode is exactly the running code: */
536                     /* In that case CrntCode = XXXCode, CrntCode or the      */
537                     /* prefix code is last code and the suffix char is       */
538                     /* exactly the prefix of last code!                      */
539                     if (CrntCode == Private->RunningCode - 2) {
540                         CrntPrefix = LastCode;
541                         Suffix[Private->RunningCode - 2] =
542                         Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
543                                                         LastCode, ClearCode);
544                     }
545                     else {
546                         GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
547                     }
548                 }
549                 else
550                     CrntPrefix = CrntCode;
551
552                 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE  */
553                 /* During the trace. As we might loop forever, in case of    */
554                 /* defective image, we count the number of loops we trace    */
555                 /* and stop if we got LZ_MAX_CODE. obviously we can not      */
556                 /* loop more than that.                                      */
557                 j = 0;
558                 while (j++ <= LZ_MAX_CODE &&
559                        CrntPrefix > ClearCode &&
560                        CrntPrefix <= LZ_MAX_CODE) {
561                     Stack[StackPtr++] = Suffix[CrntPrefix];
562                     CrntPrefix = Prefix[CrntPrefix];
563                 }
564                 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
565                     GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
566                 }
567                 /* Push the last character on stack: */
568                 Stack[StackPtr++] = CrntPrefix;
569
570                 /* Now lets pop all the stack into output: */
571                 while (StackPtr != 0 && i < LineLen)
572                     Line[i++] = Stack[--StackPtr];
573             }
574             if (LastCode != NO_SUCH_CODE) {
575                 Prefix[Private->RunningCode - 2] = LastCode;
576
577                 if (CrntCode == Private->RunningCode - 2) {
578                     /* Only allowed if CrntCode is exactly the running code: */
579                     /* In that case CrntCode = XXXCode, CrntCode or the      */
580                     /* prefix code is last code and the suffix char is       */
581                     /* exactly the prefix of last code!                      */
582                     Suffix[Private->RunningCode - 2] =
583                         DGifGetPrefixChar(Prefix, LastCode, ClearCode);
584                 }
585                 else {
586                     Suffix[Private->RunningCode - 2] =
587                         DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
588                 }
589             }
590             LastCode = CrntCode;
591         }
592     }
593
594     Private->LastCode = LastCode;
595     Private->StackPtr = StackPtr;
596 }
597
598 /******************************************************************************
599 * Routine to trace the Prefixes linked list until we get a prefix which is    *
600 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
601 * If image is defective, we might loop here forever, so we limit the loops to *
602 * the maximum possible if image O.k. - LZ_MAX_CODE times.                     *
603 ******************************************************************************/
604 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
605 {
606     int i = 0;
607
608     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
609     return Code;
610 }
611
612 /******************************************************************************
613 *   Interface for accessing the LZ codes directly. Set Code to the real code  *
614 * (12bits), or to -1 if EOF code is returned.                                 *
615 ******************************************************************************/
616 void DGifGetLZCodes(GifFileType *GifFile, int *Code)
617 {
618     GifByteType *CodeBlock;
619     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
620
621     if (!IS_READABLE(Private)) {
622         /* This file was NOT open for reading: */
623         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
624     }
625
626     DGifDecompressInput(GifFile, Code);
627
628     if (*Code == Private->EOFCode) {
629         /* Skip rest of codes (hopefully only NULL terminating block): */
630         do
631             DGifGetCodeNext(GifFile, &CodeBlock);
632         while (CodeBlock != NULL);
633
634         *Code = -1;
635     }
636     else if (*Code == Private->ClearCode) {
637         /* We need to start over again: */
638         Private->RunningCode = Private->EOFCode + 1;
639         Private->RunningBits = Private->BitsPerPixel + 1;
640         Private->MaxCode1 = 1 << Private->RunningBits;
641     }
642 }
643
644 /******************************************************************************
645 *   The LZ decompression input routine:                                       *
646 *   This routine is responsable for the decompression of the bit stream from  *
647 * 8 bits (bytes) packets, into the real codes.                                *
648 *   Returns GIF_OK if read succesfully.                                       *
649 ******************************************************************************/
650 static void DGifDecompressInput(GifFileType *GifFile, int *Code)
651 {
652     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
653     GifByteType NextByte;
654     static unsigned int CodeMasks[] = {
655         0x0000, 0x0001, 0x0003, 0x0007,
656         0x000f, 0x001f, 0x003f, 0x007f,
657         0x00ff, 0x01ff, 0x03ff, 0x07ff,
658         0x0fff
659     };
660
661     while (Private->CrntShiftState < Private->RunningBits) {
662         /* Needs to get more bytes from input stream for next code: */
663         DGifBufferedInput(GifFile, &NextByte);
664         Private->CrntShiftDWord |=
665                 ((unsigned long) NextByte) << Private->CrntShiftState;
666         Private->CrntShiftState += 8;
667     }
668     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
669
670     Private->CrntShiftDWord >>= Private->RunningBits;
671     Private->CrntShiftState -= Private->RunningBits;
672
673     /* If code cannt fit into RunningBits bits, must raise its size. Note */
674     /* however that codes above 4095 are used for special signaling.      */
675     if (++Private->RunningCode > Private->MaxCode1 &&
676         Private->RunningBits < LZ_BITS) {
677         Private->MaxCode1 <<= 1;
678         Private->RunningBits++;
679     }
680 }
681
682 /******************************************************************************
683 *   This routines read one gif data block at a time and buffers it internally *
684 * so that the decompression routine could access it.                          *
685 *   The routine returns the next byte from its internal buffer (or read next  *
686 * block in if buffer empty)                                                   *
687 ******************************************************************************/
688 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte)
689 {
690     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
691     GifByteType *Buf = Private->Buf;
692
693     if (Buf[0] == 0) {
694         /* Needs to read the next buffer - this one is empty: */
695         GifRead(Buf, 1, GifFile);
696         GifRead((Buf + 1), Buf[0], GifFile);
697         *NextByte = Buf[1];
698         Buf[1] = 2;        /* We use now the second place as last char read! */
699         Buf[0]--;
700     }
701     else {
702         *NextByte = Buf[Buf[1]++];
703         Buf[0]--;
704     }
705 }
706
707 /******************************************************************************
708 * This routine reads an entire GIF into core, hanging all its state info off  *
709 * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()   *
710 * first to initialize I/O.  Its inverse is EGifSpew().                        *
711 ******************************************************************************/
712 void DGifSlurp(GifFileType *GifFile)
713 {
714     int ImageSize;
715     GifRecordType RecordType;
716     SavedImage *sp;
717     GifByteType *ExtData;
718
719     /* Some versions of malloc dislike 0-length requests */
720     GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
721     memset(GifFile->SavedImages, 0, sizeof(SavedImage));
722     sp = &GifFile->SavedImages[0];
723
724     do {
725         DGifGetRecordType(GifFile, &RecordType);
726
727         switch (RecordType) {
728             case IMAGE_DESC_RECORD_TYPE:
729                 DGifGetImageDesc(GifFile);
730
731                 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
732                 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
733
734                 sp->RasterBits
735                     = (GifPixelType*) malloc (ImageSize * sizeof(GifPixelType));
736
737                 DGifGetLine(GifFile, sp->RasterBits, ImageSize);
738                 break;
739
740             case EXTENSION_RECORD_TYPE:
741                 DGifGetExtension(GifFile,&sp->Function,&ExtData);
742                 
743                 while (ExtData != NULL) {
744                     if (AddExtensionBlock(sp, ExtData[0], ExtData+1) == GIF_ERROR)
745                         GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
746                     DGifGetExtensionNext(GifFile, &ExtData);
747                 }
748                 break;
749
750             case TERMINATE_RECORD_TYPE:
751                 break;
752
753             default:    /* Should be trapped by DGifGetRecordType */
754                 break;
755         }
756     } while (RecordType != TERMINATE_RECORD_TYPE);
757 }
758
759 /******************************************************************************
760 * Extension record functions                                                  *
761 ******************************************************************************/
762
763 void MakeExtension(SavedImage *New, int Function)
764 {
765     New->Function = Function;
766     /*
767      * Someday we might have to deal with multiple extensions.
768      */
769 }
770
771 int AddExtensionBlock(SavedImage *New, int Len, GifByteType *data)
772 {
773     int size;
774     ExtensionBlock *ep;
775
776     if (New->ExtensionBlocks == NULL)
777         New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
778     else
779         New->ExtensionBlocks =
780             (ExtensionBlock *)realloc(New->ExtensionBlocks,
781                       sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
782
783     if (New->ExtensionBlocks == NULL)
784         return(GIF_ERROR);
785
786     ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
787     ep->ByteCount = Len;
788     size = Len * sizeof(GifByteType);
789     ep->Bytes = (GifByteType *)malloc(size);
790     memcpy(ep->Bytes, data, size);
791     return(GIF_OK);
792 }
793
794 void FreeExtension(SavedImage *Image)
795 {
796     ExtensionBlock      *ep;
797
798     for (ep = Image->ExtensionBlocks;
799          ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
800          ep++)
801         (void) free((char *)ep->Bytes);
802     free((char *)Image->ExtensionBlocks);
803     Image->ExtensionBlocks = NULL;
804 }
805
806 /******************************************************************************
807 * Image block allocation functions                                            *
808 ******************************************************************************/
809 SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom)
810 /*
811  * Append an image block to the SavedImages array  
812  */
813 {
814     SavedImage  *sp;
815
816     if (GifFile->SavedImages == NULL)
817         GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
818     else
819         GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
820                                 sizeof(SavedImage) * (GifFile->ImageCount+1));
821
822     if (GifFile->SavedImages == NULL)
823         return((SavedImage *)NULL);
824     else
825     {
826         sp = &GifFile->SavedImages[GifFile->ImageCount++];
827         memset((char *)sp, '\0', sizeof(SavedImage));
828
829         if (CopyFrom)
830         {
831             memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
832
833             /*
834              * Make our own allocated copies of the heap fields in the
835              * copied record.  This guards against potential aliasing
836              * problems.
837              */
838
839             /* first, the local color map */
840             if (sp->ImageDesc.ColorMap)
841                 sp->ImageDesc.ColorMap =
842                     MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
843                                   CopyFrom->ImageDesc.ColorMap->Colors);
844
845             /* next, the raster */
846             sp->RasterBits = (GifPixelType *) malloc(sizeof(GifPixelType)
847                                 * CopyFrom->ImageDesc.Height
848                                 * CopyFrom->ImageDesc.Width);
849             memcpy(sp->RasterBits,
850                    CopyFrom->RasterBits,
851                    sizeof(GifPixelType)
852                         * CopyFrom->ImageDesc.Height
853                         * CopyFrom->ImageDesc.Width);
854
855             /* finally, the extension blocks */
856             if (sp->ExtensionBlocks)
857             {
858                 sp->ExtensionBlocks
859                     = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
860                                               * CopyFrom->ExtensionBlockCount);
861                 memcpy(sp->ExtensionBlocks,
862                    CopyFrom->ExtensionBlocks,
863                    sizeof(ExtensionBlock)
864                         * CopyFrom->ExtensionBlockCount);
865
866                 /*
867                  * For the moment, the actual blocks can take their
868                  * chances with free().  We'll fix this later. 
869                  */
870             }
871         }
872
873         return(sp);
874     }
875 }
876
877 void FreeSavedImages(GifFileType *GifFile)
878 {
879     SavedImage  *sp;
880
881     for (sp = GifFile->SavedImages;
882          sp < GifFile->SavedImages + GifFile->ImageCount;
883          sp++)
884     {
885         if (sp->ImageDesc.ColorMap)
886             FreeMapObject(sp->ImageDesc.ColorMap);
887
888         if (sp->RasterBits)
889             free((char *)sp->RasterBits);
890
891         if (sp->ExtensionBlocks)
892             FreeExtension(sp);
893     }
894     free((char *) GifFile->SavedImages);
895 }
896
897 /******************************************************************************
898 * Miscellaneous utility functions                                             *
899 ******************************************************************************/
900
901 static int BitSize(int n)
902 /* return smallest bitfield size n will fit in */
903 {
904     register    int i;
905
906     for (i = 1; i <= 8; i++)
907         if ((1 << i) >= n)
908             break;
909     return(i);
910 }
911
912 /******************************************************************************
913 * Color map object functions                                                  *
914 ******************************************************************************/
915
916 ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
917 /*
918  * Allocate a color map of given size; initialize with contents of
919  * ColorMap if that pointer is non-NULL.
920  */
921 {
922     ColorMapObject *Object;
923
924     if (ColorCount != (1 << BitSize(ColorCount)))
925         return((ColorMapObject *)NULL);
926
927     Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
928     if (Object == (ColorMapObject *)NULL)
929         return((ColorMapObject *)NULL);
930
931     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
932     if (Object->Colors == (GifColorType *)NULL)
933         return((ColorMapObject *)NULL);
934
935     Object->ColorCount = ColorCount;
936     Object->BitsPerPixel = BitSize(ColorCount);
937
938     if (ColorMap)
939         memcpy((char *)Object->Colors,
940                (char *)ColorMap, ColorCount * sizeof(GifColorType));
941
942     return(Object);
943 }
944
945 void FreeMapObject(ColorMapObject *Object)
946 /*
947  * Free a color map object
948  */
949 {
950     free(Object->Colors);
951     free(Object);
952 }