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