summaryrefslogtreecommitdiffstats
path: root/dgif_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'dgif_lib.c')
-rw-r--r--dgif_lib.c806
1 files changed, 437 insertions, 369 deletions
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 <config.h>
-#endif
-#include <stdlib.h>
-#if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__)
-#include <io.h>
-#include <alloc.h>
-#include <sys\stat.h>
-#else
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif /* __MSDOS__ */
-
-#ifdef HAVE_IO_H
-#include <io.h>
-#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 <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#include <stdio.h>
#include <string.h>
+
+#ifdef _WIN32
+#include <io.h>
+#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 */