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