(U-0002195D): Add `ideographic-structure'; add `sound@ja/on'; add
[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;
370
371     if (GifFile == NULL) return -1;
372
373     Private = (GifFilePrivateType *)GifFile->Private;
374     if (!IS_READABLE(Private))
375     {
376         /* This file was NOT open for reading: */
377         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
378     }
379
380     if (GifClose (GifFile))
381     {
382         GifInternError(GifFile, D_GIF_ERR_CLOSE_FAILED);
383     }
384     return 0;
385 }
386
387 /******************************************************************************
388 *   Get 2 bytes (word) from the given file:                                   *
389 ******************************************************************************/
390 static void DGifGetWord(GifFileType *GifFile, int *Word)
391 {
392     unsigned char c[2];
393
394     GifRead(c, 2, GifFile);
395
396     *Word = (((unsigned int) c[1]) << 8) + c[0];
397 }
398
399 /******************************************************************************
400 *   Get the image code in compressed form.  his routine can be called if the  *
401 * information needed to be piped out as is. Obviously this is much faster     *
402 * than decoding and encoding again. This routine should be followed by calls  *
403 * to DGifGetCodeNext, until NULL block is returned.                           *
404 *   The block should NOT be freed by the user (not dynamically allocated).    *
405 ******************************************************************************/
406 void DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
407 {
408     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
409
410     if (!IS_READABLE(Private)) {
411         /* This file was NOT open for reading: */
412         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
413     }
414
415     *CodeSize = Private->BitsPerPixel;
416
417     DGifGetCodeNext(GifFile, CodeBlock);
418 }
419
420 /******************************************************************************
421 *   Continue to get the image code in compressed form. This routine should be *
422 * called until NULL block is returned.                                        *
423 *   The block should NOT be freed by the user (not dynamically allocated).    *
424 ******************************************************************************/
425 void DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
426 {
427     GifByteType Buf;
428     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
429
430     GifRead(&Buf, 1, GifFile);
431
432     if (Buf > 0) {
433         *CodeBlock = Private->Buf;             /* Use private unused buffer. */
434         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
435         GifRead(&((*CodeBlock)[1]), Buf, GifFile);
436     }
437     else {
438         *CodeBlock = NULL;
439         Private->Buf[0] = 0;               /* Make sure the buffer is empty! */
440         Private->PixelCount = 0;   /* And local info. indicate image read. */
441     }
442
443 }
444
445 /******************************************************************************
446 *   Setup the LZ decompression for this image:                                *
447 ******************************************************************************/
448 static void DGifSetupDecompress(GifFileType *GifFile)
449 {
450     int i, BitsPerPixel;
451     GifByteType CodeSize;
452     unsigned int *Prefix;
453     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
454
455     GifRead(&CodeSize, 1, GifFile);    /* Read Code size from file. */
456     BitsPerPixel = CodeSize;
457
458     Private->Buf[0] = 0;                              /* Input Buffer empty. */
459     Private->BitsPerPixel = BitsPerPixel;
460     Private->ClearCode = (1 << BitsPerPixel);
461     Private->EOFCode = Private->ClearCode + 1;
462     Private->RunningCode = Private->EOFCode + 1;
463     Private->RunningBits = BitsPerPixel + 1;     /* Number of bits per code. */
464     Private->MaxCode1 = 1 << Private->RunningBits;     /* Max. code + 1. */
465     Private->StackPtr = 0;                  /* No pixels on the pixel stack. */
466     Private->LastCode = NO_SUCH_CODE;
467     Private->CrntShiftState = 0;        /* No information in CrntShiftDWord. */
468     Private->CrntShiftDWord = 0;
469
470     Prefix = Private->Prefix;
471     for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
472 }
473
474 /******************************************************************************
475 *   The LZ decompression routine:                                             *
476 *   This version decompress the given gif file into Line of length LineLen.   *
477 *   This routine can be called few times (one per scan line, for example), in *
478 * order the complete the whole image.                                         *
479 ******************************************************************************/
480 static void DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
481                                                                 int LineLen)
482 {
483     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
484     GifByteType *Stack, *Suffix;
485     unsigned int *Prefix;
486     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
487
488     StackPtr = Private->StackPtr;
489     Prefix = Private->Prefix;
490     Suffix = Private->Suffix;
491     Stack = Private->Stack;
492     EOFCode = Private->EOFCode;
493     ClearCode = Private->ClearCode;
494     LastCode = Private->LastCode;
495
496     CrntPrefix = 0;
497     if (StackPtr != 0) {
498         /* Let pop the stack off before continueing to read the gif file: */
499         while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
500     }
501
502     while (i < LineLen) {                           /* Decode LineLen items. */
503         DGifDecompressInput(GifFile, &CrntCode);
504
505         if (CrntCode == EOFCode) {
506             /* Note however that usually we will not be here as we will stop */
507             /* decoding as soon as we got all the pixel, or EOF code will    */
508             /* not be read at all, and DGifGetLine/Pixel clean everything.   */
509             if (i != LineLen - 1 || Private->PixelCount != 0) {
510                 GifInternError(GifFile, D_GIF_ERR_EOF_TOO_SOON);
511             }
512             i++;
513         }
514         else if (CrntCode == ClearCode) {
515             /* We need to start over again: */
516             for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
517             Private->RunningCode = Private->EOFCode + 1;
518             Private->RunningBits = Private->BitsPerPixel + 1;
519             Private->MaxCode1 = 1 << Private->RunningBits;
520             LastCode = Private->LastCode = NO_SUCH_CODE;
521         }
522         else {
523             /* Its regular code - if in pixel range simply add it to output  */
524             /* stream, otherwise trace to codes linked list until the prefix */
525             /* is in pixel range:                                            */
526             if (CrntCode < ClearCode) {
527                 /* This is simple - its pixel scalar, so add it to output:   */
528                 Line[i++] = CrntCode;
529             }
530             else {
531                 /* Its a code to needed to be traced: trace the linked list  */
532                 /* until the prefix is a pixel, while pushing the suffix     */
533                 /* pixels on our stack. If we done, pop the stack in reverse */
534                 /* (thats what stack is good for!) order to output.          */
535                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
536                     /* Only allowed if CrntCode is exactly the running code: */
537                     /* In that case CrntCode = XXXCode, CrntCode or the      */
538                     /* prefix code is last code and the suffix char is       */
539                     /* exactly the prefix of last code!                      */
540                     if (CrntCode == Private->RunningCode - 2) {
541                         CrntPrefix = LastCode;
542                         Suffix[Private->RunningCode - 2] =
543                         Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
544                                                         LastCode, ClearCode);
545                     }
546                     else {
547                         GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
548                     }
549                 }
550                 else
551                     CrntPrefix = CrntCode;
552
553                 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE  */
554                 /* During the trace. As we might loop forever, in case of    */
555                 /* defective image, we count the number of loops we trace    */
556                 /* and stop if we got LZ_MAX_CODE. obviously we can not      */
557                 /* loop more than that.                                      */
558                 j = 0;
559                 while (j++ <= LZ_MAX_CODE &&
560                        CrntPrefix > ClearCode &&
561                        CrntPrefix <= LZ_MAX_CODE) {
562                     Stack[StackPtr++] = Suffix[CrntPrefix];
563                     CrntPrefix = Prefix[CrntPrefix];
564                 }
565                 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
566                     GifInternError(GifFile, D_GIF_ERR_IMAGE_DEFECT);
567                 }
568                 /* Push the last character on stack: */
569                 Stack[StackPtr++] = CrntPrefix;
570
571                 /* Now lets pop all the stack into output: */
572                 while (StackPtr != 0 && i < LineLen)
573                     Line[i++] = Stack[--StackPtr];
574             }
575             if (LastCode != NO_SUCH_CODE) {
576                 Prefix[Private->RunningCode - 2] = LastCode;
577
578                 if (CrntCode == Private->RunningCode - 2) {
579                     /* Only allowed if CrntCode is exactly the running code: */
580                     /* In that case CrntCode = XXXCode, CrntCode or the      */
581                     /* prefix code is last code and the suffix char is       */
582                     /* exactly the prefix of last code!                      */
583                     Suffix[Private->RunningCode - 2] =
584                         DGifGetPrefixChar(Prefix, LastCode, ClearCode);
585                 }
586                 else {
587                     Suffix[Private->RunningCode - 2] =
588                         DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
589                 }
590             }
591             LastCode = CrntCode;
592         }
593     }
594
595     Private->LastCode = LastCode;
596     Private->StackPtr = StackPtr;
597 }
598
599 /******************************************************************************
600 * Routine to trace the Prefixes linked list until we get a prefix which is    *
601 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
602 * If image is defective, we might loop here forever, so we limit the loops to *
603 * the maximum possible if image O.k. - LZ_MAX_CODE times.                     *
604 ******************************************************************************/
605 static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
606 {
607     int i = 0;
608
609     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
610     return Code;
611 }
612
613 /******************************************************************************
614 *   Interface for accessing the LZ codes directly. Set Code to the real code  *
615 * (12bits), or to -1 if EOF code is returned.                                 *
616 ******************************************************************************/
617 void DGifGetLZCodes(GifFileType *GifFile, int *Code)
618 {
619     GifByteType *CodeBlock;
620     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
621
622     if (!IS_READABLE(Private)) {
623         /* This file was NOT open for reading: */
624         GifInternError(GifFile, D_GIF_ERR_NOT_READABLE);
625     }
626
627     DGifDecompressInput(GifFile, Code);
628
629     if (*Code == Private->EOFCode) {
630         /* Skip rest of codes (hopefully only NULL terminating block): */
631         do
632             DGifGetCodeNext(GifFile, &CodeBlock);
633         while (CodeBlock != NULL);
634
635         *Code = -1;
636     }
637     else if (*Code == Private->ClearCode) {
638         /* We need to start over again: */
639         Private->RunningCode = Private->EOFCode + 1;
640         Private->RunningBits = Private->BitsPerPixel + 1;
641         Private->MaxCode1 = 1 << Private->RunningBits;
642     }
643 }
644
645 /******************************************************************************
646 *   The LZ decompression input routine:                                       *
647 *   This routine is responsable for the decompression of the bit stream from  *
648 * 8 bits (bytes) packets, into the real codes.                                *
649 *   Returns GIF_OK if read succesfully.                                       *
650 ******************************************************************************/
651 static void DGifDecompressInput(GifFileType *GifFile, int *Code)
652 {
653     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
654     GifByteType NextByte;
655     static unsigned int CodeMasks[] = {
656         0x0000, 0x0001, 0x0003, 0x0007,
657         0x000f, 0x001f, 0x003f, 0x007f,
658         0x00ff, 0x01ff, 0x03ff, 0x07ff,
659         0x0fff
660     };
661
662     while (Private->CrntShiftState < Private->RunningBits) {
663         /* Needs to get more bytes from input stream for next code: */
664         DGifBufferedInput(GifFile, &NextByte);
665         Private->CrntShiftDWord |=
666                 ((unsigned long) NextByte) << Private->CrntShiftState;
667         Private->CrntShiftState += 8;
668     }
669     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
670
671     Private->CrntShiftDWord >>= Private->RunningBits;
672     Private->CrntShiftState -= Private->RunningBits;
673
674     /* If code cannt fit into RunningBits bits, must raise its size. Note */
675     /* however that codes above 4095 are used for special signaling.      */
676     if (++Private->RunningCode > Private->MaxCode1 &&
677         Private->RunningBits < LZ_BITS) {
678         Private->MaxCode1 <<= 1;
679         Private->RunningBits++;
680     }
681 }
682
683 /******************************************************************************
684 *   This routines read one gif data block at a time and buffers it internally *
685 * so that the decompression routine could access it.                          *
686 *   The routine returns the next byte from its internal buffer (or read next  *
687 * block in if buffer empty)                                                   *
688 ******************************************************************************/
689 static void DGifBufferedInput(GifFileType *GifFile, GifByteType *NextByte)
690 {
691     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
692     GifByteType *Buf = Private->Buf;
693
694     if (Buf[0] == 0) {
695         /* Needs to read the next buffer - this one is empty: */
696         GifRead(Buf, 1, GifFile);
697         GifRead((Buf + 1), Buf[0], GifFile);
698         *NextByte = Buf[1];
699         Buf[1] = 2;        /* We use now the second place as last char read! */
700         Buf[0]--;
701     }
702     else {
703         *NextByte = Buf[Buf[1]++];
704         Buf[0]--;
705     }
706 }
707
708 /******************************************************************************
709 * This routine reads an entire GIF into core, hanging all its state info off  *
710 * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()   *
711 * first to initialize I/O.  Its inverse is EGifSpew().                        *
712 ******************************************************************************/
713 void DGifSlurp(GifFileType *GifFile)
714 {
715     int ImageSize;
716     GifRecordType RecordType;
717     SavedImage *sp;
718     GifByteType *ExtData;
719
720     /* Some versions of malloc dislike 0-length requests */
721     GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
722     memset(GifFile->SavedImages, 0, sizeof(SavedImage));
723     sp = &GifFile->SavedImages[0];
724
725     do {
726         DGifGetRecordType(GifFile, &RecordType);
727
728         switch (RecordType) {
729             case IMAGE_DESC_RECORD_TYPE:
730                 DGifGetImageDesc(GifFile);
731
732                 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
733                 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
734
735                 sp->RasterBits
736                     = (GifPixelType*) malloc (ImageSize * sizeof(GifPixelType));
737
738                 DGifGetLine(GifFile, sp->RasterBits, ImageSize);
739                 break;
740
741             case EXTENSION_RECORD_TYPE:
742                 DGifGetExtension(GifFile,&sp->Function,&ExtData);
743                 
744                 while (ExtData != NULL) {
745                     if (AddExtensionBlock(sp, ExtData[0], ExtData+1) == GIF_ERROR)
746                         GifInternError(GifFile, D_GIF_ERR_NOT_ENOUGH_MEM);
747                     DGifGetExtensionNext(GifFile, &ExtData);
748                 }
749                 break;
750
751             case TERMINATE_RECORD_TYPE:
752                 break;
753
754             default:    /* Should be trapped by DGifGetRecordType */
755                 break;
756         }
757     } while (RecordType != TERMINATE_RECORD_TYPE);
758 }
759
760 /******************************************************************************
761 * Extension record functions                                                  *
762 ******************************************************************************/
763
764 void MakeExtension(SavedImage *New, int Function)
765 {
766     New->Function = Function;
767     /*
768      * Someday we might have to deal with multiple extensions.
769      */
770 }
771
772 int AddExtensionBlock(SavedImage *New, int Len, GifByteType *data)
773 {
774     int size;
775     ExtensionBlock *ep;
776
777     if (New->ExtensionBlocks == NULL)
778         New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
779     else
780         New->ExtensionBlocks =
781             (ExtensionBlock *)realloc(New->ExtensionBlocks,
782                       sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
783
784     if (New->ExtensionBlocks == NULL)
785         return(GIF_ERROR);
786
787     ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
788     ep->ByteCount = Len;
789     size = Len * sizeof(GifByteType);
790     ep->Bytes = (GifByteType *)malloc(size);
791     memcpy(ep->Bytes, data, size);
792     return(GIF_OK);
793 }
794
795 void FreeExtension(SavedImage *Image)
796 {
797     ExtensionBlock      *ep;
798
799     for (ep = Image->ExtensionBlocks;
800          ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
801          ep++)
802         (void) free((char *)ep->Bytes);
803     free((char *)Image->ExtensionBlocks);
804     Image->ExtensionBlocks = NULL;
805 }
806
807 /******************************************************************************
808 * Image block allocation functions                                            *
809 ******************************************************************************/
810 SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom)
811 /*
812  * Append an image block to the SavedImages array  
813  */
814 {
815     SavedImage  *sp;
816
817     if (GifFile->SavedImages == NULL)
818         GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
819     else
820         GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
821                                 sizeof(SavedImage) * (GifFile->ImageCount+1));
822
823     if (GifFile->SavedImages == NULL)
824         return((SavedImage *)NULL);
825     else
826     {
827         sp = &GifFile->SavedImages[GifFile->ImageCount++];
828         memset((char *)sp, '\0', sizeof(SavedImage));
829
830         if (CopyFrom)
831         {
832             memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
833
834             /*
835              * Make our own allocated copies of the heap fields in the
836              * copied record.  This guards against potential aliasing
837              * problems.
838              */
839
840             /* first, the local color map */
841             if (sp->ImageDesc.ColorMap)
842                 sp->ImageDesc.ColorMap =
843                     MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
844                                   CopyFrom->ImageDesc.ColorMap->Colors);
845
846             /* next, the raster */
847             sp->RasterBits = (GifPixelType *) malloc(sizeof(GifPixelType)
848                                 * CopyFrom->ImageDesc.Height
849                                 * CopyFrom->ImageDesc.Width);
850             memcpy(sp->RasterBits,
851                    CopyFrom->RasterBits,
852                    sizeof(GifPixelType)
853                         * CopyFrom->ImageDesc.Height
854                         * CopyFrom->ImageDesc.Width);
855
856             /* finally, the extension blocks */
857             if (sp->ExtensionBlocks)
858             {
859                 sp->ExtensionBlocks
860                     = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
861                                               * CopyFrom->ExtensionBlockCount);
862                 memcpy(sp->ExtensionBlocks,
863                    CopyFrom->ExtensionBlocks,
864                    sizeof(ExtensionBlock)
865                         * CopyFrom->ExtensionBlockCount);
866
867                 /*
868                  * For the moment, the actual blocks can take their
869                  * chances with free().  We'll fix this later. 
870                  */
871             }
872         }
873
874         return(sp);
875     }
876 }
877
878 void FreeSavedImages(GifFileType *GifFile)
879 {
880     SavedImage  *sp;
881
882     for (sp = GifFile->SavedImages;
883          sp < GifFile->SavedImages + GifFile->ImageCount;
884          sp++)
885     {
886         if (sp->ImageDesc.ColorMap)
887             FreeMapObject(sp->ImageDesc.ColorMap);
888
889         if (sp->RasterBits)
890             free((char *)sp->RasterBits);
891
892         if (sp->ExtensionBlocks)
893             FreeExtension(sp);
894     }
895     free((char *) GifFile->SavedImages);
896 }
897
898 /******************************************************************************
899 * Miscellaneous utility functions                                             *
900 ******************************************************************************/
901
902 static int BitSize(int n)
903 /* return smallest bitfield size n will fit in */
904 {
905     register    int i;
906
907     for (i = 1; i <= 8; i++)
908         if ((1 << i) >= n)
909             break;
910     return(i);
911 }
912
913 /******************************************************************************
914 * Color map object functions                                                  *
915 ******************************************************************************/
916
917 ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
918 /*
919  * Allocate a color map of given size; initialize with contents of
920  * ColorMap if that pointer is non-NULL.
921  */
922 {
923     ColorMapObject *Object;
924
925     if (ColorCount != (1 << BitSize(ColorCount)))
926         return((ColorMapObject *)NULL);
927
928     Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
929     if (Object == (ColorMapObject *)NULL)
930         return((ColorMapObject *)NULL);
931
932     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
933     if (Object->Colors == (GifColorType *)NULL)
934       {
935         free (Object);
936         return((ColorMapObject *)NULL);
937       }
938
939     Object->ColorCount = ColorCount;
940     Object->BitsPerPixel = BitSize(ColorCount);
941
942     if (ColorMap)
943         memcpy((char *)Object->Colors,
944                (char *)ColorMap, ColorCount * sizeof(GifColorType));
945
946     return(Object);
947 }
948
949 void FreeMapObject(ColorMapObject *Object)
950 /*
951  * Free a color map object
952  */
953 {
954     free(Object->Colors);
955     free(Object);
956 }