dgif_lib.c revision 1bc4596b116b3c829824c8b929ce48f864ca4a3c
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
51static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
52static int DGifSetupDecompress(GifFileType *GifFile);
53static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
54                              int LineLen);
55static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
56static int DGifDecompressInput(GifFileType *GifFile, int *Code);
57static 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 *****************************************************************************/
66GifFileType *
67DGifOpenFileName(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 *****************************************************************************/
89GifFileType *
90DGifOpenFileHandle(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 *****************************************************************************/
168GifFileType *
169DGifOpen(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 *****************************************************************************/
232int
233DGifGetScreenDesc(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 *****************************************************************************/
287int
288DGifGetRecordType(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 *****************************************************************************/
328int
329DGifGetImageDesc(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 *****************************************************************************/
426int
427DGifGetLine(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 *****************************************************************************/
470int
471DGifGetPixel(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 *****************************************************************************/
514int
515DGifGetExtension(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 *****************************************************************************/
542int
543DGifGetExtensionNext(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 *****************************************************************************/
569int
570DGifCloseFile(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 *****************************************************************************/
620static int
621DGifGetWord(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 *****************************************************************************/
642int
643DGifGetCode(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 *****************************************************************************/
665int
666DGifGetCodeNext(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 *****************************************************************************/
696static int
697DGifSetupDecompress(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 *****************************************************************************/
732static int
733DGifDecompressLine(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 *****************************************************************************/
865static int
866DGifGetPrefixChar(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 *****************************************************************************/
885int
886DGifGetLZCodes(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 *****************************************************************************/
925static int
926DGifDecompressInput(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 *****************************************************************************/
978static int
979DGifBufferedInput(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 ******************************************************************************/
1018int
1019DGifSlurp(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