1c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
2c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
39aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craikdgif_lib.c - GIF decoding
49aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
59aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikThe functions here and in egif_lib.c are partitioned carefully so that
69aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craikif you only require one of read and write capability, only one of these
79aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craiktwo modules will be linked.  Preserve this property!
8c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
99aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*****************************************************************************/
109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#include <stdlib.h>
129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#include <limits.h>
139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#include <stdint.h>
14c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <fcntl.h>
15c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <unistd.h>
16c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <stdio.h>
17c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <string.h>
189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#ifdef _WIN32
209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#include <io.h>
219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#endif /* _WIN32 */
229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
23c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include "gif_lib.h"
24c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include "gif_lib_private.h"
25c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/* compose unsigned little endian value */
279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#define UNSIGNED_LITTLE_ENDIAN(lo, hi)	((lo) | ((hi) << 8))
28c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
29c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* avoid extra function call in case we use fread (TVT) */
30c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#define READ(_gif,_buf,_len)                                     \
31c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project  (((GifFilePrivateType*)_gif->Private)->Read ?                   \
32c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
33c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
34c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
35c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int DGifGetWord(GifFileType *GifFile, GifWord *Word);
36c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int DGifSetupDecompress(GifFileType *GifFile);
37c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
38c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                              int LineLen);
39c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
40c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int DGifDecompressInput(GifFileType *GifFile, int *Code);
41c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
42c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                             GifByteType *NextByte);
43c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
44c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
459aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Open a new GIF file for read, given by its name.
469aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Returns dynamically allocated GifFileType pointer which serves as the GIF
479aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik info record.
489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
49c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectGifFileType *
509aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifOpenFileName(const char *FileName, int *Error)
519aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
52c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    int FileHandle;
53c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFileType *GifFile;
54c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
559aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if ((FileHandle = open(FileName, O_RDONLY)) == -1) {
569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	if (Error != NULL)
579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_OPEN_FAILED;
58c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
59c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
60c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile = DGifOpenFileHandle(FileHandle, Error);
629aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    // cppcheck-suppress resourceLeak
63c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GifFile;
64c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
65c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
66c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
679aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Update a new GIF file, given its file handle.
689aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Returns dynamically allocated GifFileType pointer which serves as the GIF
699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik info record.
709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
71c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectGifFileType *
729aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifOpenFileHandle(int FileHandle, int *Error)
739aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    char Buf[GIF_STAMP_LEN + 1];
75c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFileType *GifFile;
76c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private;
77c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    FILE *f;
78c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
79c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFile = (GifFileType *)malloc(sizeof(GifFileType));
80c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile == NULL) {
819aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
829aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
839aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        (void)close(FileHandle);
84c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
85c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
86c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType));
889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Belt and suspenders, in case the null pointer isn't zero */
909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->SavedImages = NULL;
919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->SColorMap = NULL;
92c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
93c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
94c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Private == NULL) {
959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
969aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
979aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        (void)close(FileHandle);
98c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
99c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
100c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
1019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#ifdef _WIN32
1029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    _setmode(FileHandle, O_BINARY);    /* Make sure it is in binary mode. */
1039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#endif /* _WIN32 */
104c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
105c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    f = fdopen(FileHandle, "rb");    /* Make it into a stream: */
106c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /*@-mustfreeonly@*/
1089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->Private = (void *)Private;
109c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->FileHandle = FileHandle;
110c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->File = f;
111c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->FileState = FILE_STATE_READ;
1129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    Private->Read = NULL;        /* don't use alternate input method (TVT) */
1139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->UserData = NULL;    /* TVT */
1149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /*@=mustfreeonly@*/
1159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
1169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Let's see if this is a GIF file: */
1179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
1189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
1199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_READ_FAILED;
1209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        (void)fclose(f);
121c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)Private);
122c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
123c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
124c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
125c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Check for GIF prefix at start of file */
127c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Buf[GIF_STAMP_LEN] = 0;
128c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
1299aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
1309aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_NOT_GIF_FILE;
1319aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        (void)fclose(f);
132c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)Private);
133c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
134c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
135c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
136c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
137c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
1389aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        (void)fclose(f);
139c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)Private);
140c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
141c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
142c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
143c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1449aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->Error = 0;
1459aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
1469aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* What version of GIF? */
1479aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
148c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
149c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GifFile;
150c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
151c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
152c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
1539aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFileType constructor with user supplied input function (TVT)
1549aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
155c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectGifFileType *
1569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifOpen(void *userData, InputFunc readFunc, int *Error)
1579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
1589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    char Buf[GIF_STAMP_LEN + 1];
159c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFileType *GifFile;
160c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private;
161c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
162c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFile = (GifFileType *)malloc(sizeof(GifFileType));
163c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile == NULL) {
1649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
1659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
166c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
167c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
168c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
169c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    memset(GifFile, '\0', sizeof(GifFileType));
170c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Belt and suspenders, in case the null pointer isn't zero */
1729aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->SavedImages = NULL;
1739aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->SColorMap = NULL;
1749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
175c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
176c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!Private) {
1779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
1789aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
179c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
180c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
181c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
182c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1839aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->Private = (void *)Private;
184c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->FileHandle = 0;
1859aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    Private->File = NULL;
186c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->FileState = FILE_STATE_READ;
187c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
188c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->Read = readFunc;    /* TVT */
189c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFile->UserData = userData;    /* TVT */
190c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
191c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    /* Lets see if this is a GIF file: */
1929aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
1939aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
1949aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_READ_FAILED;
195c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)Private);
196c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
197c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
198c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
199c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
2009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Check for GIF prefix at start of file */
2019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    Buf[GIF_STAMP_LEN] = '\0';
202c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
2039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Error != NULL)
2049aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    *Error = D_GIF_ERR_NOT_GIF_FILE;
205c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)Private);
206c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
207c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
208c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
209c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
210c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
211c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)Private);
212c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        free((char *)GifFile);
213c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return NULL;
214c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
215c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
2169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->Error = 0;
2179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
2189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* What version of GIF? */
2199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
220c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
221c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GifFile;
222c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
223c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
224c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
2259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine should be called before any other DGif calls. Note that
2269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik this routine is called automatically from DGif file open routines.
2279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
228c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
2299aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetScreenDesc(GifFileType *GifFile)
2309aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
2319aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    int BitsPerPixel;
2329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    bool SortFlag;
233c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType Buf[3];
234c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
235c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
236c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
237c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
2389aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
239c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
240c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
241c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
242c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    /* Put the screen descriptor into the file: */
243c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
244c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
245c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
246c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
247c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, Buf, 3) != 3) {
2489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
2499aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GifFreeMapObject(GifFile->SColorMap);
2509aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GifFile->SColorMap = NULL;
251c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
252c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
253c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
2549aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    SortFlag = (Buf[0] & 0x08) != 0;
255c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    BitsPerPixel = (Buf[0] & 0x07) + 1;
256c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFile->SBackGroundColor = Buf[1];
2579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->AspectByte = Buf[2];
258c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Buf[0] & 0x80) {    /* Do we have global color map? */
2599aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	int i;
260c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
2619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
262c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (GifFile->SColorMap == NULL) {
2639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
264c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
265c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
266c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
267c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* Get the global color map: */
2689aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GifFile->SColorMap->SortFlag = SortFlag;
269c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
270c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            if (READ(GifFile, Buf, 3) != 3) {
2719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                GifFreeMapObject(GifFile->SColorMap);
272c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                GifFile->SColorMap = NULL;
2739aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                GifFile->Error = D_GIF_ERR_READ_FAILED;
274c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                return GIF_ERROR;
275c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            }
276c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            GifFile->SColorMap->Colors[i].Red = Buf[0];
277c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            GifFile->SColorMap->Colors[i].Green = Buf[1];
278c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            GifFile->SColorMap->Colors[i].Blue = Buf[2];
279c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
280c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else {
281c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        GifFile->SColorMap = NULL;
282c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
283c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
284c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
285c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
286c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
287c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
2889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine should be called before any attempt to read an image.
2899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
290c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
2919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
2929aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
293c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType Buf;
294c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
295c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
296c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
297c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
2989aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
299c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
300c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
301c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
302c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, &Buf, 1) != 1) {
3039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
304c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
305c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
306c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
307c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    switch (Buf) {
3089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik      case DESCRIPTOR_INTRODUCER:
309c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          *Type = IMAGE_DESC_RECORD_TYPE;
310c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          break;
3119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik      case EXTENSION_INTRODUCER:
312c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          *Type = EXTENSION_RECORD_TYPE;
313c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          break;
3149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik      case TERMINATOR_INTRODUCER:
315c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          *Type = TERMINATE_RECORD_TYPE;
316c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          break;
317c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project      default:
318c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          *Type = UNDEFINED_RECORD_TYPE;
3199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik          GifFile->Error = D_GIF_ERR_WRONG_RECORD;
320c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          return GIF_ERROR;
321c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
322c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
323c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
324c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
325c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
326c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
3279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine should be called before any attempt to read an image.
3289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Note it is assumed the Image desc. header has been read.
3299aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
330c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
3319aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetImageDesc(GifFileType *GifFile)
3329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
3339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    unsigned int BitsPerPixel;
334c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType Buf[3];
335c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
336c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    SavedImage *sp;
337c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
338c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
339c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
3409aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
341c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
342c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
343c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
344c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
345c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
346c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
347c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
348c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
349c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, Buf, 1) != 1) {
3509aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
3519aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GifFreeMapObject(GifFile->Image.ColorMap);
3529aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GifFile->Image.ColorMap = NULL;
353c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
354c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
355c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    BitsPerPixel = (Buf[0] & 0x07) + 1;
3569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
357c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
3589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Setup the colormap */
3599aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (GifFile->Image.ColorMap) {
3609aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFreeMapObject(GifFile->Image.ColorMap);
3619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Image.ColorMap = NULL;
3629aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    }
3639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Does this image have local color map? */
3649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (Buf[0] & 0x80) {
3659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	unsigned int i;
366c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
3679aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
368c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (GifFile->Image.ColorMap == NULL) {
3699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
370c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
371c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
372c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
373c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* Get the image local color map: */
374c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
375c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            if (READ(GifFile, Buf, 3) != 3) {
3769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                GifFreeMapObject(GifFile->Image.ColorMap);
3779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                GifFile->Error = D_GIF_ERR_READ_FAILED;
378c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                GifFile->Image.ColorMap = NULL;
379c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                return GIF_ERROR;
380c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            }
381c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
382c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
383c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
384c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
385c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
386c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
387c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile->SavedImages) {
388c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
389c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                                      sizeof(SavedImage) *
390c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                                      (GifFile->ImageCount + 1))) == NULL) {
3919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
392c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
393c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
394c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else {
395c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if ((GifFile->SavedImages =
396c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project             (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
3979aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
398c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
399c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
400c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
401c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
402c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    sp = &GifFile->SavedImages[GifFile->ImageCount];
403c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
404c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile->Image.ColorMap != NULL) {
4059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        sp->ImageDesc.ColorMap = GifMakeMapObject(
406c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                                 GifFile->Image.ColorMap->ColorCount,
407c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                                 GifFile->Image.ColorMap->Colors);
408c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (sp->ImageDesc.ColorMap == NULL) {
4099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
410c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
411c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
412c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
413c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    sp->RasterBits = (unsigned char *)NULL;
414c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    sp->ExtensionBlockCount = 0;
415c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    sp->ExtensionBlocks = (ExtensionBlock *) NULL;
416c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
417c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFile->ImageCount++;
418c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
419c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->PixelCount = (long)GifFile->Image.Width *
420c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project       (long)GifFile->Image.Height;
421c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
4229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* Reset decompress algorithm parameters. */
4239aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    (void)DGifSetupDecompress(GifFile);
424c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
425c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
426c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
427c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
428c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
4299aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Get one full scanned line (Line) of length LineLen from GIF file.
4309aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
431c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
4329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
4339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
434c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType *Dummy;
435c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
436c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
437c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
438c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
4399aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
440c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
441c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
442c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
443c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!LineLen)
444c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        LineLen = GifFile->Image.Width;
445c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
446c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
4479aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
448c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
449c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
450c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
451c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
452c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (Private->PixelCount == 0) {
4539aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            /* We probably won't be called any more, so let's clean up
4549aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik             * everything before we return: need to flush out all the
4559aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik             * rest of image until an empty block (size 0)
4569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik             * detected. We use GetCodeNext.
4579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	     */
458c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            do
459c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
460c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    return GIF_ERROR;
461c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            while (Dummy != NULL) ;
462c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
463c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_OK;
464c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else
465c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
466c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
467c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
468c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
4699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Put one pixel (Pixel) into GIF file.
4709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
471c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
4729aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
4739aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
474c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType *Dummy;
475c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
476c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
477c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
478c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
4799aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
480c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
481c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
482c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (--Private->PixelCount > 0xffff0000UL)
483c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    {
4849aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
485c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
486c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
487c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
488c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
489c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (Private->PixelCount == 0) {
4909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            /* We probably won't be called any more, so let's clean up
4919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik             * everything before we return: need to flush out all the
4929aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik             * rest of image until an empty block (size 0)
4939aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik             * detected. We use GetCodeNext.
4949aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	     */
495c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            do
496c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
497c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    return GIF_ERROR;
498c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            while (Dummy != NULL) ;
499c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
500c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_OK;
501c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else
502c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
503c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
504c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
505c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
5069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Get an extension block (see GIF manual) from GIF file. This routine only
5079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik returns the first data block, and DGifGetExtensionNext should be called
5089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik after this one until NULL extension is returned.
5099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The Extension should NOT be freed by the user (not dynamically allocated).
5109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Note it is assumed the Extension description header has been read.
5119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
512c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
5139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
5149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
515c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType Buf;
516c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
517c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
518c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
519c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
5209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
521c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
522c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
523c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
524c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, &Buf, 1) != 1) {
5259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
526c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
527c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
528c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    *ExtCode = Buf;
529c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
530c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return DGifGetExtensionNext(GifFile, Extension);
531c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
532c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
533c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
5349aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Get a following extension block (see GIF manual) from GIF file. This
5359aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik routine should be called until NULL Extension is returned.
5369aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The Extension should NOT be freed by the user (not dynamically allocated).
5379aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
538c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
5399aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
5409aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
541c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType Buf;
542c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
543c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
544c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, &Buf, 1) != 1) {
5459aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
546c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
547c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
548c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Buf > 0) {
549c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *Extension = Private->Buf;    /* Use private unused buffer. */
550c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
5519aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	/* coverity[tainted_data] */
552c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
5539aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_READ_FAILED;
554c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
555c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
556c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else
557c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *Extension = NULL;
558c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
559c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
560c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
561c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
562c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
5639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Extract a Graphics Control Block from raw extension data
5649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
5659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
5669aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craikint DGifExtensionToGCB(const size_t GifExtensionLength,
5679aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		       const GifByteType *GifExtension,
5689aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		       GraphicsControlBlock *GCB)
5699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
5709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (GifExtensionLength != 4) {
5719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	return GIF_ERROR;
5729aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    }
573c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
5749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
5759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
5769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
5779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (GifExtension[0] & 0x01)
5789aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GCB->TransparentColor = (int)GifExtension[3];
5799aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    else
5809aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	GCB->TransparentColor = NO_TRANSPARENT_COLOR;
581c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
5829aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    return GIF_OK;
5839aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik}
584c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
5859aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************
5869aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Extract the Graphics Control Block for a saved image, if it exists.
5879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
5889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
5899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craikint DGifSavedExtensionToGCB(GifFileType *GifFile,
5909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik			    int ImageIndex, GraphicsControlBlock *GCB)
5919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
5929aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    int i;
5939aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
5949aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
5959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	return GIF_ERROR;
5969aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
5979aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
5989aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->UserInputFlag = false;
5999aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->DelayTime = 0;
6009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GCB->TransparentColor = NO_TRANSPARENT_COLOR;
6019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
6039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
6049aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
6059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
606c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
607c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
6089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    return GIF_ERROR;
6099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik}
6109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************
6129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine should be called last, to close the GIF file.
6139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
6149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craikint
6159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifCloseFile(GifFileType *GifFile)
6169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
6179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFilePrivateType *Private;
6189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (GifFile == NULL || GifFile->Private == NULL)
6209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        return GIF_ERROR;
621c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
622c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile->Image.ColorMap) {
6239aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFreeMapObject(GifFile->Image.ColorMap);
624c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        GifFile->Image.ColorMap = NULL;
625c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
626c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
627c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile->SColorMap) {
6289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFreeMapObject(GifFile->SColorMap);
629c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        GifFile->SColorMap = NULL;
630c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
631c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
632c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (GifFile->SavedImages) {
6339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFreeSavedImages(GifFile);
634c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        GifFile->SavedImages = NULL;
635c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
636c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
6379aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
638c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
6399aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    Private = (GifFilePrivateType *) GifFile->Private;
6409aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6419aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (!IS_READABLE(Private)) {
6429aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        /* This file was NOT open for reading: */
6439aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
6449aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        return GIF_ERROR;
6459aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    }
6469aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6479aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    if (Private->File && (fclose(Private->File) != 0)) {
6489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_CLOSE_FAILED;
649c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
650c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
6519aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6529aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    free((char *)GifFile->Private);
6539aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
6549aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /*
6559aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik     * Without the #ifndef, we get spurious warnings because Coverity mistakenly
6569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik     * thinks the GIF structure is freed on an error return.
6579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik     */
6589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#ifndef __COVERITY__
6599aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    free(GifFile);
6609aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik#endif /* __COVERITY__ */
6619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
662c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
663c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
664c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
665c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
6669aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Get 2 bytes (word) from the given file:
6679aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
668c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int
6699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetWord(GifFileType *GifFile, GifWord *Word)
6709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
671c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    unsigned char c[2];
672c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
673c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, c, 2) != 2) {
6749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
675c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
676c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
677c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
6789aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
679c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
680c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
681c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
682c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
6839aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Get the image code in compressed form.  This routine can be called if the
6849aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik information needed to be piped out as is. Obviously this is much faster
6859aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik than decoding and encoding again. This routine should be followed by calls
6869aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik to DGifGetCodeNext, until NULL block is returned.
6879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The block should NOT be freed by the user (not dynamically allocated).
6889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
689c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
6909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
6919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
692c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
693c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
694c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
695c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
6969aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
697c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
698c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
699c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
700c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    *CodeSize = Private->BitsPerPixel;
701c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
702c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return DGifGetCodeNext(GifFile, CodeBlock);
703c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
704c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
705c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
7069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Continue to get the image code in compressed form. This routine should be
7079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik called until NULL block is returned.
7089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The block should NOT be freed by the user (not dynamically allocated).
7099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
710c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
7119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
7129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
713c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType Buf;
714c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
715c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
7169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* coverity[tainted_data_argument] */
717c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (READ(GifFile, &Buf, 1) != 1) {
7189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_READ_FAILED;
719c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
720c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
721c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
7229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    /* coverity[lower_bounds] */
723c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Buf > 0) {
724c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *CodeBlock = Private->Buf;    /* Use private unused buffer. */
725c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
7269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	/* coverity[tainted_data] */
727c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
7289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_READ_FAILED;
729c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
730c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
731c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else {
732c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *CodeBlock = NULL;
733c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
734c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->PixelCount = 0;    /* And local info. indicate image read. */
735c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
736c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
737c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
738c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
739c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
740c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
7419aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Setup the LZ decompression for this image:
7429aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
743c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int
7449aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifSetupDecompress(GifFileType *GifFile)
7459aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
746c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    int i, BitsPerPixel;
747c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType CodeSize;
748c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifPrefixType *Prefix;
749c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
750c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
751c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
752c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    BitsPerPixel = CodeSize;
753c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
754c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->Buf[0] = 0;    /* Input Buffer empty. */
755c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->BitsPerPixel = BitsPerPixel;
756c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->ClearCode = (1 << BitsPerPixel);
757c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->EOFCode = Private->ClearCode + 1;
758c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->RunningCode = Private->EOFCode + 1;
759c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
760c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
761c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->StackPtr = 0;    /* No pixels on the pixel stack. */
762c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->LastCode = NO_SUCH_CODE;
763c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
764c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->CrntShiftDWord = 0;
765c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
766c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Prefix = Private->Prefix;
767c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    for (i = 0; i <= LZ_MAX_CODE; i++)
768c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Prefix[i] = NO_SUCH_CODE;
769c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
770c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
771c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
772c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
773c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
7749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The LZ decompression routine:
7759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This version decompress the given GIF file into Line of length LineLen.
7769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine can be called few times (one per scan line, for example), in
7779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik order the complete the whole image.
7789aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
779c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int
7809aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
7819aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
782c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    int i = 0;
783c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
784c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType *Stack, *Suffix;
785c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifPrefixType *Prefix;
786c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
787c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
788c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    StackPtr = Private->StackPtr;
789c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Prefix = Private->Prefix;
790c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Suffix = Private->Suffix;
791c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Stack = Private->Stack;
792c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    EOFCode = Private->EOFCode;
793c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    ClearCode = Private->ClearCode;
794c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    LastCode = Private->LastCode;
795c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
796c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (StackPtr > LZ_MAX_CODE) {
797c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
798c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
799c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
800c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (StackPtr != 0) {
8019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        /* Let pop the stack off before continueing to read the GIF file: */
802c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        while (StackPtr != 0 && i < LineLen)
803c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            Line[i++] = Stack[--StackPtr];
804c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
805c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
806c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    while (i < LineLen) {    /* Decode LineLen items. */
807c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
808c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
809c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
810c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (CrntCode == EOFCode) {
811c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            /* Note however that usually we will not be here as we will stop
812c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project             * decoding as soon as we got all the pixel, or EOF code will
813c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project             * not be read at all, and DGifGetLine/Pixel clean everything.  */
8149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
8159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    return GIF_ERROR;
816c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        } else if (CrntCode == ClearCode) {
817c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            /* We need to start over again: */
818c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            for (j = 0; j <= LZ_MAX_CODE; j++)
819c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                Prefix[j] = NO_SUCH_CODE;
820c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            Private->RunningCode = Private->EOFCode + 1;
821c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            Private->RunningBits = Private->BitsPerPixel + 1;
822c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            Private->MaxCode1 = 1 << Private->RunningBits;
823c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            LastCode = Private->LastCode = NO_SUCH_CODE;
824c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        } else {
825c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            /* Its regular code - if in pixel range simply add it to output
826c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project             * stream, otherwise trace to codes linked list until the prefix
827c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project             * is in pixel range: */
828c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            if (CrntCode < ClearCode) {
829c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                /* This is simple - its pixel scalar, so add it to output: */
830c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                Line[i++] = CrntCode;
831c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            } else {
832c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                /* Its a code to needed to be traced: trace the linked list
833c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                 * until the prefix is a pixel, while pushing the suffix
834c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                 * pixels on our stack. If we done, pop the stack in reverse
835c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                 * (thats what stack is good for!) order to output.  */
836c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                if (Prefix[CrntCode] == NO_SUCH_CODE) {
837c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    /* Only allowed if CrntCode is exactly the running code:
838c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                     * In that case CrntCode = XXXCode, CrntCode or the
839c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                     * prefix code is last code and the suffix char is
840c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                     * exactly the prefix of last code! */
841c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    if (CrntCode == Private->RunningCode - 2) {
842c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                        CrntPrefix = LastCode;
843c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                        Suffix[Private->RunningCode - 2] =
844c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
845c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                                                                 LastCode,
846c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                                                                 ClearCode);
847c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    } else {
8489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                        GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
849c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                        return GIF_ERROR;
850c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    }
851c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                } else
852c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    CrntPrefix = CrntCode;
853c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
8549aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
8559aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                 * during the trace. As we might loop forever, in case of
8569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                 * defective image, we use StackPtr as loop counter and stop
8579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                 * before overflowing Stack[]. */
8589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                while (StackPtr < LZ_MAX_CODE &&
859c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                       CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
860c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    Stack[StackPtr++] = Suffix[CrntPrefix];
861c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    CrntPrefix = Prefix[CrntPrefix];
862c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                }
8639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
8649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                    GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
865c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    return GIF_ERROR;
866c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                }
867c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                /* Push the last character on stack: */
868c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                Stack[StackPtr++] = CrntPrefix;
869c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
870c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                /* Now lets pop all the stack into output: */
871c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                while (StackPtr != 0 && i < LineLen)
872c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    Line[i++] = Stack[--StackPtr];
873c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            }
8749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
875c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                Prefix[Private->RunningCode - 2] = LastCode;
876c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
877c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                if (CrntCode == Private->RunningCode - 2) {
878c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    /* Only allowed if CrntCode is exactly the running code:
879c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                     * In that case CrntCode = XXXCode, CrntCode or the
880c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                     * prefix code is last code and the suffix char is
881c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                     * exactly the prefix of last code! */
882c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    Suffix[Private->RunningCode - 2] =
883c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                       DGifGetPrefixChar(Prefix, LastCode, ClearCode);
884c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                } else {
885c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                    Suffix[Private->RunningCode - 2] =
886c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                       DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
887c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                }
888c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            }
889c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            LastCode = CrntCode;
890c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
891c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
892c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
893c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->LastCode = LastCode;
894c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->StackPtr = StackPtr;
895c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
896c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
897c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
898c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
899c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
9009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Routine to trace the Prefixes linked list until we get a prefix which is
9019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik not code, but a pixel value (less than ClearCode). Returns that pixel value.
9029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik If image is defective, we might loop here forever, so we limit the loops to
9039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik the maximum possible if image O.k. - LZ_MAX_CODE times.
9049aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
905c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int
9069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
9079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
908c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    int i = 0;
909c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
910c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
911c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (Code > LZ_MAX_CODE) {
912c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return NO_SUCH_CODE;
913c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
914c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Code = Prefix[Code];
915c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
916c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return Code;
917c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
918c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
919c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
9209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Interface for accessing the LZ codes directly. Set Code to the real code
9219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (12bits), or to -1 if EOF code is returned.
9229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
923c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
9249aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifGetLZCodes(GifFileType *GifFile, int *Code)
9259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
926c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType *CodeBlock;
927c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
928c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
929c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (!IS_READABLE(Private)) {
930c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* This file was NOT open for reading: */
9319aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_NOT_READABLE;
932c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
933c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
934c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
935c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
936c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
937c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
938c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (*Code == Private->EOFCode) {
939c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* Skip rest of codes (hopefully only NULL terminating block): */
940c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        do {
941c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
942c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                return GIF_ERROR;
943c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        } while (CodeBlock != NULL) ;
944c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
945c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *Code = -1;
946c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else if (*Code == Private->ClearCode) {
947c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* We need to start over again: */
948c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->RunningCode = Private->EOFCode + 1;
949c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->RunningBits = Private->BitsPerPixel + 1;
950c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->MaxCode1 = 1 << Private->RunningBits;
951c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
952c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
953c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
954c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
955c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
956c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
9579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The LZ decompression input routine:
9589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine is responsable for the decompression of the bit stream from
9599aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 8 bits (bytes) packets, into the real codes.
9609aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Returns GIF_OK if read successfully.
9619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
962c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int
9639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifDecompressInput(GifFileType *GifFile, int *Code)
9649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
9659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    static const unsigned short CodeMasks[] = {
9669aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	0x0000, 0x0001, 0x0003, 0x0007,
9679aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	0x000f, 0x001f, 0x003f, 0x007f,
9689aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	0x00ff, 0x01ff, 0x03ff, 0x07ff,
9699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	0x0fff
9709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    };
9719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
972c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
973c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
974c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType NextByte;
9759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
976c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    /* The image can't contain more than LZ_BITS per code. */
977c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Private->RunningBits > LZ_BITS) {
9789aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
979c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        return GIF_ERROR;
980c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
981c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
982c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    while (Private->CrntShiftState < Private->RunningBits) {
983c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* Needs to get more bytes from input stream for next code: */
984c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
985c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
986c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
987c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->CrntShiftDWord |=
9889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	    ((unsigned long)NextByte) << Private->CrntShiftState;
989c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->CrntShiftState += 8;
990c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
991c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
992c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
993c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->CrntShiftDWord >>= Private->RunningBits;
994c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    Private->CrntShiftState -= Private->RunningBits;
995c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
996c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    /* If code cannot fit into RunningBits bits, must raise its size. Note
997c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project     * however that codes above 4095 are used for special signaling.
998c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project     * If we're using LZ_BITS bits already and we're at the max code, just
999c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project     * keep using the table as it is, don't increment Private->RunningCode.
1000c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project     */
1001c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Private->RunningCode < LZ_MAX_CODE + 2 &&
10029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	++Private->RunningCode > Private->MaxCode1 &&
10039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	Private->RunningBits < LZ_BITS) {
1004c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->MaxCode1 <<= 1;
1005c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Private->RunningBits++;
1006c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
1007c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
1008c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
1009c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1010c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
10119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routines read one GIF data block at a time and buffers it internally
10129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik so that the decompression routine could access it.
10139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik The routine returns the next byte from its internal buffer (or read next
10149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik block in if buffer empty) and returns GIF_OK if succesful.
10159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/
1016c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectstatic int
10179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
10189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
1019c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    if (Buf[0] == 0) {
1020c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* Needs to read the next buffer - this one is empty: */
1021c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (READ(GifFile, Buf, 1) != 1) {
10229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_READ_FAILED;
1023c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
1024c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
1025c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        /* There shouldn't be any empty data blocks here as the LZW spec
1026c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project         * says the LZW termination code should come first.  Therefore we
1027c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project         * shouldn't be inside this routine at that point.
1028c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project         */
1029c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (Buf[0] == 0) {
10309aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
10319aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            return GIF_ERROR;
10329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        }
10339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        /* There shouldn't be any empty data blocks here as the LZW spec
10349aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik         * says the LZW termination code should come first.  Therefore we
10359aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik         * shouldn't be inside this routine at that point.
10369aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik         */
10379aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik        if (Buf[0] == 0) {
10389aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1039c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
1040c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
1041c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
10429aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik            GifFile->Error = D_GIF_ERR_READ_FAILED;
1043c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return GIF_ERROR;
1044c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
1045c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *NextByte = Buf[1];
1046c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Buf[1] = 2;    /* We use now the second place as last char read! */
1047c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Buf[0]--;
1048c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } else {
1049c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        *NextByte = Buf[Buf[1]++];
1050c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        Buf[0]--;
1051c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    }
1052c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1053c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return GIF_OK;
1054c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
1055c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1056c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/******************************************************************************
10579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik This routine reads an entire GIF into core, hanging all its state info off
10589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
10599aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik first to initialize I/O.  Its inverse is EGifSpew().
10609aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/
1061c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint
10629aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDGifSlurp(GifFileType *GifFile)
10639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{
10649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    size_t ImageSize;
1065c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifRecordType RecordType;
1066c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    SavedImage *sp;
1067c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    GifByteType *ExtData;
10689aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    int ExtFunction;
1069c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
10709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->ExtensionBlocks = NULL;
10719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik    GifFile->ExtensionBlockCount = 0;
1072c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1073c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    do {
1074c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1075c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project            return (GIF_ERROR);
1076c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1077c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        switch (RecordType) {
1078c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          case IMAGE_DESC_RECORD_TYPE:
1079c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1080c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                  return (GIF_ERROR);
1081c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1082c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
10839aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              /* Allocate memory for the image */
10849aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 &&
10859aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                      sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
10869aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  return GIF_ERROR;
10879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              }
1088c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1089c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
10909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
10919aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  return GIF_ERROR;
10929aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              }
1093c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              sp->RasterBits = (unsigned char *)malloc(ImageSize *
10949aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                      sizeof(GifPixelType));
10959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
1096c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              if (sp->RasterBits == NULL) {
1097c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                  return GIF_ERROR;
1098c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              }
1099c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
11009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	      if (sp->ImageDesc.Interlace) {
11019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  int i, j;
11029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		   /*
11039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		    * The way an interlaced image should be read -
11049aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		    * offsets and jumps...
11059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		    */
11069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  int InterlacedOffset[] = { 0, 4, 2, 1 };
11079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  int InterlacedJumps[] = { 8, 8, 4, 2 };
11089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  /* Need to perform 4 passes on the image */
11099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  for (i = 0; i < 4; i++)
11109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		      for (j = InterlacedOffset[i];
11119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik			   j < sp->ImageDesc.Height;
11129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik			   j += InterlacedJumps[i]) {
11139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik			  if (DGifGetLine(GifFile,
11149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik					  sp->RasterBits+j*sp->ImageDesc.Width,
11159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik					  sp->ImageDesc.Width) == GIF_ERROR)
11169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik			      return GIF_ERROR;
11179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		      }
11189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	      }
11199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	      else {
11209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
11219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		      return (GIF_ERROR);
11229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	      }
11239aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
11249aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              if (GifFile->ExtensionBlocks) {
11259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  sp->ExtensionBlocks = GifFile->ExtensionBlocks;
11269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
11279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
11289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  GifFile->ExtensionBlocks = NULL;
11299aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  GifFile->ExtensionBlockCount = 0;
1130c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              }
1131c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              break;
1132c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1133c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          case EXTENSION_RECORD_TYPE:
11349aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik              if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
1135c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                  return (GIF_ERROR);
11369aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	      /* Create an extension block with our data */
11379aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik	      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
11389aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik				       &GifFile->ExtensionBlocks,
11399aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik				       ExtFunction, ExtData[0], &ExtData[1])
11409aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  == GIF_ERROR)
11419aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  return (GIF_ERROR);
1142c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              while (ExtData != NULL) {
1143c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                  if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1144c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project                      return (GIF_ERROR);
11459aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                  /* Continue the extension block */
11469aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		  if (ExtData != NULL)
11479aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik		      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
11489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik					       &GifFile->ExtensionBlocks,
11499aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik					       CONTINUE_EXT_FUNC_CODE,
11509aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik					       ExtData[0], &ExtData[1]) == GIF_ERROR)
11519aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik                      return (GIF_ERROR);
1152c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              }
1153c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              break;
1154c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1155c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          case TERMINATE_RECORD_TYPE:
1156c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              break;
1157c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1158c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project          default:    /* Should be trapped by DGifGetRecordType */
1159c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project              break;
1160c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project        }
1161c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    } while (RecordType != TERMINATE_RECORD_TYPE);
1162c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project
1163c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project    return (GIF_OK);
1164c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project}
11659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik
11669aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/* end */
1167