• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *****************************************************************************/
12 
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16 
17 #include <stdlib.h>
18 #if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__)
19 #include <io.h>
20 #include <alloc.h>
21 #include <sys\stat.h>
22 #else
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #endif /* __MSDOS__ */
26 
27 #ifdef HAVE_IO_H
28 #include <io.h>
29 #endif
30 
31 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif /* HAVE_FCNTL_H */
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif /* HAVE_UNISTD_H */
37 #include <stdio.h>
38 #include <string.h>
39 #include "gif_lib.h"
40 #include "gif_lib_private.h"
41 
42 #define COMMENT_EXT_FUNC_CODE 0xfe  /* Extension function code for
43                                        comment. */
44 
45 /* avoid extra function call in case we use fread (TVT) */
46 #define READ(_gif,_buf,_len)                                     \
47   (((GifFilePrivateType*)_gif->Private)->Read ?                   \
48     ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
49     fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
50 
51 static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
52 static int DGifSetupDecompress(GifFileType *GifFile);
53 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
54                               int LineLen);
55 static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
56 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
57 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
58                              GifByteType *NextByte);
59 #ifndef _GBA_NO_FILEIO
60 
61 /******************************************************************************
62  * Open a new gif file for read, given by its name.
63  * Returns GifFileType pointer dynamically allocated which serves as the gif
64  * info record. _GifError is cleared if succesfull.
65  *****************************************************************************/
66 GifFileType *
DGifOpenFileName(const char * FileName)67 DGifOpenFileName(const char *FileName) {
68     int FileHandle;
69     GifFileType *GifFile;
70 
71     if ((FileHandle = open(FileName, O_RDONLY
72 #if defined(__MSDOS__) || defined(WINDOWS32) || defined(_OPEN_BINARY)
73                            | O_BINARY
74 #endif /* __MSDOS__ || _OPEN_BINARY */
75          )) == -1) {
76         _GifError = D_GIF_ERR_OPEN_FAILED;
77         return NULL;
78     }
79 
80     GifFile = DGifOpenFileHandle(FileHandle);
81     return GifFile;
82 }
83 
84 /******************************************************************************
85  * Update a new gif file, given its file handle.
86  * Returns GifFileType pointer dynamically allocated which serves as the gif
87  * info record. _GifError is cleared if succesfull.
88  *****************************************************************************/
89 GifFileType *
DGifOpenFileHandle(int FileHandle)90 DGifOpenFileHandle(int FileHandle) {
91 
92     unsigned char Buf[GIF_STAMP_LEN + 1];
93     GifFileType *GifFile;
94     GifFilePrivateType *Private;
95     FILE *f;
96 
97     GifFile = (GifFileType *)malloc(sizeof(GifFileType));
98     if (GifFile == NULL) {
99         _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
100         close(FileHandle);
101         return NULL;
102     }
103 
104     memset(GifFile, '\0', sizeof(GifFileType));
105 
106     Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
107     if (Private == NULL) {
108         _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
109         close(FileHandle);
110         free((char *)GifFile);
111         return NULL;
112     }
113 #if defined(__MSDOS__) || defined(WINDOWS32) || defined(_OPEN_BINARY)
114     setmode(FileHandle, O_BINARY);    /* Make sure it is in binary mode. */
115 #endif /* __MSDOS__ */
116 
117     f = fdopen(FileHandle, "rb");    /* Make it into a stream: */
118 
119 #if defined(__MSDOS__) || defined(WINDOWS32)
120     setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);    /* And inc. stream
121                                                           buffer. */
122 #endif /* __MSDOS__ */
123 
124     GifFile->Private = (VoidPtr)Private;
125     Private->FileHandle = FileHandle;
126     Private->File = f;
127     Private->FileState = FILE_STATE_READ;
128     Private->Read = 0;    /* don't use alternate input method (TVT) */
129     GifFile->UserData = 0;    /* TVT */
130 
131     /* Lets see if this is a GIF file: */
132     if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
133         _GifError = D_GIF_ERR_READ_FAILED;
134         fclose(f);
135         free((char *)Private);
136         free((char *)GifFile);
137         return NULL;
138     }
139 
140     /* The GIF Version number is ignored at this time. Maybe we should do
141      * something more useful with it.  */
142     Buf[GIF_STAMP_LEN] = 0;
143     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
144         _GifError = D_GIF_ERR_NOT_GIF_FILE;
145         fclose(f);
146         free((char *)Private);
147         free((char *)GifFile);
148         return NULL;
149     }
150 
151     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
152         fclose(f);
153         free((char *)Private);
154         free((char *)GifFile);
155         return NULL;
156     }
157 
158     _GifError = 0;
159 
160     return GifFile;
161 }
162 
163 #endif /* _GBA_NO_FILEIO */
164 
165 /******************************************************************************
166  * GifFileType constructor with user supplied input function (TVT)
167  *****************************************************************************/
168 GifFileType *
DGifOpen(void * userData,InputFunc readFunc)169 DGifOpen(void *userData,
170          InputFunc readFunc) {
171 
172     unsigned char Buf[GIF_STAMP_LEN + 1];
173     GifFileType *GifFile;
174     GifFilePrivateType *Private;
175 
176     GifFile = (GifFileType *)malloc(sizeof(GifFileType));
177     if (GifFile == NULL) {
178         _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
179         return NULL;
180     }
181 
182     memset(GifFile, '\0', sizeof(GifFileType));
183 
184     Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
185     if (!Private) {
186         _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
187         free((char *)GifFile);
188         return NULL;
189     }
190 
191     GifFile->Private = (VoidPtr)Private;
192     Private->FileHandle = 0;
193     Private->File = 0;
194     Private->FileState = FILE_STATE_READ;
195 
196     Private->Read = readFunc;    /* TVT */
197     GifFile->UserData = userData;    /* TVT */
198 
199     /* Lets see if this is a GIF file: */
200     if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
201         _GifError = D_GIF_ERR_READ_FAILED;
202         free((char *)Private);
203         free((char *)GifFile);
204         return NULL;
205     }
206 
207     /* The GIF Version number is ignored at this time. Maybe we should do
208      * something more useful with it. */
209     Buf[GIF_STAMP_LEN] = 0;
210     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
211         _GifError = D_GIF_ERR_NOT_GIF_FILE;
212         free((char *)Private);
213         free((char *)GifFile);
214         return NULL;
215     }
216 
217     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
218         free((char *)Private);
219         free((char *)GifFile);
220         return NULL;
221     }
222 
223     _GifError = 0;
224 
225     return GifFile;
226 }
227 
228 /******************************************************************************
229  * This routine should be called before any other DGif calls. Note that
230  * this routine is called automatically from DGif file open routines.
231  *****************************************************************************/
232 int
DGifGetScreenDesc(GifFileType * GifFile)233 DGifGetScreenDesc(GifFileType * GifFile) {
234 
235     int i, BitsPerPixel;
236     GifByteType Buf[3];
237     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
238 
239     if (!IS_READABLE(Private)) {
240         /* This file was NOT open for reading: */
241         _GifError = D_GIF_ERR_NOT_READABLE;
242         return GIF_ERROR;
243     }
244 
245     /* Put the screen descriptor into the file: */
246     if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
247         DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
248         return GIF_ERROR;
249 
250     if (READ(GifFile, Buf, 3) != 3) {
251         _GifError = D_GIF_ERR_READ_FAILED;
252         return GIF_ERROR;
253     }
254     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
255     BitsPerPixel = (Buf[0] & 0x07) + 1;
256     GifFile->SBackGroundColor = Buf[1];
257     if (Buf[0] & 0x80) {    /* Do we have global color map? */
258 
259         GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
260         if (GifFile->SColorMap == NULL) {
261             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
262             return GIF_ERROR;
263         }
264 
265         /* Get the global color map: */
266         for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
267             if (READ(GifFile, Buf, 3) != 3) {
268                 FreeMapObject(GifFile->SColorMap);
269                 GifFile->SColorMap = NULL;
270                 _GifError = D_GIF_ERR_READ_FAILED;
271                 return GIF_ERROR;
272             }
273             GifFile->SColorMap->Colors[i].Red = Buf[0];
274             GifFile->SColorMap->Colors[i].Green = Buf[1];
275             GifFile->SColorMap->Colors[i].Blue = Buf[2];
276         }
277     } else {
278         GifFile->SColorMap = NULL;
279     }
280 
281     return GIF_OK;
282 }
283 
284 /******************************************************************************
285  * This routine should be called before any attempt to read an image.
286  *****************************************************************************/
287 int
DGifGetRecordType(GifFileType * GifFile,GifRecordType * Type)288 DGifGetRecordType(GifFileType * GifFile,
289                   GifRecordType * Type) {
290 
291     GifByteType Buf;
292     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
293 
294     if (!IS_READABLE(Private)) {
295         /* This file was NOT open for reading: */
296         _GifError = D_GIF_ERR_NOT_READABLE;
297         return GIF_ERROR;
298     }
299 
300     if (READ(GifFile, &Buf, 1) != 1) {
301         _GifError = D_GIF_ERR_READ_FAILED;
302         return GIF_ERROR;
303     }
304 
305     switch (Buf) {
306       case ',':
307           *Type = IMAGE_DESC_RECORD_TYPE;
308           break;
309       case '!':
310           *Type = EXTENSION_RECORD_TYPE;
311           break;
312       case ';':
313           *Type = TERMINATE_RECORD_TYPE;
314           break;
315       default:
316           *Type = UNDEFINED_RECORD_TYPE;
317           _GifError = D_GIF_ERR_WRONG_RECORD;
318           return GIF_ERROR;
319     }
320 
321     return GIF_OK;
322 }
323 
324 /******************************************************************************
325  * This routine should be called before any attempt to read an image.
326  * Note it is assumed the Image desc. header (',') has been read.
327  *****************************************************************************/
328 int
DGifGetImageDesc(GifFileType * GifFile)329 DGifGetImageDesc(GifFileType * GifFile) {
330 
331     int i, BitsPerPixel;
332     GifByteType Buf[3];
333     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
334     SavedImage *sp;
335 
336     if (!IS_READABLE(Private)) {
337         /* This file was NOT open for reading: */
338         _GifError = D_GIF_ERR_NOT_READABLE;
339         return GIF_ERROR;
340     }
341 
342     if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
343         DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
344         DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
345         DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
346         return GIF_ERROR;
347     if (READ(GifFile, Buf, 1) != 1) {
348         _GifError = D_GIF_ERR_READ_FAILED;
349         return GIF_ERROR;
350     }
351     BitsPerPixel = (Buf[0] & 0x07) + 1;
352     GifFile->Image.Interlace = (Buf[0] & 0x40);
353     if (Buf[0] & 0x80) {    /* Does this image have local color map? */
354 
355         /*** FIXME: Why do we check both of these in order to do this?
356          * Why do we have both Image and SavedImages? */
357         if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
358             FreeMapObject(GifFile->Image.ColorMap);
359 
360         GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
361         if (GifFile->Image.ColorMap == NULL) {
362             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
363             return GIF_ERROR;
364         }
365 
366         /* Get the image local color map: */
367         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
368             if (READ(GifFile, Buf, 3) != 3) {
369                 FreeMapObject(GifFile->Image.ColorMap);
370                 _GifError = D_GIF_ERR_READ_FAILED;
371                 GifFile->Image.ColorMap = NULL;
372                 return GIF_ERROR;
373             }
374             GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
375             GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
376             GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
377         }
378     } else if (GifFile->Image.ColorMap) {
379         FreeMapObject(GifFile->Image.ColorMap);
380         GifFile->Image.ColorMap = NULL;
381     }
382 
383     if (GifFile->SavedImages) {
384         if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
385                                       sizeof(SavedImage) *
386                                       (GifFile->ImageCount + 1))) == NULL) {
387             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
388             return GIF_ERROR;
389         }
390     } else {
391         if ((GifFile->SavedImages =
392              (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
393             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
394             return GIF_ERROR;
395         }
396     }
397 
398     sp = &GifFile->SavedImages[GifFile->ImageCount];
399     memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
400     if (GifFile->Image.ColorMap != NULL) {
401         sp->ImageDesc.ColorMap = MakeMapObject(
402                                  GifFile->Image.ColorMap->ColorCount,
403                                  GifFile->Image.ColorMap->Colors);
404         if (sp->ImageDesc.ColorMap == NULL) {
405             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
406             return GIF_ERROR;
407         }
408     }
409     sp->RasterBits = (unsigned char *)NULL;
410     sp->ExtensionBlockCount = 0;
411     sp->ExtensionBlocks = (ExtensionBlock *) NULL;
412 
413     GifFile->ImageCount++;
414 
415     Private->PixelCount = (long)GifFile->Image.Width *
416        (long)GifFile->Image.Height;
417 
418     DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
419 
420     return GIF_OK;
421 }
422 
423 /******************************************************************************
424  * Get one full scanned line (Line) of length LineLen from GIF file.
425  *****************************************************************************/
426 int
DGifGetLine(GifFileType * GifFile,GifPixelType * Line,int LineLen)427 DGifGetLine(GifFileType * GifFile,
428             GifPixelType * Line,
429             int LineLen) {
430 
431     GifByteType *Dummy;
432     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
433 
434     if (!IS_READABLE(Private)) {
435         /* This file was NOT open for reading: */
436         _GifError = D_GIF_ERR_NOT_READABLE;
437         return GIF_ERROR;
438     }
439 
440     if (!LineLen)
441         LineLen = GifFile->Image.Width;
442 
443 #if defined(__MSDOS__) || defined(WINDOWS32) || defined(__GNUC__)
444     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
445 #else
446     if ((Private->PixelCount -= LineLen) > 0xffff0000) {
447 #endif /* __MSDOS__ */
448         _GifError = D_GIF_ERR_DATA_TOO_BIG;
449         return GIF_ERROR;
450     }
451 
452     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
453         if (Private->PixelCount == 0) {
454             /* We probably would not be called any more, so lets clean
455              * everything before we return: need to flush out all rest of
456              * image until empty block (size 0) detected. We use GetCodeNext. */
457             do
458                 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
459                     return GIF_ERROR;
460             while (Dummy != NULL) ;
461         }
462         return GIF_OK;
463     } else
464         return GIF_ERROR;
465 }
466 
467 /******************************************************************************
468  * Put one pixel (Pixel) into GIF file.
469  *****************************************************************************/
470 int
471 DGifGetPixel(GifFileType * GifFile,
472              GifPixelType Pixel) {
473 
474     GifByteType *Dummy;
475     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
476 
477     if (!IS_READABLE(Private)) {
478         /* This file was NOT open for reading: */
479         _GifError = D_GIF_ERR_NOT_READABLE;
480         return GIF_ERROR;
481     }
482 #if defined(__MSDOS__) || defined(WINDOWS32) || defined(__GNUC__)
483     if (--Private->PixelCount > 0xffff0000UL)
484 #else
485     if (--Private->PixelCount > 0xffff0000)
486 #endif /* __MSDOS__ */
487     {
488         _GifError = D_GIF_ERR_DATA_TOO_BIG;
489         return GIF_ERROR;
490     }
491 
492     if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
493         if (Private->PixelCount == 0) {
494             /* We probably would not be called any more, so lets clean
495              * everything before we return: need to flush out all rest of
496              * image until empty block (size 0) detected. We use GetCodeNext. */
497             do
498                 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
499                     return GIF_ERROR;
500             while (Dummy != NULL) ;
501         }
502         return GIF_OK;
503     } else
504         return GIF_ERROR;
505 }
506 
507 /******************************************************************************
508  * Get an extension block (see GIF manual) from gif file. This routine only
509  * returns the first data block, and DGifGetExtensionNext should be called
510  * after this one until NULL extension is returned.
511  * The Extension should NOT be freed by the user (not dynamically allocated).
512  * Note it is assumed the Extension desc. header ('!') has been read.
513  *****************************************************************************/
514 int
515 DGifGetExtension(GifFileType * GifFile,
516                  int *ExtCode,
517                  GifByteType ** Extension) {
518 
519     GifByteType Buf;
520     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
521 
522     if (!IS_READABLE(Private)) {
523         /* This file was NOT open for reading: */
524         _GifError = D_GIF_ERR_NOT_READABLE;
525         return GIF_ERROR;
526     }
527 
528     if (READ(GifFile, &Buf, 1) != 1) {
529         _GifError = D_GIF_ERR_READ_FAILED;
530         return GIF_ERROR;
531     }
532     *ExtCode = Buf;
533 
534     return DGifGetExtensionNext(GifFile, Extension);
535 }
536 
537 /******************************************************************************
538  * Get a following extension block (see GIF manual) from gif file. This
539  * routine should be called until NULL Extension is returned.
540  * The Extension should NOT be freed by the user (not dynamically allocated).
541  *****************************************************************************/
542 int
543 DGifGetExtensionNext(GifFileType * GifFile,
544                      GifByteType ** Extension) {
545 
546     GifByteType Buf;
547     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
548 
549     if (READ(GifFile, &Buf, 1) != 1) {
550         _GifError = D_GIF_ERR_READ_FAILED;
551         return GIF_ERROR;
552     }
553     if (Buf > 0) {
554         *Extension = Private->Buf;    /* Use private unused buffer. */
555         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
556         if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
557             _GifError = D_GIF_ERR_READ_FAILED;
558             return GIF_ERROR;
559         }
560     } else
561         *Extension = NULL;
562 
563     return GIF_OK;
564 }
565 
566 /******************************************************************************
567  * This routine should be called last, to close the GIF file.
568  *****************************************************************************/
569 int
570 DGifCloseFile(GifFileType * GifFile) {
571 
572     GifFilePrivateType *Private;
573     FILE *File;
574 
575     if (GifFile == NULL)
576         return GIF_ERROR;
577 
578     Private = (GifFilePrivateType *) GifFile->Private;
579 
580     if (!IS_READABLE(Private)) {
581         /* This file was NOT open for reading: */
582         _GifError = D_GIF_ERR_NOT_READABLE;
583         return GIF_ERROR;
584     }
585 
586     File = Private->File;
587 
588     if (GifFile->Image.ColorMap) {
589         FreeMapObject(GifFile->Image.ColorMap);
590         GifFile->Image.ColorMap = NULL;
591     }
592 
593     if (GifFile->SColorMap) {
594         FreeMapObject(GifFile->SColorMap);
595         GifFile->SColorMap = NULL;
596     }
597 
598     if (Private) {
599         free((char *)Private);
600         Private = NULL;
601     }
602 
603     if (GifFile->SavedImages) {
604         FreeSavedImages(GifFile);
605         GifFile->SavedImages = NULL;
606     }
607 
608     free(GifFile);
609 
610     if (File && (fclose(File) != 0)) {
611         _GifError = D_GIF_ERR_CLOSE_FAILED;
612         return GIF_ERROR;
613     }
614     return GIF_OK;
615 }
616 
617 /******************************************************************************
618  * Get 2 bytes (word) from the given file:
619  *****************************************************************************/
620 static int
621 DGifGetWord(GifFileType * GifFile,
622             GifWord *Word) {
623 
624     unsigned char c[2];
625 
626     if (READ(GifFile, c, 2) != 2) {
627         _GifError = D_GIF_ERR_READ_FAILED;
628         return GIF_ERROR;
629     }
630 
631     *Word = (((unsigned int)c[1]) << 8) + c[0];
632     return GIF_OK;
633 }
634 
635 /******************************************************************************
636  * Get the image code in compressed form.  This routine can be called if the
637  * information needed to be piped out as is. Obviously this is much faster
638  * than decoding and encoding again. This routine should be followed by calls
639  * to DGifGetCodeNext, until NULL block is returned.
640  * The block should NOT be freed by the user (not dynamically allocated).
641  *****************************************************************************/
642 int
643 DGifGetCode(GifFileType * GifFile,
644             int *CodeSize,
645             GifByteType ** CodeBlock) {
646 
647     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
648 
649     if (!IS_READABLE(Private)) {
650         /* This file was NOT open for reading: */
651         _GifError = D_GIF_ERR_NOT_READABLE;
652         return GIF_ERROR;
653     }
654 
655     *CodeSize = Private->BitsPerPixel;
656 
657     return DGifGetCodeNext(GifFile, CodeBlock);
658 }
659 
660 /******************************************************************************
661  * Continue to get the image code in compressed form. This routine should be
662  * called until NULL block is returned.
663  * The block should NOT be freed by the user (not dynamically allocated).
664  *****************************************************************************/
665 int
666 DGifGetCodeNext(GifFileType * GifFile,
667                 GifByteType ** CodeBlock) {
668 
669     GifByteType Buf;
670     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
671 
672     if (READ(GifFile, &Buf, 1) != 1) {
673         _GifError = D_GIF_ERR_READ_FAILED;
674         return GIF_ERROR;
675     }
676 
677     if (Buf > 0) {
678         *CodeBlock = Private->Buf;    /* Use private unused buffer. */
679         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
680         if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
681             _GifError = D_GIF_ERR_READ_FAILED;
682             return GIF_ERROR;
683         }
684     } else {
685         *CodeBlock = NULL;
686         Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
687         Private->PixelCount = 0;    /* And local info. indicate image read. */
688     }
689 
690     return GIF_OK;
691 }
692 
693 /******************************************************************************
694  * Setup the LZ decompression for this image:
695  *****************************************************************************/
696 static int
697 DGifSetupDecompress(GifFileType * GifFile) {
698 
699     int i, BitsPerPixel;
700     GifByteType CodeSize;
701     GifPrefixType *Prefix;
702     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
703 
704     READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
705     BitsPerPixel = CodeSize;
706 
707     Private->Buf[0] = 0;    /* Input Buffer empty. */
708     Private->BitsPerPixel = BitsPerPixel;
709     Private->ClearCode = (1 << BitsPerPixel);
710     Private->EOFCode = Private->ClearCode + 1;
711     Private->RunningCode = Private->EOFCode + 1;
712     Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
713     Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
714     Private->StackPtr = 0;    /* No pixels on the pixel stack. */
715     Private->LastCode = NO_SUCH_CODE;
716     Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
717     Private->CrntShiftDWord = 0;
718 
719     Prefix = Private->Prefix;
720     for (i = 0; i <= LZ_MAX_CODE; i++)
721         Prefix[i] = NO_SUCH_CODE;
722 
723     return GIF_OK;
724 }
725 
726 /******************************************************************************
727  * The LZ decompression routine:
728  * This version decompress the given gif file into Line of length LineLen.
729  * This routine can be called few times (one per scan line, for example), in
730  * order the complete the whole image.
731  *****************************************************************************/
732 static int
733 DGifDecompressLine(GifFileType * GifFile,
734                    GifPixelType * Line,
735                    int LineLen) {
736 
737     int i = 0;
738     int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
739     GifByteType *Stack, *Suffix;
740     GifPrefixType *Prefix;
741     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
742 
743     StackPtr = Private->StackPtr;
744     Prefix = Private->Prefix;
745     Suffix = Private->Suffix;
746     Stack = Private->Stack;
747     EOFCode = Private->EOFCode;
748     ClearCode = Private->ClearCode;
749     LastCode = Private->LastCode;
750 
751     if (StackPtr > LZ_MAX_CODE) {
752         return GIF_ERROR;
753     }
754 
755     if (StackPtr != 0) {
756         /* Let pop the stack off before continueing to read the gif file: */
757         while (StackPtr != 0 && i < LineLen)
758             Line[i++] = Stack[--StackPtr];
759     }
760 
761     while (i < LineLen) {    /* Decode LineLen items. */
762         if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
763             return GIF_ERROR;
764 
765         if (CrntCode == EOFCode) {
766             /* Note however that usually we will not be here as we will stop
767              * decoding as soon as we got all the pixel, or EOF code will
768              * not be read at all, and DGifGetLine/Pixel clean everything.  */
769             if (i != LineLen - 1 || Private->PixelCount != 0) {
770                 _GifError = D_GIF_ERR_EOF_TOO_SOON;
771                 return GIF_ERROR;
772             }
773             i++;
774         } else if (CrntCode == ClearCode) {
775             /* We need to start over again: */
776             for (j = 0; j <= LZ_MAX_CODE; j++)
777                 Prefix[j] = NO_SUCH_CODE;
778             Private->RunningCode = Private->EOFCode + 1;
779             Private->RunningBits = Private->BitsPerPixel + 1;
780             Private->MaxCode1 = 1 << Private->RunningBits;
781             LastCode = Private->LastCode = NO_SUCH_CODE;
782         } else {
783             /* Its regular code - if in pixel range simply add it to output
784              * stream, otherwise trace to codes linked list until the prefix
785              * is in pixel range: */
786             if (CrntCode < ClearCode) {
787                 /* This is simple - its pixel scalar, so add it to output: */
788                 Line[i++] = CrntCode;
789             } else {
790                 /* Its a code to needed to be traced: trace the linked list
791                  * until the prefix is a pixel, while pushing the suffix
792                  * pixels on our stack. If we done, pop the stack in reverse
793                  * (thats what stack is good for!) order to output.  */
794                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
795                     /* Only allowed if CrntCode is exactly the running code:
796                      * In that case CrntCode = XXXCode, CrntCode or the
797                      * prefix code is last code and the suffix char is
798                      * exactly the prefix of last code! */
799                     if (CrntCode == Private->RunningCode - 2) {
800                         CrntPrefix = LastCode;
801                         Suffix[Private->RunningCode - 2] =
802                            Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
803                                                                  LastCode,
804                                                                  ClearCode);
805                     } else {
806                         _GifError = D_GIF_ERR_IMAGE_DEFECT;
807                         return GIF_ERROR;
808                     }
809                 } else
810                     CrntPrefix = CrntCode;
811 
812                 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE
813                  * During the trace. As we might loop forever, in case of
814                  * defective image, we count the number of loops we trace
815                  * and stop if we got LZ_MAX_CODE. obviously we can not
816                  * loop more than that.  */
817                 j = 0;
818                 while (j++ <= LZ_MAX_CODE &&
819                        CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
820                     Stack[StackPtr++] = Suffix[CrntPrefix];
821                     CrntPrefix = Prefix[CrntPrefix];
822                 }
823                 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
824                     _GifError = D_GIF_ERR_IMAGE_DEFECT;
825                     return GIF_ERROR;
826                 }
827                 /* Push the last character on stack: */
828                 Stack[StackPtr++] = CrntPrefix;
829 
830                 /* Now lets pop all the stack into output: */
831                 while (StackPtr != 0 && i < LineLen)
832                     Line[i++] = Stack[--StackPtr];
833             }
834             if (LastCode != NO_SUCH_CODE) {
835                 Prefix[Private->RunningCode - 2] = LastCode;
836 
837                 if (CrntCode == Private->RunningCode - 2) {
838                     /* Only allowed if CrntCode is exactly the running code:
839                      * In that case CrntCode = XXXCode, CrntCode or the
840                      * prefix code is last code and the suffix char is
841                      * exactly the prefix of last code! */
842                     Suffix[Private->RunningCode - 2] =
843                        DGifGetPrefixChar(Prefix, LastCode, ClearCode);
844                 } else {
845                     Suffix[Private->RunningCode - 2] =
846                        DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
847                 }
848             }
849             LastCode = CrntCode;
850         }
851     }
852 
853     Private->LastCode = LastCode;
854     Private->StackPtr = StackPtr;
855 
856     return GIF_OK;
857 }
858 
859 /******************************************************************************
860  * Routine to trace the Prefixes linked list until we get a prefix which is
861  * not code, but a pixel value (less than ClearCode). Returns that pixel value.
862  * If image is defective, we might loop here forever, so we limit the loops to
863  * the maximum possible if image O.k. - LZ_MAX_CODE times.
864  *****************************************************************************/
865 static int
866 DGifGetPrefixChar(GifPrefixType *Prefix,
867                   int Code,
868                   int ClearCode) {
869 
870     int i = 0;
871 
872     while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
873         if (Code > LZ_MAX_CODE) {
874             return NO_SUCH_CODE;
875         }
876         Code = Prefix[Code];
877     }
878     return Code;
879 }
880 
881 /******************************************************************************
882  * Interface for accessing the LZ codes directly. Set Code to the real code
883  * (12bits), or to -1 if EOF code is returned.
884  *****************************************************************************/
885 int
886 DGifGetLZCodes(GifFileType * GifFile,
887                int *Code) {
888 
889     GifByteType *CodeBlock;
890     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
891 
892     if (!IS_READABLE(Private)) {
893         /* This file was NOT open for reading: */
894         _GifError = D_GIF_ERR_NOT_READABLE;
895         return GIF_ERROR;
896     }
897 
898     if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
899         return GIF_ERROR;
900 
901     if (*Code == Private->EOFCode) {
902         /* Skip rest of codes (hopefully only NULL terminating block): */
903         do {
904             if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
905                 return GIF_ERROR;
906         } while (CodeBlock != NULL) ;
907 
908         *Code = -1;
909     } else if (*Code == Private->ClearCode) {
910         /* We need to start over again: */
911         Private->RunningCode = Private->EOFCode + 1;
912         Private->RunningBits = Private->BitsPerPixel + 1;
913         Private->MaxCode1 = 1 << Private->RunningBits;
914     }
915 
916     return GIF_OK;
917 }
918 
919 /******************************************************************************
920  * The LZ decompression input routine:
921  * This routine is responsable for the decompression of the bit stream from
922  * 8 bits (bytes) packets, into the real codes.
923  * Returns GIF_OK if read succesfully.
924  *****************************************************************************/
925 static int
926 DGifDecompressInput(GifFileType * GifFile,
927                     int *Code) {
928 
929     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
930 
931     GifByteType NextByte;
932     static unsigned short CodeMasks[] = {
933         0x0000, 0x0001, 0x0003, 0x0007,
934         0x000f, 0x001f, 0x003f, 0x007f,
935         0x00ff, 0x01ff, 0x03ff, 0x07ff,
936         0x0fff
937     };
938     /* The image can't contain more than LZ_BITS per code. */
939     if (Private->RunningBits > LZ_BITS) {
940         _GifError = D_GIF_ERR_IMAGE_DEFECT;
941         return GIF_ERROR;
942     }
943 
944     while (Private->CrntShiftState < Private->RunningBits) {
945         /* Needs to get more bytes from input stream for next code: */
946         if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
947             return GIF_ERROR;
948         }
949         Private->CrntShiftDWord |=
950            ((unsigned long)NextByte) << Private->CrntShiftState;
951         Private->CrntShiftState += 8;
952     }
953     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
954 
955     Private->CrntShiftDWord >>= Private->RunningBits;
956     Private->CrntShiftState -= Private->RunningBits;
957 
958     /* If code cannot fit into RunningBits bits, must raise its size. Note
959      * however that codes above 4095 are used for special signaling.
960      * If we're using LZ_BITS bits already and we're at the max code, just
961      * keep using the table as it is, don't increment Private->RunningCode.
962      */
963     if (Private->RunningCode < LZ_MAX_CODE + 2 &&
964             ++Private->RunningCode > Private->MaxCode1 &&
965             Private->RunningBits < LZ_BITS) {
966         Private->MaxCode1 <<= 1;
967         Private->RunningBits++;
968     }
969     return GIF_OK;
970 }
971 
972 /******************************************************************************
973  * This routines read one gif data block at a time and buffers it internally
974  * so that the decompression routine could access it.
975  * The routine returns the next byte from its internal buffer (or read next
976  * block in if buffer empty) and returns GIF_OK if succesful.
977  *****************************************************************************/
978 static int
979 DGifBufferedInput(GifFileType * GifFile,
980                   GifByteType * Buf,
981                   GifByteType * NextByte) {
982 
983     if (Buf[0] == 0) {
984         /* Needs to read the next buffer - this one is empty: */
985         if (READ(GifFile, Buf, 1) != 1) {
986             _GifError = D_GIF_ERR_READ_FAILED;
987             return GIF_ERROR;
988         }
989         /* There shouldn't be any empty data blocks here as the LZW spec
990          * says the LZW termination code should come first.  Therefore we
991          * shouldn't be inside this routine at that point.
992          */
993         if (Buf[0] == 0) {
994             _GifError = D_GIF_ERR_IMAGE_DEFECT;
995             return GIF_ERROR;
996         }
997         if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
998             _GifError = D_GIF_ERR_READ_FAILED;
999             return GIF_ERROR;
1000         }
1001         *NextByte = Buf[1];
1002         Buf[1] = 2;    /* We use now the second place as last char read! */
1003         Buf[0]--;
1004     } else {
1005         *NextByte = Buf[Buf[1]++];
1006         Buf[0]--;
1007     }
1008 
1009     return GIF_OK;
1010 }
1011 #ifndef _GBA_NO_FILEIO
1012 
1013 /******************************************************************************
1014  * This routine reads an entire GIF into core, hanging all its state info off
1015  * the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
1016  * first to initialize I/O.  Its inverse is EGifSpew().
1017  ******************************************************************************/
1018 int
1019 DGifSlurp(GifFileType * GifFile) {
1020 
1021     int ImageSize;
1022     GifRecordType RecordType;
1023     SavedImage *sp;
1024     GifByteType *ExtData;
1025     SavedImage temp_save;
1026 
1027     temp_save.ExtensionBlocks = NULL;
1028     temp_save.ExtensionBlockCount = 0;
1029 
1030     do {
1031         if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1032             return (GIF_ERROR);
1033 
1034         switch (RecordType) {
1035           case IMAGE_DESC_RECORD_TYPE:
1036               if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1037                   return (GIF_ERROR);
1038 
1039               sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1040               ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1041 
1042               sp->RasterBits = (unsigned char *)malloc(ImageSize *
1043                                                        sizeof(GifPixelType));
1044               if (sp->RasterBits == NULL) {
1045                   return GIF_ERROR;
1046               }
1047               if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
1048                   GIF_ERROR)
1049                   return (GIF_ERROR);
1050               if (temp_save.ExtensionBlocks) {
1051                   sp->ExtensionBlocks = temp_save.ExtensionBlocks;
1052                   sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;
1053 
1054                   temp_save.ExtensionBlocks = NULL;
1055                   temp_save.ExtensionBlockCount = 0;
1056 
1057                   /* FIXME: The following is wrong.  It is left in only for
1058                    * backwards compatibility.  Someday it should go away. Use
1059                    * the sp->ExtensionBlocks->Function variable instead. */
1060                   sp->Function = sp->ExtensionBlocks[0].Function;
1061               }
1062               break;
1063 
1064           case EXTENSION_RECORD_TYPE:
1065               if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) ==
1066                   GIF_ERROR)
1067                   return (GIF_ERROR);
1068               while (ExtData != NULL) {
1069 
1070                   /* Create an extension block with our data */
1071                   if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1])
1072                       == GIF_ERROR)
1073                       return (GIF_ERROR);
1074 
1075                   if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1076                       return (GIF_ERROR);
1077                   temp_save.Function = 0;
1078               }
1079               break;
1080 
1081           case TERMINATE_RECORD_TYPE:
1082               break;
1083 
1084           default:    /* Should be trapped by DGifGetRecordType */
1085               break;
1086         }
1087     } while (RecordType != TERMINATE_RECORD_TYPE);
1088 
1089     /* Just in case the Gif has an extension block without an associated
1090      * image... (Should we save this into a savefile structure with no image
1091      * instead? Have to check if the present writing code can handle that as
1092      * well.... */
1093     if (temp_save.ExtensionBlocks)
1094         FreeExtension(&temp_save);
1095 
1096     return (GIF_OK);
1097 }
1098 #endif /* _GBA_NO_FILEIO */
1099