From 9aef3ea079a57c98a9207f8c3b95a5dc08ee74b5 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Mon, 24 Jun 2013 19:34:25 -0700 Subject: Update GIFLIB to 5.0.4 bug:9557383 Requires external/skia change: https://googleplex-android-review.googlesource.com/#/c/324745/ Change-Id: I0e59747b084c3215c699ada0edc0abd195e22e73 --- MODULE_LICENSE_MIT | 0 dgif_lib.c | 806 +++++++++++++++++++++++++++++------------------------ gif_err.c | 77 ++--- gif_hash.h | 38 +-- gif_lib.h | 373 +++++++++++-------------- gif_lib_private.h | 24 +- gifalloc.c | 273 ++++++++---------- 7 files changed, 760 insertions(+), 831 deletions(-) create mode 100644 MODULE_LICENSE_MIT diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT new file mode 100644 index 0000000..e69de29 diff --git a/dgif_lib.c b/dgif_lib.c index 760d053..c7ff504 100644 --- a/dgif_lib.c +++ b/dgif_lib.c @@ -1,46 +1,30 @@ /****************************************************************************** - * "Gif-Lib" - Yet another gif library. - * - * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 - ****************************************************************************** - * The kernel of the GIF Decoding process can be found here. - ****************************************************************************** - * History: - * 16 Jun 89 - Version 1.0 by Gershon Elber. - * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). - *****************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__) -#include -#include -#include -#else -#include -#include -#endif /* __MSDOS__ */ - -#ifdef HAVE_IO_H -#include -#endif +dgif_lib.c - GIF decoding + +The functions here and in egif_lib.c are partitioned carefully so that +if you only require one of read and write capability, only one of these +two modules will be linked. Preserve this property! -#ifdef HAVE_FCNTL_H +*****************************************************************************/ + +#include +#include +#include #include -#endif /* HAVE_FCNTL_H */ -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include #include + +#ifdef _WIN32 +#include +#endif /* _WIN32 */ + #include "gif_lib.h" #include "gif_lib_private.h" -#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for - comment. */ +/* compose unsigned little endian value */ +#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8)) /* avoid extra function call in case we use fread (TVT) */ #define READ(_gif,_buf,_len) \ @@ -56,159 +40,168 @@ static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode); static int DGifDecompressInput(GifFileType *GifFile, int *Code); static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte); -#ifndef _GBA_NO_FILEIO /****************************************************************************** - * Open a new gif file for read, given by its name. - * Returns GifFileType pointer dynamically allocated which serves as the gif - * info record. _GifError is cleared if succesfull. - *****************************************************************************/ + Open a new GIF file for read, given by its name. + Returns dynamically allocated GifFileType pointer which serves as the GIF + info record. +******************************************************************************/ GifFileType * -DGifOpenFileName(const char *FileName) { +DGifOpenFileName(const char *FileName, int *Error) +{ int FileHandle; GifFileType *GifFile; - if ((FileHandle = open(FileName, O_RDONLY -#if defined(__MSDOS__) || defined(WINDOWS32) || defined(_OPEN_BINARY) - | O_BINARY -#endif /* __MSDOS__ || _OPEN_BINARY */ - )) == -1) { - _GifError = D_GIF_ERR_OPEN_FAILED; + if ((FileHandle = open(FileName, O_RDONLY)) == -1) { + if (Error != NULL) + *Error = D_GIF_ERR_OPEN_FAILED; return NULL; } - GifFile = DGifOpenFileHandle(FileHandle); + GifFile = DGifOpenFileHandle(FileHandle, Error); + // cppcheck-suppress resourceLeak return GifFile; } /****************************************************************************** - * Update a new gif file, given its file handle. - * Returns GifFileType pointer dynamically allocated which serves as the gif - * info record. _GifError is cleared if succesfull. - *****************************************************************************/ + Update a new GIF file, given its file handle. + Returns dynamically allocated GifFileType pointer which serves as the GIF + info record. +******************************************************************************/ GifFileType * -DGifOpenFileHandle(int FileHandle) { - - unsigned char Buf[GIF_STAMP_LEN + 1]; +DGifOpenFileHandle(int FileHandle, int *Error) +{ + char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; FILE *f; GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - close(FileHandle); + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + (void)close(FileHandle); return NULL; } - memset(GifFile, '\0', sizeof(GifFileType)); + /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType)); + + /* Belt and suspenders, in case the null pointer isn't zero */ + GifFile->SavedImages = NULL; + GifFile->SColorMap = NULL; Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); if (Private == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - close(FileHandle); + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + (void)close(FileHandle); free((char *)GifFile); return NULL; } -#if defined(__MSDOS__) || defined(WINDOWS32) || defined(_OPEN_BINARY) - setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ -#endif /* __MSDOS__ */ +#ifdef _WIN32 + _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ +#endif /* _WIN32 */ f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ -#if defined(__MSDOS__) || defined(WINDOWS32) - setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE); /* And inc. stream - buffer. */ -#endif /* __MSDOS__ */ - - GifFile->Private = (VoidPtr)Private; + /*@-mustfreeonly@*/ + GifFile->Private = (void *)Private; Private->FileHandle = FileHandle; Private->File = f; Private->FileState = FILE_STATE_READ; - Private->Read = 0; /* don't use alternate input method (TVT) */ - GifFile->UserData = 0; /* TVT */ - - /* Lets see if this is a GIF file: */ - if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - _GifError = D_GIF_ERR_READ_FAILED; - fclose(f); + Private->Read = NULL; /* don't use alternate input method (TVT) */ + GifFile->UserData = NULL; /* TVT */ + /*@=mustfreeonly@*/ + + /* Let's see if this is a GIF file: */ + if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { + if (Error != NULL) + *Error = D_GIF_ERR_READ_FAILED; + (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } - /* The GIF Version number is ignored at this time. Maybe we should do - * something more useful with it. */ + /* Check for GIF prefix at start of file */ Buf[GIF_STAMP_LEN] = 0; if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - _GifError = D_GIF_ERR_NOT_GIF_FILE; - fclose(f); + if (Error != NULL) + *Error = D_GIF_ERR_NOT_GIF_FILE; + (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - fclose(f); + (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } - _GifError = 0; + GifFile->Error = 0; + + /* What version of GIF? */ + Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); return GifFile; } -#endif /* _GBA_NO_FILEIO */ - /****************************************************************************** - * GifFileType constructor with user supplied input function (TVT) - *****************************************************************************/ + GifFileType constructor with user supplied input function (TVT) +******************************************************************************/ GifFileType * -DGifOpen(void *userData, - InputFunc readFunc) { - - unsigned char Buf[GIF_STAMP_LEN + 1]; +DGifOpen(void *userData, InputFunc readFunc, int *Error) +{ + char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; return NULL; } memset(GifFile, '\0', sizeof(GifFileType)); + /* Belt and suspenders, in case the null pointer isn't zero */ + GifFile->SavedImages = NULL; + GifFile->SColorMap = NULL; + Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); if (!Private) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; free((char *)GifFile); return NULL; } - GifFile->Private = (VoidPtr)Private; + GifFile->Private = (void *)Private; Private->FileHandle = 0; - Private->File = 0; + Private->File = NULL; Private->FileState = FILE_STATE_READ; Private->Read = readFunc; /* TVT */ GifFile->UserData = userData; /* TVT */ /* Lets see if this is a GIF file: */ - if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - _GifError = D_GIF_ERR_READ_FAILED; + if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { + if (Error != NULL) + *Error = D_GIF_ERR_READ_FAILED; free((char *)Private); free((char *)GifFile); return NULL; } - /* The GIF Version number is ignored at this time. Maybe we should do - * something more useful with it. */ - Buf[GIF_STAMP_LEN] = 0; + /* Check for GIF prefix at start of file */ + Buf[GIF_STAMP_LEN] = '\0'; if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - _GifError = D_GIF_ERR_NOT_GIF_FILE; + if (Error != NULL) + *Error = D_GIF_ERR_NOT_GIF_FILE; free((char *)Private); free((char *)GifFile); return NULL; @@ -220,25 +213,29 @@ DGifOpen(void *userData, return NULL; } - _GifError = 0; + GifFile->Error = 0; + + /* What version of GIF? */ + Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); return GifFile; } /****************************************************************************** - * This routine should be called before any other DGif calls. Note that - * this routine is called automatically from DGif file open routines. - *****************************************************************************/ + This routine should be called before any other DGif calls. Note that + this routine is called automatically from DGif file open routines. +******************************************************************************/ int -DGifGetScreenDesc(GifFileType * GifFile) { - - int i, BitsPerPixel; +DGifGetScreenDesc(GifFileType *GifFile) +{ + int BitsPerPixel; + bool SortFlag; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -248,26 +245,32 @@ DGifGetScreenDesc(GifFileType * GifFile) { return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; + GifFreeMapObject(GifFile->SColorMap); + GifFile->SColorMap = NULL; return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; + SortFlag = (Buf[0] & 0x08) != 0; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; + GifFile->AspectByte = Buf[2]; if (Buf[0] & 0x80) { /* Do we have global color map? */ + int i; - GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); + GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the global color map: */ + GifFile->SColorMap->SortFlag = SortFlag; for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { - FreeMapObject(GifFile->SColorMap); + GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; @@ -282,39 +285,38 @@ DGifGetScreenDesc(GifFileType * GifFile) { } /****************************************************************************** - * This routine should be called before any attempt to read an image. - *****************************************************************************/ + This routine should be called before any attempt to read an image. +******************************************************************************/ int -DGifGetRecordType(GifFileType * GifFile, - GifRecordType * Type) { - +DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type) +{ GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } switch (Buf) { - case ',': + case DESCRIPTOR_INTRODUCER: *Type = IMAGE_DESC_RECORD_TYPE; break; - case '!': + case EXTENSION_INTRODUCER: *Type = EXTENSION_RECORD_TYPE; break; - case ';': + case TERMINATOR_INTRODUCER: *Type = TERMINATE_RECORD_TYPE; break; default: *Type = UNDEFINED_RECORD_TYPE; - _GifError = D_GIF_ERR_WRONG_RECORD; + GifFile->Error = D_GIF_ERR_WRONG_RECORD; return GIF_ERROR; } @@ -322,20 +324,20 @@ DGifGetRecordType(GifFileType * GifFile, } /****************************************************************************** - * This routine should be called before any attempt to read an image. - * Note it is assumed the Image desc. header (',') has been read. - *****************************************************************************/ + This routine should be called before any attempt to read an image. + Note it is assumed the Image desc. header has been read. +******************************************************************************/ int -DGifGetImageDesc(GifFileType * GifFile) { - - int i, BitsPerPixel; +DGifGetImageDesc(GifFileType *GifFile) +{ + unsigned int BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -345,29 +347,34 @@ DGifGetImageDesc(GifFileType * GifFile) { DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Image.ColorMap = NULL; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->Image.Interlace = (Buf[0] & 0x40); - if (Buf[0] & 0x80) { /* Does this image have local color map? */ + GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; - /*** FIXME: Why do we check both of these in order to do this? - * Why do we have both Image and SavedImages? */ - if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL) - FreeMapObject(GifFile->Image.ColorMap); + /* Setup the colormap */ + if (GifFile->Image.ColorMap) { + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Image.ColorMap = NULL; + } + /* Does this image have local color map? */ + if (Buf[0] & 0x80) { + unsigned int i; - GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); + GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the image local color map: */ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { - FreeMapObject(GifFile->Image.ColorMap); - _GifError = D_GIF_ERR_READ_FAILED; + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Error = D_GIF_ERR_READ_FAILED; GifFile->Image.ColorMap = NULL; return GIF_ERROR; } @@ -375,22 +382,19 @@ DGifGetImageDesc(GifFileType * GifFile) { GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } - } else if (GifFile->Image.ColorMap) { - FreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; } if (GifFile->SavedImages) { if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { if ((GifFile->SavedImages = (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } @@ -398,11 +402,11 @@ DGifGetImageDesc(GifFileType * GifFile) { sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = MakeMapObject( + sp->ImageDesc.ColorMap = GifMakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } @@ -415,45 +419,42 @@ DGifGetImageDesc(GifFileType * GifFile) { Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; - DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ + /* Reset decompress algorithm parameters. */ + (void)DGifSetupDecompress(GifFile); return GIF_OK; } /****************************************************************************** - * Get one full scanned line (Line) of length LineLen from GIF file. - *****************************************************************************/ + Get one full scanned line (Line) of length LineLen from GIF file. +******************************************************************************/ int -DGifGetLine(GifFileType * GifFile, - GifPixelType * Line, - int LineLen) { - +DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) +{ GifByteType *Dummy; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (!LineLen) LineLen = GifFile->Image.Width; -#if defined(__MSDOS__) || defined(WINDOWS32) || defined(__GNUC__) if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { -#else - if ((Private->PixelCount -= LineLen) > 0xffff0000) { -#endif /* __MSDOS__ */ - _GifError = D_GIF_ERR_DATA_TOO_BIG; + GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { if (Private->PixelCount == 0) { - /* We probably would not be called any more, so lets clean - * everything before we return: need to flush out all rest of - * image until empty block (size 0) detected. We use GetCodeNext. */ + /* We probably won't be called any more, so let's clean up + * everything before we return: need to flush out all the + * rest of image until an empty block (size 0) + * detected. We use GetCodeNext. + */ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) return GIF_ERROR; @@ -465,35 +466,32 @@ DGifGetLine(GifFileType * GifFile, } /****************************************************************************** - * Put one pixel (Pixel) into GIF file. - *****************************************************************************/ + Put one pixel (Pixel) into GIF file. +******************************************************************************/ int -DGifGetPixel(GifFileType * GifFile, - GifPixelType Pixel) { - +DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) +{ GifByteType *Dummy; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } -#if defined(__MSDOS__) || defined(WINDOWS32) || defined(__GNUC__) if (--Private->PixelCount > 0xffff0000UL) -#else - if (--Private->PixelCount > 0xffff0000) -#endif /* __MSDOS__ */ { - _GifError = D_GIF_ERR_DATA_TOO_BIG; + GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { if (Private->PixelCount == 0) { - /* We probably would not be called any more, so lets clean - * everything before we return: need to flush out all rest of - * image until empty block (size 0) detected. We use GetCodeNext. */ + /* We probably won't be called any more, so let's clean up + * everything before we return: need to flush out all the + * rest of image until an empty block (size 0) + * detected. We use GetCodeNext. + */ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) return GIF_ERROR; @@ -505,28 +503,26 @@ DGifGetPixel(GifFileType * GifFile, } /****************************************************************************** - * Get an extension block (see GIF manual) from gif file. This routine only - * returns the first data block, and DGifGetExtensionNext should be called - * after this one until NULL extension is returned. - * The Extension should NOT be freed by the user (not dynamically allocated). - * Note it is assumed the Extension desc. header ('!') has been read. - *****************************************************************************/ + Get an extension block (see GIF manual) from GIF file. This routine only + returns the first data block, and DGifGetExtensionNext should be called + after this one until NULL extension is returned. + The Extension should NOT be freed by the user (not dynamically allocated). + Note it is assumed the Extension description header has been read. +******************************************************************************/ int -DGifGetExtension(GifFileType * GifFile, - int *ExtCode, - GifByteType ** Extension) { - +DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) +{ GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *ExtCode = Buf; @@ -535,26 +531,26 @@ DGifGetExtension(GifFileType * GifFile, } /****************************************************************************** - * Get a following extension block (see GIF manual) from gif file. This - * routine should be called until NULL Extension is returned. - * The Extension should NOT be freed by the user (not dynamically allocated). - *****************************************************************************/ + Get a following extension block (see GIF manual) from GIF file. This + routine should be called until NULL Extension is returned. + The Extension should NOT be freed by the user (not dynamically allocated). +******************************************************************************/ int -DGifGetExtensionNext(GifFileType * GifFile, - GifByteType ** Extension) { - +DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension) +{ GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } if (Buf > 0) { *Extension = Private->Buf; /* Use private unused buffer. */ (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data] */ if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else @@ -564,91 +560,140 @@ DGifGetExtensionNext(GifFileType * GifFile, } /****************************************************************************** - * This routine should be called last, to close the GIF file. - *****************************************************************************/ -int -DGifCloseFile(GifFileType * GifFile) { - - GifFilePrivateType *Private; - FILE *File; + Extract a Graphics Control Block from raw extension data +******************************************************************************/ + +int DGifExtensionToGCB(const size_t GifExtensionLength, + const GifByteType *GifExtension, + GraphicsControlBlock *GCB) +{ + if (GifExtensionLength != 4) { + return GIF_ERROR; + } - if (GifFile == NULL) - return GIF_ERROR; + GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; + GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; + GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); + if (GifExtension[0] & 0x01) + GCB->TransparentColor = (int)GifExtension[3]; + else + GCB->TransparentColor = NO_TRANSPARENT_COLOR; - Private = (GifFilePrivateType *) GifFile->Private; + return GIF_OK; +} - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; +/****************************************************************************** + Extract the Graphics Control Block for a saved image, if it exists. +******************************************************************************/ + +int DGifSavedExtensionToGCB(GifFileType *GifFile, + int ImageIndex, GraphicsControlBlock *GCB) +{ + int i; + + if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) + return GIF_ERROR; + + GCB->DisposalMode = DISPOSAL_UNSPECIFIED; + GCB->UserInputFlag = false; + GCB->DelayTime = 0; + GCB->TransparentColor = NO_TRANSPARENT_COLOR; + + for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) { + ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; + if (ep->Function == GRAPHICS_EXT_FUNC_CODE) + return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB); } - File = Private->File; + return GIF_ERROR; +} + +/****************************************************************************** + This routine should be called last, to close the GIF file. +******************************************************************************/ +int +DGifCloseFile(GifFileType *GifFile) +{ + GifFilePrivateType *Private; + + if (GifFile == NULL || GifFile->Private == NULL) + return GIF_ERROR; if (GifFile->Image.ColorMap) { - FreeMapObject(GifFile->Image.ColorMap); + GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } if (GifFile->SColorMap) { - FreeMapObject(GifFile->SColorMap); + GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; } - if (Private) { - free((char *)Private); - Private = NULL; - } - if (GifFile->SavedImages) { - FreeSavedImages(GifFile); + GifFreeSavedImages(GifFile); GifFile->SavedImages = NULL; } - free(GifFile); + GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks); - if (File && (fclose(File) != 0)) { - _GifError = D_GIF_ERR_CLOSE_FAILED; + Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + if (Private->File && (fclose(Private->File) != 0)) { + GifFile->Error = D_GIF_ERR_CLOSE_FAILED; return GIF_ERROR; } + + free((char *)GifFile->Private); + + /* + * Without the #ifndef, we get spurious warnings because Coverity mistakenly + * thinks the GIF structure is freed on an error return. + */ +#ifndef __COVERITY__ + free(GifFile); +#endif /* __COVERITY__ */ + return GIF_OK; } /****************************************************************************** - * Get 2 bytes (word) from the given file: - *****************************************************************************/ + Get 2 bytes (word) from the given file: +******************************************************************************/ static int -DGifGetWord(GifFileType * GifFile, - GifWord *Word) { - +DGifGetWord(GifFileType *GifFile, GifWord *Word) +{ unsigned char c[2]; if (READ(GifFile, c, 2) != 2) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } - *Word = (((unsigned int)c[1]) << 8) + c[0]; + *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]); return GIF_OK; } /****************************************************************************** - * Get the image code in compressed form. This routine can be called if the - * information needed to be piped out as is. Obviously this is much faster - * than decoding and encoding again. This routine should be followed by calls - * to DGifGetCodeNext, until NULL block is returned. - * The block should NOT be freed by the user (not dynamically allocated). - *****************************************************************************/ + Get the image code in compressed form. This routine can be called if the + information needed to be piped out as is. Obviously this is much faster + than decoding and encoding again. This routine should be followed by calls + to DGifGetCodeNext, until NULL block is returned. + The block should NOT be freed by the user (not dynamically allocated). +******************************************************************************/ int -DGifGetCode(GifFileType * GifFile, - int *CodeSize, - GifByteType ** CodeBlock) { - +DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) +{ GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -658,27 +703,29 @@ DGifGetCode(GifFileType * GifFile, } /****************************************************************************** - * Continue to get the image code in compressed form. This routine should be - * called until NULL block is returned. - * The block should NOT be freed by the user (not dynamically allocated). - *****************************************************************************/ + Continue to get the image code in compressed form. This routine should be + called until NULL block is returned. + The block should NOT be freed by the user (not dynamically allocated). +******************************************************************************/ int -DGifGetCodeNext(GifFileType * GifFile, - GifByteType ** CodeBlock) { - +DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) +{ GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + /* coverity[tainted_data_argument] */ if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } + /* coverity[lower_bounds] */ if (Buf > 0) { *CodeBlock = Private->Buf; /* Use private unused buffer. */ (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data] */ if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else { @@ -691,11 +738,11 @@ DGifGetCodeNext(GifFileType * GifFile, } /****************************************************************************** - * Setup the LZ decompression for this image: - *****************************************************************************/ + Setup the LZ decompression for this image: +******************************************************************************/ static int -DGifSetupDecompress(GifFileType * GifFile) { - +DGifSetupDecompress(GifFileType *GifFile) +{ int i, BitsPerPixel; GifByteType CodeSize; GifPrefixType *Prefix; @@ -724,16 +771,14 @@ DGifSetupDecompress(GifFileType * GifFile) { } /****************************************************************************** - * The LZ decompression routine: - * This version decompress the given gif file into Line of length LineLen. - * This routine can be called few times (one per scan line, for example), in - * order the complete the whole image. - *****************************************************************************/ + The LZ decompression routine: + This version decompress the given GIF file into Line of length LineLen. + This routine can be called few times (one per scan line, for example), in + order the complete the whole image. +******************************************************************************/ static int -DGifDecompressLine(GifFileType * GifFile, - GifPixelType * Line, - int LineLen) { - +DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) +{ int i = 0; int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; GifByteType *Stack, *Suffix; @@ -753,7 +798,7 @@ DGifDecompressLine(GifFileType * GifFile, } if (StackPtr != 0) { - /* Let pop the stack off before continueing to read the gif file: */ + /* Let pop the stack off before continueing to read the GIF file: */ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } @@ -766,11 +811,8 @@ DGifDecompressLine(GifFileType * GifFile, /* Note however that usually we will not be here as we will stop * decoding as soon as we got all the pixel, or EOF code will * not be read at all, and DGifGetLine/Pixel clean everything. */ - if (i != LineLen - 1 || Private->PixelCount != 0) { - _GifError = D_GIF_ERR_EOF_TOO_SOON; - return GIF_ERROR; - } - i++; + GifFile->Error = D_GIF_ERR_EOF_TOO_SOON; + return GIF_ERROR; } else if (CrntCode == ClearCode) { /* We need to start over again: */ for (j = 0; j <= LZ_MAX_CODE; j++) @@ -803,25 +845,23 @@ DGifDecompressLine(GifFileType * GifFile, LastCode, ClearCode); } else { - _GifError = D_GIF_ERR_IMAGE_DEFECT; + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } } else CrntPrefix = CrntCode; - /* Now (if image is O.K.) we should not get an NO_SUCH_CODE - * During the trace. As we might loop forever, in case of - * defective image, we count the number of loops we trace - * and stop if we got LZ_MAX_CODE. obviously we can not - * loop more than that. */ - j = 0; - while (j++ <= LZ_MAX_CODE && + /* Now (if image is O.K.) we should not get a NO_SUCH_CODE + * during the trace. As we might loop forever, in case of + * defective image, we use StackPtr as loop counter and stop + * before overflowing Stack[]. */ + while (StackPtr < LZ_MAX_CODE && CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) { Stack[StackPtr++] = Suffix[CrntPrefix]; CrntPrefix = Prefix[CrntPrefix]; } - if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { - _GifError = D_GIF_ERR_IMAGE_DEFECT; + if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } /* Push the last character on stack: */ @@ -831,7 +871,7 @@ DGifDecompressLine(GifFileType * GifFile, while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } - if (LastCode != NO_SUCH_CODE) { + if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { Prefix[Private->RunningCode - 2] = LastCode; if (CrntCode == Private->RunningCode - 2) { @@ -857,16 +897,14 @@ DGifDecompressLine(GifFileType * GifFile, } /****************************************************************************** - * Routine to trace the Prefixes linked list until we get a prefix which is - * not code, but a pixel value (less than ClearCode). Returns that pixel value. - * If image is defective, we might loop here forever, so we limit the loops to - * the maximum possible if image O.k. - LZ_MAX_CODE times. - *****************************************************************************/ + Routine to trace the Prefixes linked list until we get a prefix which is + not code, but a pixel value (less than ClearCode). Returns that pixel value. + If image is defective, we might loop here forever, so we limit the loops to + the maximum possible if image O.k. - LZ_MAX_CODE times. +******************************************************************************/ static int -DGifGetPrefixChar(GifPrefixType *Prefix, - int Code, - int ClearCode) { - +DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode) +{ int i = 0; while (Code > ClearCode && i++ <= LZ_MAX_CODE) { @@ -879,19 +917,18 @@ DGifGetPrefixChar(GifPrefixType *Prefix, } /****************************************************************************** - * Interface for accessing the LZ codes directly. Set Code to the real code - * (12bits), or to -1 if EOF code is returned. - *****************************************************************************/ + Interface for accessing the LZ codes directly. Set Code to the real code + (12bits), or to -1 if EOF code is returned. +******************************************************************************/ int -DGifGetLZCodes(GifFileType * GifFile, - int *Code) { - +DGifGetLZCodes(GifFileType *GifFile, int *Code) +{ GifByteType *CodeBlock; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -917,27 +954,28 @@ DGifGetLZCodes(GifFileType * GifFile, } /****************************************************************************** - * The LZ decompression input routine: - * This routine is responsable for the decompression of the bit stream from - * 8 bits (bytes) packets, into the real codes. - * Returns GIF_OK if read succesfully. - *****************************************************************************/ + The LZ decompression input routine: + This routine is responsable for the decompression of the bit stream from + 8 bits (bytes) packets, into the real codes. + Returns GIF_OK if read successfully. +******************************************************************************/ static int -DGifDecompressInput(GifFileType * GifFile, - int *Code) { - +DGifDecompressInput(GifFileType *GifFile, int *Code) +{ + static const unsigned short CodeMasks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000f, 0x001f, 0x003f, 0x007f, + 0x00ff, 0x01ff, 0x03ff, 0x07ff, + 0x0fff + }; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; GifByteType NextByte; - static unsigned short CodeMasks[] = { - 0x0000, 0x0001, 0x0003, 0x0007, - 0x000f, 0x001f, 0x003f, 0x007f, - 0x00ff, 0x01ff, 0x03ff, 0x07ff, - 0x0fff - }; + /* The image can't contain more than LZ_BITS per code. */ if (Private->RunningBits > LZ_BITS) { - _GifError = D_GIF_ERR_IMAGE_DEFECT; + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } @@ -947,7 +985,7 @@ DGifDecompressInput(GifFileType * GifFile, return GIF_ERROR; } Private->CrntShiftDWord |= - ((unsigned long)NextByte) << Private->CrntShiftState; + ((unsigned long)NextByte) << Private->CrntShiftState; Private->CrntShiftState += 8; } *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; @@ -961,8 +999,8 @@ DGifDecompressInput(GifFileType * GifFile, * keep using the table as it is, don't increment Private->RunningCode. */ if (Private->RunningCode < LZ_MAX_CODE + 2 && - ++Private->RunningCode > Private->MaxCode1 && - Private->RunningBits < LZ_BITS) { + ++Private->RunningCode > Private->MaxCode1 && + Private->RunningBits < LZ_BITS) { Private->MaxCode1 <<= 1; Private->RunningBits++; } @@ -970,20 +1008,18 @@ DGifDecompressInput(GifFileType * GifFile, } /****************************************************************************** - * This routines read one gif data block at a time and buffers it internally - * so that the decompression routine could access it. - * The routine returns the next byte from its internal buffer (or read next - * block in if buffer empty) and returns GIF_OK if succesful. - *****************************************************************************/ + This routines read one GIF data block at a time and buffers it internally + so that the decompression routine could access it. + The routine returns the next byte from its internal buffer (or read next + block in if buffer empty) and returns GIF_OK if succesful. +******************************************************************************/ static int -DGifBufferedInput(GifFileType * GifFile, - GifByteType * Buf, - GifByteType * NextByte) { - +DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) +{ if (Buf[0] == 0) { /* Needs to read the next buffer - this one is empty: */ if (READ(GifFile, Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } /* There shouldn't be any empty data blocks here as the LZW spec @@ -991,11 +1027,19 @@ DGifBufferedInput(GifFileType * GifFile, * shouldn't be inside this routine at that point. */ if (Buf[0] == 0) { - _GifError = D_GIF_ERR_IMAGE_DEFECT; + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; + } + /* There shouldn't be any empty data blocks here as the LZW spec + * says the LZW termination code should come first. Therefore we + * shouldn't be inside this routine at that point. + */ + if (Buf[0] == 0) { + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *NextByte = Buf[1]; @@ -1008,24 +1052,23 @@ DGifBufferedInput(GifFileType * GifFile, return GIF_OK; } -#ifndef _GBA_NO_FILEIO /****************************************************************************** - * This routine reads an entire GIF into core, hanging all its state info off - * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() - * first to initialize I/O. Its inverse is EGifSpew(). - ******************************************************************************/ + This routine reads an entire GIF into core, hanging all its state info off + the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() + first to initialize I/O. Its inverse is EGifSpew(). +*******************************************************************************/ int -DGifSlurp(GifFileType * GifFile) { - - int ImageSize; +DGifSlurp(GifFileType *GifFile) +{ + size_t ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; - SavedImage temp_save; + int ExtFunction; - temp_save.ExtensionBlocks = NULL; - temp_save.ExtensionBlockCount = 0; + GifFile->ExtensionBlocks = NULL; + GifFile->ExtensionBlockCount = 0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) @@ -1037,44 +1080,75 @@ DGifSlurp(GifFileType * GifFile) { return (GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; + /* Allocate memory for the image */ + if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 && + sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { + return GIF_ERROR; + } ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; + if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { + return GIF_ERROR; + } sp->RasterBits = (unsigned char *)malloc(ImageSize * - sizeof(GifPixelType)); + sizeof(GifPixelType)); + if (sp->RasterBits == NULL) { return GIF_ERROR; } - if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) == - GIF_ERROR) - return (GIF_ERROR); - if (temp_save.ExtensionBlocks) { - sp->ExtensionBlocks = temp_save.ExtensionBlocks; - sp->ExtensionBlockCount = temp_save.ExtensionBlockCount; - - temp_save.ExtensionBlocks = NULL; - temp_save.ExtensionBlockCount = 0; - /* FIXME: The following is wrong. It is left in only for - * backwards compatibility. Someday it should go away. Use - * the sp->ExtensionBlocks->Function variable instead. */ - sp->Function = sp->ExtensionBlocks[0].Function; + if (sp->ImageDesc.Interlace) { + int i, j; + /* + * The way an interlaced image should be read - + * offsets and jumps... + */ + int InterlacedOffset[] = { 0, 4, 2, 1 }; + int InterlacedJumps[] = { 8, 8, 4, 2 }; + /* Need to perform 4 passes on the image */ + for (i = 0; i < 4; i++) + for (j = InterlacedOffset[i]; + j < sp->ImageDesc.Height; + j += InterlacedJumps[i]) { + if (DGifGetLine(GifFile, + sp->RasterBits+j*sp->ImageDesc.Width, + sp->ImageDesc.Width) == GIF_ERROR) + return GIF_ERROR; + } + } + else { + if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) + return (GIF_ERROR); + } + + if (GifFile->ExtensionBlocks) { + sp->ExtensionBlocks = GifFile->ExtensionBlocks; + sp->ExtensionBlockCount = GifFile->ExtensionBlockCount; + + GifFile->ExtensionBlocks = NULL; + GifFile->ExtensionBlockCount = 0; } break; case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) == - GIF_ERROR) + if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR) return (GIF_ERROR); + /* Create an extension block with our data */ + if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, + ExtFunction, ExtData[0], &ExtData[1]) + == GIF_ERROR) + return (GIF_ERROR); while (ExtData != NULL) { - - /* Create an extension block with our data */ - if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1]) - == GIF_ERROR) - return (GIF_ERROR); - if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); - temp_save.Function = 0; + /* Continue the extension block */ + if (ExtData != NULL) + if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, + CONTINUE_EXT_FUNC_CODE, + ExtData[0], &ExtData[1]) == GIF_ERROR) + return (GIF_ERROR); } break; @@ -1086,13 +1160,7 @@ DGifSlurp(GifFileType * GifFile) { } } while (RecordType != TERMINATE_RECORD_TYPE); - /* Just in case the Gif has an extension block without an associated - * image... (Should we save this into a savefile structure with no image - * instead? Have to check if the present writing code can handle that as - * well.... */ - if (temp_save.ExtensionBlocks) - FreeExtension(&temp_save); - return (GIF_OK); } -#endif /* _GBA_NO_FILEIO */ + +/* end */ diff --git a/gif_err.c b/gif_err.c index ea977bd..8de72a0 100644 --- a/gif_err.c +++ b/gif_err.c @@ -1,64 +1,43 @@ /***************************************************************************** - * "Gif-Lib" - Yet another gif library. - * - * Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 - ***************************************************************************** - * Handle error reporting for the GIF library. - ***************************************************************************** - * History: - * 17 Jun 89 - Version 1.0 by Gershon Elber. - ****************************************************************************/ -#ifdef HAVE_CONFIG_H -#include -#endif +gif_err.c - handle error reporting for the GIF library. -#include -#include "gif_lib.h" - -int _GifError = 0; - -/***************************************************************************** - * Return the last GIF error (0 if none) and reset the error. - ****************************************************************************/ -int -GifLastError(void) { - int i = _GifError; +****************************************************************************/ - _GifError = 0; +#include - return i; -} -#ifndef _GBA_NO_FILEIO +#include "gif_lib.h" +#include "gif_lib_private.h" /***************************************************************************** - * Print the last GIF error to stderr. - ****************************************************************************/ -void -PrintGifError(void) { + Return a string description of the last GIF error +*****************************************************************************/ +char * +GifErrorString(int ErrorCode) +{ char *Err; - switch (_GifError) { + switch (ErrorCode) { case E_GIF_ERR_OPEN_FAILED: Err = "Failed to open given file"; break; case E_GIF_ERR_WRITE_FAILED: - Err = "Failed to Write to given file"; + Err = "Failed to write to given file"; break; case E_GIF_ERR_HAS_SCRN_DSCR: - Err = "Screen Descriptor already been set"; + Err = "Screen descriptor has already been set"; break; case E_GIF_ERR_HAS_IMAG_DSCR: - Err = "Image Descriptor is still active"; + Err = "Image descriptor is still active"; break; case E_GIF_ERR_NO_COLOR_MAP: - Err = "Neither Global Nor Local color map"; + Err = "Neither global nor local color map"; break; case E_GIF_ERR_DATA_TOO_BIG: - Err = "#Pixels bigger than Width * Height"; + Err = "Number of pixels bigger than width * height"; break; case E_GIF_ERR_NOT_ENOUGH_MEM: - Err = "Fail to allocate required memory"; + Err = "Failed to allocate required memory"; break; case E_GIF_ERR_DISK_IS_FULL: Err = "Write failed (disk full?)"; @@ -73,28 +52,28 @@ PrintGifError(void) { Err = "Failed to open given file"; break; case D_GIF_ERR_READ_FAILED: - Err = "Failed to Read from given file"; + Err = "Failed to read from given file"; break; case D_GIF_ERR_NOT_GIF_FILE: - Err = "Given file is NOT GIF file"; + Err = "Data is not in GIF format"; break; case D_GIF_ERR_NO_SCRN_DSCR: - Err = "No Screen Descriptor detected"; + Err = "No screen descriptor detected"; break; case D_GIF_ERR_NO_IMAG_DSCR: Err = "No Image Descriptor detected"; break; case D_GIF_ERR_NO_COLOR_MAP: - Err = "Neither Global Nor Local color map"; + Err = "Neither global nor local color map"; break; case D_GIF_ERR_WRONG_RECORD: Err = "Wrong record type detected"; break; case D_GIF_ERR_DATA_TOO_BIG: - Err = "#Pixels bigger than Width * Height"; + Err = "Number of pixels bigger than width * height"; break; case D_GIF_ERR_NOT_ENOUGH_MEM: - Err = "Fail to allocate required memory"; + Err = "Failed to allocate required memory"; break; case D_GIF_ERR_CLOSE_FAILED: Err = "Failed to close given file"; @@ -106,15 +85,13 @@ PrintGifError(void) { Err = "Image is defective, decoding aborted"; break; case D_GIF_ERR_EOF_TOO_SOON: - Err = "Image EOF detected, before image complete"; + Err = "Image EOF detected before image complete"; break; default: Err = NULL; break; } - if (Err != NULL) - fprintf(stderr, "\nGIF-LIB error: %s.\n", Err); - else - fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError); + return Err; } -#endif /* _GBA_NO_FILEIO */ + +/* end */ diff --git a/gif_hash.h b/gif_hash.h index 3e23ff3..ac20a43 100644 --- a/gif_hash.h +++ b/gif_hash.h @@ -1,36 +1,14 @@ /****************************************************************************** -* Declarations, global to other of the GIF-HASH.C module. * -* * -* Written by Gershon Elber, Jun 1989 * -******************************************************************************* -* History: * -* 14 Jun 89 - Version 1.0 by Gershon Elber. * + +gif_hash.h - magfic constants and declarations for GIF LZW + ******************************************************************************/ #ifndef _GIF_HASH_H_ #define _GIF_HASH_H_ -#ifdef HAVE_CONFIG_H -#include -#endif - -/* Find a thirty-two bit int type */ -#ifdef HAVE_STDINT_H -#include -#endif -#ifdef HAVE_INTTYPES_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_UNISTD_H #include -#endif - -#ifdef HAVE_BASETSD_H -#include -#endif +#include #define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */ #define HT_KEY_MASK 0x1FFF /* 13bits keys */ @@ -48,12 +26,14 @@ #define HT_PUT_CODE(l) (l & 0x0FFF) typedef struct GifHashTableType { - UINT32 HTable[HT_SIZE]; + uint32_t HTable[HT_SIZE]; } GifHashTableType; GifHashTableType *_InitHashTable(void); void _ClearHashTable(GifHashTableType *HashTable); -void _InsertHashTable(GifHashTableType *HashTable, UINT32 Key, int Code); -int _ExistsHashTable(GifHashTableType *HashTable, UINT32 Key); +void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code); +int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key); #endif /* _GIF_HASH_H_ */ + +/* end */ diff --git a/gif_lib.h b/gif_lib.h index f0cf858..23df861 100644 --- a/gif_lib.h +++ b/gif_lib.h @@ -1,17 +1,8 @@ /****************************************************************************** - * In order to make life a little bit easier when using the GIF file format, - * this library was written, and which does all the dirty work... - * - * Written by Gershon Elber, Jun. 1989 - * Hacks by Eric S. Raymond, Sep. 1992 - ****************************************************************************** - * History: - * 14 Jun 89 - Version 1.0 by Gershon Elber. - * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names) - * 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to suoport GIF slurp) - * 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support) - * 17 Dec 98 - Version 4.0 by Toshio Kuratomi (Fix extension writing code) - *****************************************************************************/ + +gif_lib.h - service library for decoding and encoding GIF images + +*****************************************************************************/ #ifndef _GIF_LIB_H_ #define _GIF_LIB_H_ 1 @@ -20,21 +11,14 @@ extern "C" { #endif /* __cplusplus */ -#define GIF_LIB_VERSION " Version 4.1, " +#define GIFLIB_MAJOR 5 +#define GIFLIB_MINOR 0 +#define GIFLIB_RELEASE 4 #define GIF_ERROR 0 #define GIF_OK 1 -#ifndef TRUE -#define TRUE 1 -#endif /* TRUE */ -#ifndef FALSE -#define FALSE 0 -#endif /* FALSE */ - -#ifndef NULL -#define NULL 0 -#endif /* NULL */ +#include #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 @@ -42,28 +26,11 @@ extern "C" { #define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */ #define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */ -#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */ - -typedef int GifBooleanType; typedef unsigned char GifPixelType; typedef unsigned char *GifRowType; typedef unsigned char GifByteType; -#ifdef _GBA_OPTMEM - typedef unsigned short GifPrefixType; - typedef short GifWord; -#else - typedef unsigned int GifPrefixType; - typedef int GifWord; -#endif - -#define GIF_MESSAGE(Msg) fprintf(stderr, "\n%s: %s\n", PROGRAM_NAME, Msg) -#define GIF_EXIT(Msg) { GIF_MESSAGE(Msg); exit(-3); } - -#ifdef SYSV -#define VoidPtr char * -#else -#define VoidPtr void * -#endif /* SYSV */ +typedef unsigned int GifPrefixType; +typedef int GifWord; typedef struct GifColorType { GifByteType Red, Green, Blue; @@ -72,27 +39,52 @@ typedef struct GifColorType { typedef struct ColorMapObject { int ColorCount; int BitsPerPixel; + bool SortFlag; GifColorType *Colors; /* on malloc(3) heap */ } ColorMapObject; typedef struct GifImageDesc { - GifWord Left, Top, Width, Height, /* Current image dimensions. */ - Interlace; /* Sequential/Interlaced lines. */ - ColorMapObject *ColorMap; /* The local color map */ + GifWord Left, Top, Width, Height; /* Current image dimensions. */ + bool Interlace; /* Sequential/Interlaced lines. */ + ColorMapObject *ColorMap; /* The local color map */ } GifImageDesc; +typedef struct ExtensionBlock { + int ByteCount; + GifByteType *Bytes; /* on malloc(3) heap */ + int Function; /* The block function code */ +#define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */ +#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ +#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */ +#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ +#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */ +} ExtensionBlock; + +typedef struct SavedImage { + GifImageDesc ImageDesc; + GifByteType *RasterBits; /* on malloc(3) heap */ + int ExtensionBlockCount; /* Count of extensions before image */ + ExtensionBlock *ExtensionBlocks; /* Extensions before image */ +} SavedImage; + typedef struct GifFileType { - GifWord SWidth, SHeight, /* Screen dimensions. */ - SColorResolution, /* How many colors can we generate? */ - SBackGroundColor; /* I hope you understand this one... */ - ColorMapObject *SColorMap; /* NULL if not exists. */ - int ImageCount; /* Number of current image */ - GifImageDesc Image; /* Block describing current image */ - struct SavedImage *SavedImages; /* Use this to accumulate file state */ - VoidPtr UserData; /* hook to attach user data (TVT) */ - VoidPtr Private; /* Don't mess with this! */ + GifWord SWidth, SHeight; /* Size of virtual canvas */ + GifWord SColorResolution; /* How many colors can we generate? */ + GifWord SBackGroundColor; /* Background color for virtual canvas */ + GifByteType AspectByte; /* Used to compute pixel aspect ratio */ + ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ + int ImageCount; /* Number of current image (both APIs) */ + GifImageDesc Image; /* Current image (low-level API) */ + SavedImage *SavedImages; /* Image sequence (high-level API) */ + int ExtensionBlockCount; /* Count extensions past last image */ + ExtensionBlock *ExtensionBlocks; /* Extensions past last image */ + int Error; /* Last error condition reported */ + void *UserData; /* hook to attach user data (TVT) */ + void *Private; /* Don't mess with this! */ } GifFileType; +#define GIF_ASPECT_RATIO(n) ((n)+15.0/64.0) + typedef enum { UNDEFINED_RECORD_TYPE, SCREEN_DESC_RECORD_TYPE, @@ -101,68 +93,41 @@ typedef enum { TERMINATE_RECORD_TYPE /* Begin with ';' */ } GifRecordType; -/* DumpScreen2Gif routine constants identify type of window/screen to dump. - * Note all values below 1000 are reserved for the IBMPC different display - * devices (it has many!) and are compatible with the numbering TC2.0 - * (Turbo C 2.0 compiler for IBM PC) gives to these devices. - */ -typedef enum { - GIF_DUMP_SGI_WINDOW = 1000, - GIF_DUMP_X_WINDOW = 1001 -} GifScreenDumpType; - /* func type to read gif data from arbitrary sources (TVT) */ typedef int (*InputFunc) (GifFileType *, GifByteType *, int); -/* func type to write gif data ro arbitrary targets. +/* func type to write gif data to arbitrary targets. * Returns count of bytes written. (MRB) */ typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int); /****************************************************************************** - * GIF89 extension function codes + GIF89 structures ******************************************************************************/ -#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ -#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control */ -#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ -#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */ +typedef struct GraphicsControlBlock { + int DisposalMode; +#define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */ +#define DISPOSE_DO_NOT 1 /* Leave image in place */ +#define DISPOSE_BACKGROUND 2 /* Set area too background color */ +#define DISPOSE_PREVIOUS 3 /* Restore to previous content */ + bool UserInputFlag; /* User confirmation required before disposal */ + int DelayTime; /* pre-display delay in 0.01sec units */ + int TransparentColor; /* Palette index for transparency, -1 if none */ +#define NO_TRANSPARENT_COLOR -1 +} GraphicsControlBlock; /****************************************************************************** - * O.K., here are the routines one can access in order to encode GIF file: - * (GIF_LIB file EGIF_LIB.C). + GIF encoding routines ******************************************************************************/ +/* Main entry points */ GifFileType *EGifOpenFileName(const char *GifFileName, - int GifTestExistance); -GifFileType *EGifOpenFileHandle(int GifFileHandle); -GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc); - + const bool GifTestExistence, int *Error); +GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error); +GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error); int EGifSpew(GifFileType * GifFile); -void EGifSetGifVersion(const char *Version); -int EGifPutScreenDesc(GifFileType * GifFile, - int GifWidth, int GifHeight, int GifColorRes, - int GifBackGround, - const ColorMapObject * GifColorMap); -int EGifPutImageDesc(GifFileType * GifFile, int GifLeft, int GifTop, - int Width, int GifHeight, int GifInterlace, - const ColorMapObject * GifColorMap); -int EGifPutLine(GifFileType * GifFile, GifPixelType * GifLine, - int GifLineLen); -int EGifPutPixel(GifFileType * GifFile, GifPixelType GifPixel); -int EGifPutComment(GifFileType * GifFile, const char *GifComment); -int EGifPutExtensionFirst(GifFileType * GifFile, int GifExtCode, - int GifExtLen, const VoidPtr GifExtension); -int EGifPutExtensionNext(GifFileType * GifFile, int GifExtCode, - int GifExtLen, const VoidPtr GifExtension); -int EGifPutExtensionLast(GifFileType * GifFile, int GifExtCode, - int GifExtLen, const VoidPtr GifExtension); -int EGifPutExtension(GifFileType * GifFile, int GifExtCode, int GifExtLen, - const VoidPtr GifExtension); -int EGifPutCode(GifFileType * GifFile, int GifCodeSize, - const GifByteType * GifCodeBlock); -int EGifPutCodeNext(GifFileType * GifFile, - const GifByteType * GifCodeBlock); +char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */ int EGifCloseFile(GifFileType * GifFile); #define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ @@ -176,30 +141,43 @@ int EGifCloseFile(GifFileType * GifFile); #define E_GIF_ERR_CLOSE_FAILED 9 #define E_GIF_ERR_NOT_WRITEABLE 10 +/* These are legacy. You probably do not want to call them directly */ +int EGifPutScreenDesc(GifFileType *GifFile, + const int GifWidth, const int GifHeight, + const int GifColorRes, + const int GifBackGround, + const ColorMapObject *GifColorMap); +int EGifPutImageDesc(GifFileType *GifFile, + const int GifLeft, const int GifTop, + const int GifWidth, const int GifHeight, + const bool GifInterlace, + const ColorMapObject *GifColorMap); +void EGifSetGifVersion(GifFileType *GifFile, const bool gif89); +int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, + int GifLineLen); +int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel); +int EGifPutComment(GifFileType *GifFile, const char *GifComment); +int EGifPutExtensionLeader(GifFileType *GifFile, const int GifExtCode); +int EGifPutExtensionBlock(GifFileType *GifFile, + const int GifExtLen, const void *GifExtension); +int EGifPutExtensionTrailer(GifFileType *GifFile); +int EGifPutExtension(GifFileType *GifFile, const int GifExtCode, + const int GifExtLen, + const void *GifExtension); +int EGifPutCode(GifFileType *GifFile, int GifCodeSize, + const GifByteType *GifCodeBlock); +int EGifPutCodeNext(GifFileType *GifFile, + const GifByteType *GifCodeBlock); + /****************************************************************************** - * O.K., here are the routines one can access in order to decode GIF file: - * (GIF_LIB file DGIF_LIB.C). - *****************************************************************************/ -#ifndef _GBA_NO_FILEIO -GifFileType *DGifOpenFileName(const char *GifFileName); -GifFileType *DGifOpenFileHandle(int GifFileHandle); + GIF decoding routines +******************************************************************************/ + +/* Main entry points */ +GifFileType *DGifOpenFileName(const char *GifFileName, int *Error); +GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error); int DGifSlurp(GifFileType * GifFile); -#endif /* _GBA_NO_FILEIO */ -GifFileType *DGifOpen(void *userPtr, InputFunc readFunc); /* new one - * (TVT) */ -int DGifGetScreenDesc(GifFileType * GifFile); -int DGifGetRecordType(GifFileType * GifFile, GifRecordType * GifType); -int DGifGetImageDesc(GifFileType * GifFile); -int DGifGetLine(GifFileType * GifFile, GifPixelType * GifLine, int GifLineLen); -int DGifGetPixel(GifFileType * GifFile, GifPixelType GifPixel); -int DGifGetComment(GifFileType * GifFile, char *GifComment); -int DGifGetExtension(GifFileType * GifFile, int *GifExtCode, - GifByteType ** GifExtension); -int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension); -int DGifGetCode(GifFileType * GifFile, int *GifCodeSize, - GifByteType ** GifCodeBlock); -int DGifGetCodeNext(GifFileType * GifFile, GifByteType ** GifCodeBlock); -int DGifGetLZCodes(GifFileType * GifFile, int *GifCode); +GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */ int DGifCloseFile(GifFileType * GifFile); #define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ @@ -216,121 +194,88 @@ int DGifCloseFile(GifFileType * GifFile); #define D_GIF_ERR_IMAGE_DEFECT 112 #define D_GIF_ERR_EOF_TOO_SOON 113 +/* These are legacy. You probably do not want to call them directly */ +int DGifGetScreenDesc(GifFileType *GifFile); +int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType); +int DGifGetImageDesc(GifFileType *GifFile); +int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen); +int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel); +int DGifGetComment(GifFileType *GifFile, char *GifComment); +int DGifGetExtension(GifFileType *GifFile, int *GifExtCode, + GifByteType **GifExtension); +int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension); +int DGifGetCode(GifFileType *GifFile, int *GifCodeSize, + GifByteType **GifCodeBlock); +int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock); +int DGifGetLZCodes(GifFileType *GifFile, int *GifCode); + + /****************************************************************************** - * O.K., here are the routines from GIF_LIB file QUANTIZE.C. + Color table quantization (deprecated) ******************************************************************************/ -int QuantizeBuffer(unsigned int Width, unsigned int Height, +int GifQuantizeBuffer(unsigned int Width, unsigned int Height, int *ColorMapSize, GifByteType * RedInput, GifByteType * GreenInput, GifByteType * BlueInput, GifByteType * OutputBuffer, GifColorType * OutputColorMap); /****************************************************************************** - * O.K., here are the routines from GIF_LIB file QPRINTF.C. + Error handling and reporting. ******************************************************************************/ -extern int GifQuietPrint; - -#ifdef HAVE_STDARG_H - extern void GifQprintf(char *Format, ...); -#elif defined (HAVE_VARARGS_H) - extern void GifQprintf(); -#endif /* HAVE_STDARG_H */ +extern char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ -/****************************************************************************** - * O.K., here are the routines from GIF_LIB file GIF_ERR.C. +/***************************************************************************** + Everything below this point is new after version 1.2, supporting `slurp + mode' for doing I/O in two big belts with all the image-bashing in core. ******************************************************************************/ -#ifndef _GBA_NO_FILEIO -extern void PrintGifError(void); -#endif /* _GBA_NO_FILEIO */ -extern int GifLastError(void); /****************************************************************************** - * O.K., here are the routines from GIF_LIB file DEV2GIF.C. + Color map handling from gif_alloc.c ******************************************************************************/ -extern int DumpScreen2Gif(const char *FileName, - int ReqGraphDriver, - long ReqGraphMode1, - long ReqGraphMode2, - long ReqGraphMode3); -/***************************************************************************** - * - * Everything below this point is new after version 1.2, supporting `slurp - * mode' for doing I/O in two big belts with all the image-bashing in core. - * - *****************************************************************************/ - -/****************************************************************************** - * Color Map handling from ALLOCGIF.C - *****************************************************************************/ - -extern ColorMapObject *MakeMapObject(int ColorCount, - const GifColorType * ColorMap); -extern void FreeMapObject(ColorMapObject * Object); -extern ColorMapObject *UnionColorMap(const ColorMapObject * ColorIn1, - const ColorMapObject * ColorIn2, +extern ColorMapObject *GifMakeMapObject(int ColorCount, + const GifColorType *ColorMap); +extern void GifFreeMapObject(ColorMapObject *Object); +extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1, + const ColorMapObject *ColorIn2, GifPixelType ColorTransIn2[]); -extern int BitSize(int n); +extern int GifBitSize(int n); /****************************************************************************** - * Support for the in-core structures allocation (slurp mode). - *****************************************************************************/ + Support for the in-core structures allocation (slurp mode). +******************************************************************************/ -/* This is the in-core version of an extension record */ -typedef struct { - int ByteCount; - char *Bytes; /* on malloc(3) heap */ - int Function; /* Holds the type of the Extension block. */ -} ExtensionBlock; +extern void GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]); +extern int GifAddExtensionBlock(int *ExtensionBlock_Count, + ExtensionBlock **ExtensionBlocks, + int Function, + unsigned int Len, unsigned char ExtData[]); +extern void GifFreeExtensions(int *ExtensionBlock_Count, + ExtensionBlock **ExtensionBlocks); +extern SavedImage *GifMakeSavedImage(GifFileType *GifFile, + const SavedImage *CopyFrom); +extern void GifFreeSavedImages(GifFileType *GifFile); -/* This holds an image header, its unpacked raster bits, and extensions */ -typedef struct SavedImage { - GifImageDesc ImageDesc; - unsigned char *RasterBits; /* on malloc(3) heap */ - int Function; /* DEPRECATED: Use ExtensionBlocks[x].Function instead */ - int ExtensionBlockCount; - ExtensionBlock *ExtensionBlocks; /* on malloc(3) heap */ -} SavedImage; +/****************************************************************************** + 5.x functions for GIF89 graphics control blocks +******************************************************************************/ -extern void ApplyTranslation(SavedImage * Image, GifPixelType Translation[]); -extern void MakeExtension(SavedImage * New, int Function); -extern int AddExtensionBlock(SavedImage * New, int Len, - unsigned char ExtData[]); -extern void FreeExtension(SavedImage * Image); -extern SavedImage *MakeSavedImage(GifFileType * GifFile, - const SavedImage * CopyFrom); -extern void FreeSavedImages(GifFileType * GifFile); +int DGifExtensionToGCB(const size_t GifExtensionLength, + const GifByteType *GifExtension, + GraphicsControlBlock *GCB); +size_t EGifGCBToExtension(const GraphicsControlBlock *GCB, + GifByteType *GifExtension); -/****************************************************************************** - * The library's internal utility font - *****************************************************************************/ - -#define GIF_FONT_WIDTH 8 -#define GIF_FONT_HEIGHT 8 -extern unsigned char AsciiTable[][GIF_FONT_WIDTH]; - -#ifdef _WIN32 - extern void DrawGifText(SavedImage * Image, -#else - extern void DrawGifText(SavedImage * Image, -#endif - const int x, const int y, - const char *legend, const int color); - -extern void DrawBox(SavedImage * Image, - const int x, const int y, - const int w, const int d, const int color); - -void DrawRectangle(SavedImage * Image, - const int x, const int y, - const int w, const int d, const int color); - -extern void DrawBoxedText(SavedImage * Image, - const int x, const int y, - const char *legend, - const int border, const int bg, const int fg); +int DGifSavedExtensionToGCB(GifFileType *GifFile, + int ImageIndex, + GraphicsControlBlock *GCB); +int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, + GifFileType *GifFile, + int ImageIndex); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _GIF_LIB_H */ + +/* end */ diff --git a/gif_lib_private.h b/gif_lib_private.h index b31c9c5..adaf557 100644 --- a/gif_lib_private.h +++ b/gif_lib_private.h @@ -1,19 +1,18 @@ +/**************************************************************************** + +gif_lib_private.h - internal giflib routines and structures + +****************************************************************************/ + #ifndef _GIF_LIB_PRIVATE_H #define _GIF_LIB_PRIVATE_H #include "gif_lib.h" #include "gif_hash.h" -#define PROGRAM_NAME "GIFLIB" - -#ifdef SYSV -#define VersionStr "Gif library module,\t\tEric S. Raymond\n\ - (C) Copyright 1997 Eric S. Raymond\n" -#else -#define VersionStr PROGRAM_NAME " IBMPC " GIF_LIB_VERSION \ - " Eric S. Raymond, " __DATE__ ", " \ - __TIME__ "\n" "(C) Copyright 1997 Eric S. Raymond\n" -#endif /* SYSV */ +#define EXTENSION_INTRODUCER 0x21 +#define DESCRIPTOR_INTRODUCER 0x2c +#define TERMINATOR_INTRODUCER 0x3b #define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ #define LZ_BITS 12 @@ -52,8 +51,9 @@ typedef struct GifFilePrivateType { GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ GifPrefixType Prefix[LZ_MAX_CODE + 1]; GifHashTableType *HashTable; + bool gif89; } GifFilePrivateType; -extern int _GifError; - #endif /* _GIF_LIB_PRIVATE_H */ + +/* end */ diff --git a/gifalloc.c b/gifalloc.c index 79d2332..4cb8cde 100644 --- a/gifalloc.c +++ b/gifalloc.c @@ -1,34 +1,25 @@ /***************************************************************************** - * "Gif-Lib" - Yet another gif library. - * - * Written by: Gershon Elber Ver 0.1, Jun. 1989 - * Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 - ***************************************************************************** - * GIF construction tools - ***************************************************************************** - * History: - * 15 Sep 92 - Version 1.0 by Eric Raymond. - ****************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif + + GIF construction tools + +****************************************************************************/ #include #include #include + #include "gif_lib.h" #define MAX(x, y) (((x) > (y)) ? (x) : (y)) /****************************************************************************** - * Miscellaneous utility functions - *****************************************************************************/ + Miscellaneous utility functions +******************************************************************************/ /* return smallest bitfield size n will fit in */ int -BitSize(int n) { - +GifBitSize(int n) +{ register int i; for (i = 1; i <= 8; i++) @@ -38,22 +29,21 @@ BitSize(int n) { } /****************************************************************************** - * Color map object functions - *****************************************************************************/ + Color map object functions +******************************************************************************/ /* * Allocate a color map of given size; initialize with contents of * ColorMap if that pointer is non-NULL. */ ColorMapObject * -MakeMapObject(int ColorCount, - const GifColorType * ColorMap) { - +GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) +{ ColorMapObject *Object; /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to * make the user know that or should we automatically round up instead? */ - if (ColorCount != (1 << BitSize(ColorCount))) { + if (ColorCount != (1 << GifBitSize(ColorCount))) { return ((ColorMapObject *) NULL); } @@ -64,13 +54,14 @@ MakeMapObject(int ColorCount, Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); if (Object->Colors == (GifColorType *) NULL) { + free(Object); return ((ColorMapObject *) NULL); } Object->ColorCount = ColorCount; - Object->BitsPerPixel = BitSize(ColorCount); + Object->BitsPerPixel = GifBitSize(ColorCount); - if (ColorMap) { + if (ColorMap != NULL) { memcpy((char *)Object->Colors, (char *)ColorMap, ColorCount * sizeof(GifColorType)); } @@ -78,72 +69,70 @@ MakeMapObject(int ColorCount, return (Object); } -/* - * Free a color map object - */ +/******************************************************************************* +Free a color map object +*******************************************************************************/ void -FreeMapObject(ColorMapObject * Object) { - +GifFreeMapObject(ColorMapObject *Object) +{ if (Object != NULL) { - free(Object->Colors); - free(Object); - /*** FIXME: - * When we are willing to break API we need to make this function - * FreeMapObject(ColorMapObject **Object) - * and do this assignment to NULL here: - * *Object = NULL; - */ + (void)free(Object->Colors); + (void)free(Object); } } #ifdef DEBUG void -DumpColorMap(ColorMapObject * Object, - FILE * fp) { - - if (Object) { +DumpColorMap(ColorMapObject *Object, + FILE * fp) +{ + if (Object != NULL) { int i, j, Len = Object->ColorCount; for (i = 0; i < Len; i += 4) { for (j = 0; j < 4 && j < Len; j++) { - fprintf(fp, "%3d: %02x %02x %02x ", i + j, - Object->Colors[i + j].Red, - Object->Colors[i + j].Green, - Object->Colors[i + j].Blue); + (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j, + Object->Colors[i + j].Red, + Object->Colors[i + j].Green, + Object->Colors[i + j].Blue); } - fprintf(fp, "\n"); + (void)fprintf(fp, "\n"); } } } #endif /* DEBUG */ -/* - * Compute the union of two given color maps and return it. If result can't - * fit into 256 colors, NULL is returned, the allocated union otherwise. - * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are - * copied iff they didn't exist before. ColorTransIn2 maps the old - * ColorIn2 into ColorUnion color map table. - */ +/******************************************************************************* + Compute the union of two given color maps and return it. If result can't + fit into 256 colors, NULL is returned, the allocated union otherwise. + ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are + copied iff they didn't exist before. ColorTransIn2 maps the old + ColorIn2 into the ColorUnion color map table./ +*******************************************************************************/ ColorMapObject * -UnionColorMap(const ColorMapObject * ColorIn1, - const ColorMapObject * ColorIn2, - GifPixelType ColorTransIn2[]) { - - int i, j, CrntSlot, RoundUpTo, NewBitSize; +GifUnionColorMap(const ColorMapObject *ColorIn1, + const ColorMapObject *ColorIn2, + GifPixelType ColorTransIn2[]) +{ + int i, j, CrntSlot, RoundUpTo, NewGifBitSize; ColorMapObject *ColorUnion; - /* - * Allocate table which will hold the result for sure. + /* + * We don't worry about duplicates within either color map; if + * the caller wants to resolve those, he can perform unions + * with an empty color map. */ - ColorUnion = MakeMapObject(MAX(ColorIn1->ColorCount, + + /* Allocate table which will hold the result for sure. */ + ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL); if (ColorUnion == NULL) return (NULL); - /* Copy ColorIn1 to ColorUnionSize; */ - /*** FIXME: What if there are duplicate entries into the colormap to begin - * with? */ + /* + * Copy ColorIn1 to ColorUnion. + */ for (i = 0; i < ColorIn1->ColorCount; i++) ColorUnion->Colors[i] = ColorIn1->Colors[i]; CrntSlot = ColorIn1->ColorCount; @@ -160,13 +149,9 @@ UnionColorMap(const ColorMapObject * ColorIn1, && ColorIn1->Colors[CrntSlot - 1].Blue == 0) CrntSlot--; - /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */ + /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { /* Let's see if this color already exists: */ - /*** FIXME: Will it ever occur that ColorIn2 will contain duplicate - * entries? So we should search from 0 to CrntSlot rather than - * ColorIn1->ColorCount? - */ for (j = 0; j < ColorIn1->ColorCount; j++) if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0) @@ -182,12 +167,12 @@ UnionColorMap(const ColorMapObject * ColorIn1, } if (CrntSlot > 256) { - FreeMapObject(ColorUnion); + GifFreeMapObject(ColorUnion); return ((ColorMapObject *) NULL); } - NewBitSize = BitSize(CrntSlot); - RoundUpTo = (1 << NewBitSize); + NewGifBitSize = GifBitSize(CrntSlot); + RoundUpTo = (1 << NewGifBitSize); if (RoundUpTo != ColorUnion->ColorCount) { register GifColorType *Map = ColorUnion->Colors; @@ -207,18 +192,17 @@ UnionColorMap(const ColorMapObject * ColorIn1, } ColorUnion->ColorCount = RoundUpTo; - ColorUnion->BitsPerPixel = NewBitSize; + ColorUnion->BitsPerPixel = NewGifBitSize; return (ColorUnion); } -/* - * Apply a given color translation to the raster bits of an image - */ +/******************************************************************************* + Apply a given color translation to the raster bits of an image +*******************************************************************************/ void -ApplyTranslation(SavedImage * Image, - GifPixelType Translation[]) { - +GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]) +{ register int i; register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; @@ -227,83 +211,70 @@ ApplyTranslation(SavedImage * Image, } /****************************************************************************** - * Extension record functions - *****************************************************************************/ - -void -MakeExtension(SavedImage * New, - int Function) { - - New->Function = Function; - /*** FIXME: - * Someday we might have to deal with multiple extensions. - * ??? Was this a note from Gershon or from me? Does the multiple - * extension blocks solve this or do we need multiple Functions? Or is - * this an obsolete function? (People should use AddExtensionBlock - * instead?) - * Looks like AddExtensionBlock needs to take the int Function argument - * then it can take the place of this function. Right now people have to - * use both. Fix AddExtensionBlock and add this to the deprecation list. - */ -} - + Extension record functions +******************************************************************************/ int -AddExtensionBlock(SavedImage * New, - int Len, - unsigned char ExtData[]) { - +GifAddExtensionBlock(int *ExtensionBlockCount, + ExtensionBlock **ExtensionBlocks, + int Function, + unsigned int Len, + unsigned char ExtData[]) +{ ExtensionBlock *ep; - if (New->ExtensionBlocks == NULL) - New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); + if (*ExtensionBlocks == NULL) + *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); else - New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks, + *ExtensionBlocks = (ExtensionBlock *)realloc(*ExtensionBlocks, sizeof(ExtensionBlock) * - (New->ExtensionBlockCount + 1)); + (*ExtensionBlockCount + 1)); - if (New->ExtensionBlocks == NULL) + if (*ExtensionBlocks == NULL) return (GIF_ERROR); - ep = &New->ExtensionBlocks[New->ExtensionBlockCount++]; + ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; + ep->Function = Function; ep->ByteCount=Len; - ep->Bytes = (char *)malloc(ep->ByteCount); + ep->Bytes = (GifByteType *)malloc(ep->ByteCount); if (ep->Bytes == NULL) return (GIF_ERROR); - if (ExtData) { + if (ExtData != NULL) { memcpy(ep->Bytes, ExtData, Len); - ep->Function = New->Function; } return (GIF_OK); } void -FreeExtension(SavedImage * Image) +GifFreeExtensions(int *ExtensionBlockCount, + ExtensionBlock **ExtensionBlocks) { ExtensionBlock *ep; - if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) { + if (*ExtensionBlocks == NULL) return; - } - for (ep = Image->ExtensionBlocks; - ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++) + + for (ep = *ExtensionBlocks; + ep < (*ExtensionBlocks + *ExtensionBlockCount); + ep++) (void)free((char *)ep->Bytes); - free((char *)Image->ExtensionBlocks); - Image->ExtensionBlocks = NULL; + (void)free((char *)*ExtensionBlocks); + *ExtensionBlocks = NULL; + *ExtensionBlockCount = 0; } /****************************************************************************** - * Image block allocation functions + Image block allocation functions ******************************************************************************/ /* Private Function: * Frees the last image in the GifFile->SavedImages array */ void -FreeLastSavedImage(GifFileType *GifFile) { - +FreeLastSavedImage(GifFileType *GifFile) +{ SavedImage *sp; if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) @@ -314,22 +285,21 @@ FreeLastSavedImage(GifFileType *GifFile) { sp = &GifFile->SavedImages[GifFile->ImageCount]; /* Deallocate its Colormap */ - if (sp->ImageDesc.ColorMap) { - FreeMapObject(sp->ImageDesc.ColorMap); + if (sp->ImageDesc.ColorMap != NULL) { + GifFreeMapObject(sp->ImageDesc.ColorMap); sp->ImageDesc.ColorMap = NULL; } /* Deallocate the image data */ - if (sp->RasterBits) + if (sp->RasterBits != NULL) free((char *)sp->RasterBits); /* Deallocate any extensions */ - if (sp->ExtensionBlocks) - FreeExtension(sp); + GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); /*** FIXME: We could realloc the GifFile->SavedImages structure but is * there a point to it? Saves some memory but we'd have to do it every - * time. If this is used in FreeSavedImages then it would be inefficient + * time. If this is used in GifFreeSavedImages then it would be inefficient * (The whole array is going to be deallocated.) If we just use it when * we want to free the last Image it's convenient to do it here. */ @@ -339,9 +309,8 @@ FreeLastSavedImage(GifFileType *GifFile) { * Append an image block to the SavedImages array */ SavedImage * -MakeSavedImage(GifFileType * GifFile, - const SavedImage * CopyFrom) { - +GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) +{ SavedImage *sp; if (GifFile->SavedImages == NULL) @@ -356,7 +325,7 @@ MakeSavedImage(GifFileType * GifFile, sp = &GifFile->SavedImages[GifFile->ImageCount++]; memset((char *)sp, '\0', sizeof(SavedImage)); - if (CopyFrom) { + if (CopyFrom != NULL) { memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); /* @@ -366,8 +335,8 @@ MakeSavedImage(GifFileType * GifFile, */ /* first, the local color map */ - if (sp->ImageDesc.ColorMap) { - sp->ImageDesc.ColorMap = MakeMapObject( + if (sp->ImageDesc.ColorMap != NULL) { + sp->ImageDesc.ColorMap = GifMakeMapObject( CopyFrom->ImageDesc.ColorMap->ColorCount, CopyFrom->ImageDesc.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { @@ -389,7 +358,7 @@ MakeSavedImage(GifFileType * GifFile, CopyFrom->ImageDesc.Width); /* finally, the extension blocks */ - if (sp->ExtensionBlocks) { + if (sp->ExtensionBlocks != NULL) { sp->ExtensionBlocks = (ExtensionBlock *)malloc( sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); @@ -399,17 +368,6 @@ MakeSavedImage(GifFileType * GifFile, } memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); - - /* - * For the moment, the actual blocks can take their - * chances with free(). We'll fix this later. - *** FIXME: [Better check this out... Toshio] - * 2004 May 27: Looks like this was an ESR note. - * It means the blocks are shallow copied from InFile to - * OutFile. However, I don't see that in this code.... - * Did ESR fix it but never remove this note (And other notes - * in gifspnge?) - */ } } @@ -418,8 +376,8 @@ MakeSavedImage(GifFileType * GifFile, } void -FreeSavedImages(GifFileType * GifFile) { - +GifFreeSavedImages(GifFileType *GifFile) +{ SavedImage *sp; if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { @@ -427,17 +385,18 @@ FreeSavedImages(GifFileType * GifFile) { } for (sp = GifFile->SavedImages; sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { - if (sp->ImageDesc.ColorMap) { - FreeMapObject(sp->ImageDesc.ColorMap); + if (sp->ImageDesc.ColorMap != NULL) { + GifFreeMapObject(sp->ImageDesc.ColorMap); sp->ImageDesc.ColorMap = NULL; } - if (sp->RasterBits) + if (sp->RasterBits != NULL) free((char *)sp->RasterBits); - - if (sp->ExtensionBlocks) - FreeExtension(sp); + + GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); } free((char *)GifFile->SavedImages); - GifFile->SavedImages=NULL; + GifFile->SavedImages = NULL; } + +/* end */ -- cgit v1.2.3