resolved conflicts for merge of 929d81ca to master
Change-Id: Ie5e1e595a2d38540cc1096386fc5c5f8c1ee7848
diff --git a/Android.mk b/Android.mk
index 427c1ee..0639e00 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,12 +4,12 @@
LOCAL_SDK_VERSION := 9
LOCAL_SRC_FILES := \
- dgif_lib.c \
- egif_lib.c \
- gifalloc.c \
- gif_err.c \
- gif_hash.c \
- quantize.c
+ dgif_lib.c \
+ egif_lib.c \
+ gifalloc.c \
+ gif_err.c \
+ gif_hash.c \
+ quantize.c
LOCAL_CFLAGS += -Wno-format -Wno-sign-compare -Wno-unused-parameter -DHAVE_CONFIG_H
LOCAL_SDK_VERSION := 8
diff --git a/README.version b/README.version
index f310fff..8d84679 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: http://sourceforge.net/projects/giflib/files/giflib-5.x/giflib-5.0.4.tar.bz2/download
-Version: 5.0.4
+URL: https://sourceforge.net/projects/giflib/files/giflib-5.1.1.tar.bz2/download
+Version: 5.1.1
BugComponent: 24950
diff --git a/dgif_lib.c b/dgif_lib.c
index 744a2f9..320fdb9 100644
--- a/dgif_lib.c
+++ b/dgif_lib.c
@@ -59,7 +59,6 @@
}
GifFile = DGifOpenFileHandle(FileHandle, Error);
- // cppcheck-suppress resourceLeak
return GifFile;
}
@@ -114,6 +113,7 @@
/*@=mustfreeonly@*/
/* Let's see if this is a GIF file: */
+ /* coverity[check_return] */
if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
if (Error != NULL)
*Error = D_GIF_ERR_READ_FAILED;
@@ -189,6 +189,7 @@
GifFile->UserData = userData; /* TVT */
/* Lets see if this is a GIF file: */
+ /* coverity[check_return] */
if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
if (Error != NULL)
*Error = D_GIF_ERR_READ_FAILED;
@@ -210,6 +211,8 @@
if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
free((char *)Private);
free((char *)GifFile);
+ if (Error != NULL)
+ *Error = D_GIF_ERR_NO_SCRN_DSCR;
return NULL;
}
@@ -267,6 +270,7 @@
/* Get the global color map: */
GifFile->SColorMap->SortFlag = SortFlag;
for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
+ /* coverity[check_return] */
if (READ(GifFile, Buf, 3) != 3) {
GifFreeMapObject(GifFile->SColorMap);
GifFile->SColorMap = NULL;
@@ -299,6 +303,7 @@
return GIF_ERROR;
}
+ /* coverity[check_return] */
if (READ(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -372,6 +377,7 @@
/* Get the image local color map: */
for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
+ /* coverity[check_return] */
if (READ(GifFile, Buf, 3) != 3) {
GifFreeMapObject(GifFile->Image.ColorMap);
GifFile->Error = D_GIF_ERR_READ_FAILED;
@@ -385,12 +391,14 @@
}
if (GifFile->SavedImages) {
- if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
- sizeof(SavedImage) *
- (GifFile->ImageCount + 1))) == NULL) {
+ SavedImage* new_saved_images =
+ (SavedImage *)realloc(GifFile->SavedImages,
+ sizeof(SavedImage) * (GifFile->ImageCount + 1));
+ if (new_saved_images == NULL) {
GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
return GIF_ERROR;
}
+ GifFile->SavedImages = new_saved_images;
} else {
if ((GifFile->SavedImages =
(SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
@@ -420,9 +428,7 @@
(long)GifFile->Image.Height;
/* Reset decompress algorithm parameters. */
- (void)DGifSetupDecompress(GifFile);
-
- return GIF_OK;
+ return DGifSetupDecompress(GifFile);
}
/******************************************************************************
@@ -521,6 +527,7 @@
return GIF_ERROR;
}
+ /* coverity[check_return] */
if (READ(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -548,7 +555,7 @@
if (Buf > 0) {
*Extension = Private->Buf; /* Use private unused buffer. */
(*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
- /* coverity[tainted_data] */
+ /* coverity[tainted_data,check_return] */
if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -612,7 +619,7 @@
This routine should be called last, to close the GIF file.
******************************************************************************/
int
-DGifCloseFile(GifFileType *GifFile)
+DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
{
GifFilePrivateType *Private;
@@ -640,25 +647,25 @@
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
- GifFile->Error = D_GIF_ERR_NOT_READABLE;
+ if (ErrorCode != NULL)
+ *ErrorCode = D_GIF_ERR_NOT_READABLE;
+ free((char *)GifFile->Private);
+ free(GifFile);
return GIF_ERROR;
}
if (Private->File && (fclose(Private->File) != 0)) {
- GifFile->Error = D_GIF_ERR_CLOSE_FAILED;
+ if (ErrorCode != NULL)
+ *ErrorCode = D_GIF_ERR_CLOSE_FAILED;
+ free((char *)GifFile->Private);
+ free(GifFile);
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__ */
-
+ if (ErrorCode != NULL)
+ *ErrorCode = D_GIF_SUCCEEDED;
return GIF_OK;
}
@@ -670,6 +677,7 @@
{
unsigned char c[2];
+ /* coverity[check_return] */
if (READ(GifFile, c, 2) != 2) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -714,6 +722,7 @@
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
/* coverity[tainted_data_argument] */
+ /* coverity[check_return] */
if (READ(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -748,7 +757,10 @@
GifPrefixType *Prefix;
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
- READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
+ /* coverity[check_return] */
+ if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */
+ return GIF_ERROR; /* Failed to read Code size. */
+ }
BitsPerPixel = CodeSize;
Private->Buf[0] = 0; /* Input Buffer empty. */
@@ -834,19 +846,22 @@
* pixels on our stack. If we done, pop the stack in reverse
* (thats what stack is good for!) order to output. */
if (Prefix[CrntCode] == NO_SUCH_CODE) {
+ CrntPrefix = LastCode;
+
/* Only allowed if CrntCode is exactly the running code:
* In that case CrntCode = XXXCode, CrntCode or the
* prefix code is last code and the suffix char is
* exactly the prefix of last code! */
if (CrntCode == Private->RunningCode - 2) {
- CrntPrefix = LastCode;
Suffix[Private->RunningCode - 2] =
Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
LastCode,
ClearCode);
} else {
- GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
- return GIF_ERROR;
+ Suffix[Private->RunningCode - 2] =
+ Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
+ CrntCode,
+ ClearCode);
}
} else
CrntPrefix = CrntCode;
@@ -1018,6 +1033,7 @@
{
if (Buf[0] == 0) {
/* Needs to read the next buffer - this one is empty: */
+ /* coverity[check_return] */
if (READ(GifFile, Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -1030,14 +1046,6 @@
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]) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
@@ -1135,12 +1143,12 @@
return (GIF_ERROR);
/* Create an extension block with our data */
if (ExtData != NULL) {
- if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
- &GifFile->ExtensionBlocks,
- ExtFunction, ExtData[0], &ExtData[1])
- == GIF_ERROR)
- return (GIF_ERROR);
- }
+ if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
+ &GifFile->ExtensionBlocks,
+ ExtFunction, ExtData[0], &ExtData[1])
+ == GIF_ERROR)
+ return (GIF_ERROR);
+ }
while (ExtData != NULL) {
if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
return (GIF_ERROR);
diff --git a/egif_lib.c b/egif_lib.c
index 4e353ba..754d914 100644
--- a/egif_lib.c
+++ b/egif_lib.c
@@ -186,7 +186,7 @@
/******************************************************************************
Routine to compute the GIF version that will be written on output.
******************************************************************************/
-char *
+const char *
EGifGetGifVersion(GifFileType *GifFile)
{
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
@@ -267,7 +267,7 @@
{
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
- char *write_version;
+ const char *write_version;
if (Private->FileState & FILE_STATE_SCREEN) {
/* If already has screen descriptor - something is wrong! */
@@ -379,6 +379,10 @@
GifFile->Image.Height = Height;
GifFile->Image.Interlace = Interlace;
if (ColorMap) {
+ if (GifFile->Image.ColorMap != NULL) {
+ GifFreeMapObject(GifFile->Image.ColorMap);
+ GifFile->Image.ColorMap = NULL;
+ }
GifFile->Image.ColorMap = GifMakeMapObject(ColorMap->ColorCount,
ColorMap->Colors);
if (GifFile->Image.ColorMap == NULL) {
@@ -496,7 +500,7 @@
int
EGifPutComment(GifFileType *GifFile, const char *Comment)
{
- unsigned int length = strlen(Comment);
+ unsigned int length;
char *buf;
length = strlen(Comment);
@@ -750,7 +754,7 @@
This routine should be called last, to close the GIF file.
******************************************************************************/
int
-EGifCloseFile(GifFileType *GifFile)
+EGifCloseFile(GifFileType *GifFile, int *ErrorCode)
{
GifByteType Buf;
GifFilePrivateType *Private;
@@ -764,7 +768,9 @@
return GIF_ERROR;
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
- GifFile->Error = E_GIF_ERR_NOT_WRITEABLE;
+ if (ErrorCode != NULL)
+ *ErrorCode = E_GIF_ERR_NOT_WRITEABLE;
+ free(GifFile);
return GIF_ERROR;
}
@@ -785,22 +791,19 @@
if (Private->HashTable) {
free((char *) Private->HashTable);
}
- free((char *) Private);
+ free((char *) Private);
}
if (File && fclose(File) != 0) {
- GifFile->Error = E_GIF_ERR_CLOSE_FAILED;
+ if (ErrorCode != NULL)
+ *ErrorCode = E_GIF_ERR_CLOSE_FAILED;
+ free(GifFile);
return GIF_ERROR;
}
- /*
- * 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__ */
-
+ if (ErrorCode != NULL)
+ *ErrorCode = E_GIF_SUCCEEDED;
return GIF_OK;
}
@@ -1140,7 +1143,7 @@
GifFileOut->ExtensionBlockCount) == GIF_ERROR)
return (GIF_ERROR);
- if (EGifCloseFile(GifFileOut) == GIF_ERROR)
+ if (EGifCloseFile(GifFileOut, NULL) == GIF_ERROR)
return (GIF_ERROR);
return (GIF_OK);
diff --git a/gif_err.c b/gif_err.c
index 8de72a0..3ec2a56 100644
--- a/gif_err.c
+++ b/gif_err.c
@@ -12,10 +12,10 @@
/*****************************************************************************
Return a string description of the last GIF error
*****************************************************************************/
-char *
+const char *
GifErrorString(int ErrorCode)
{
- char *Err;
+ const char *Err;
switch (ErrorCode) {
case E_GIF_ERR_OPEN_FAILED:
diff --git a/gif_font.c b/gif_font.c
new file mode 100644
index 0000000..ba47b29
--- /dev/null
+++ b/gif_font.c
@@ -0,0 +1,252 @@
+/*****************************************************************************
+
+gif_font.c - utility font handling and simple drawing for the GIF library
+
+****************************************************************************/
+
+#include <string.h>
+
+#include "gif_lib.h"
+
+/*****************************************************************************
+ Ascii 8 by 8 regular font - only first 128 characters are supported.
+*****************************************************************************/
+
+/*
+ * Each array entry holds the bits for 8 horizontal scan lines, topmost
+ * first. The most significant bit of each constant is the leftmost bit of
+ * the scan line.
+ */
+/*@+charint@*/
+const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* Ascii 0 */
+ {0x3c, 0x42, 0xa5, 0x81, 0xbd, 0x42, 0x3c, 0x00}, /* Ascii 1 */
+ {0x3c, 0x7e, 0xdb, 0xff, 0xc3, 0x7e, 0x3c, 0x00}, /* Ascii 2 */
+ {0x00, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 3 */
+ {0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 4 */
+ {0x00, 0x3c, 0x18, 0xff, 0xff, 0x08, 0x18, 0x00}, /* Ascii 5 */
+ {0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x10, 0x38, 0x00}, /* Ascii 6 */
+ {0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00}, /* Ascii 7 */
+ {0xff, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0xff, 0xff}, /* Ascii 8 */
+ {0x00, 0x3c, 0x42, 0x81, 0x81, 0x42, 0x3c, 0x00}, /* Ascii 9 */
+ {0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0xbd, 0xc3, 0xff}, /* Ascii 10 */
+ {0x1f, 0x07, 0x0d, 0x7c, 0xc6, 0xc6, 0x7c, 0x00}, /* Ascii 11 */
+ {0x00, 0x7e, 0xc3, 0xc3, 0x7e, 0x18, 0x7e, 0x18}, /* Ascii 12 */
+ {0x04, 0x06, 0x07, 0x04, 0x04, 0xfc, 0xf8, 0x00}, /* Ascii 13 */
+ {0x0c, 0x0a, 0x0d, 0x0b, 0xf9, 0xf9, 0x1f, 0x1f}, /* Ascii 14 */
+ {0x00, 0x92, 0x7c, 0x44, 0xc6, 0x7c, 0x92, 0x00}, /* Ascii 15 */
+ {0x00, 0x00, 0x60, 0x78, 0x7e, 0x78, 0x60, 0x00}, /* Ascii 16 */
+ {0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00}, /* Ascii 17 */
+ {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18}, /* Ascii 18 */
+ {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00}, /* Ascii 19 */
+ {0xff, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x36, 0x00}, /* Ascii 20 */
+ {0x7e, 0xc1, 0xdc, 0x22, 0x22, 0x1f, 0x83, 0x7e}, /* Ascii 21 */
+ {0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00}, /* Ascii 22 */
+ {0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x00, 0xff}, /* Ascii 23 */
+ {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, /* Ascii 24 */
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x00}, /* Ascii 25 */
+ {0x00, 0x04, 0x06, 0xff, 0x06, 0x04, 0x00, 0x00}, /* Ascii 26 */
+ {0x00, 0x20, 0x60, 0xff, 0x60, 0x20, 0x00, 0x00}, /* Ascii 27 */
+ {0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0x00}, /* Ascii 28 */
+ {0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00}, /* Ascii 29 */
+ {0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x00, 0x00}, /* Ascii 30 */
+ {0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 31 */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* */
+ {0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00}, /* ! */
+ {0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */
+ {0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00}, /* # */
+ {0x10, 0x7c, 0xd2, 0x7c, 0x86, 0x7c, 0x10, 0x00}, /* $ */
+ {0xf0, 0x96, 0xfc, 0x18, 0x3e, 0x72, 0xde, 0x00}, /* % */
+ {0x30, 0x48, 0x30, 0x78, 0xce, 0xcc, 0x78, 0x00}, /* & */
+ {0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */
+ {0x10, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x10, 0x00}, /* ( */
+ {0x10, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x10, 0x00}, /* ) */
+ {0x00, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x00, 0x00}, /* * */
+ {0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00}, /* + */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70}, /* , */
+ {0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00}, /* - */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00}, /* . */
+ {0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00}, /* / */
+ {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* 0 */
+ {0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* 1 */
+ {0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x60, 0xfe, 0x00}, /* 2 */
+ {0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00}, /* 3 */
+ {0x0e, 0x1e, 0x36, 0x66, 0xfe, 0x06, 0x06, 0x00}, /* 4 */
+ {0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xfc, 0x00}, /* 5 */
+ {0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00}, /* 6 */
+ {0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x00}, /* 7 */
+ {0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00}, /* 8 */
+ {0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00}, /* 9 */
+ {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00}, /* : */
+ {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x20, 0x00}, /* }, */
+ {0x00, 0x1c, 0x30, 0x60, 0x30, 0x1c, 0x00, 0x00}, /* < */
+ {0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}, /* = */
+ {0x00, 0x70, 0x18, 0x0c, 0x18, 0x70, 0x00, 0x00}, /* > */
+ {0x7c, 0xc6, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00}, /* ? */
+ {0x7c, 0x82, 0x9a, 0xaa, 0xaa, 0x9e, 0x7c, 0x00}, /* @ */
+ {0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00}, /* A */
+ {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00}, /* B */
+ {0x7c, 0xc6, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00}, /* C */
+ {0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00}, /* D */
+ {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xfe, 0x00}, /* E */
+ {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0x00}, /* F */
+ {0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7e, 0x00}, /* G */
+ {0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00}, /* H */
+ {0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00}, /* I */
+ {0x1e, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00}, /* J */
+ {0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x00}, /* K */
+ {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00}, /* L */
+ {0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00}, /* M */
+ {0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00}, /* N */
+ {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* O */
+ {0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00}, /* P */
+ {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x06}, /* Q */
+ {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0x00}, /* R */
+ {0x78, 0xcc, 0x60, 0x30, 0x18, 0xcc, 0x78, 0x00}, /* S */
+ {0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00}, /* T */
+ {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* U */
+ {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00}, /* V */
+ {0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00}, /* W */
+ {0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00}, /* X */
+ {0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00}, /* Y */
+ {0xfe, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00}, /* Z */
+ {0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00}, /* [ */
+ {0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00}, /* \ */
+ {0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00}, /* ] */
+ {0x00, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, /* ^ */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, /* _ */
+ {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */
+ {0x00, 0x00, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00}, /* a */
+ {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0x00}, /* b */
+ {0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0x7e, 0x00}, /* c */
+ {0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x00}, /* d */
+ {0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7e, 0x00}, /* e */
+ {0x1e, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x00}, /* f */
+ {0x00, 0x00, 0x7e, 0xc6, 0xce, 0x76, 0x06, 0x7c}, /* g */
+ {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00}, /* */
+ {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* i */
+ {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0xf0}, /* j */
+ {0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00}, /* k */
+ {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* l */
+ {0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xc6, 0xc6, 0x00}, /* m */
+ {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00}, /* n */
+ {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* o */
+ {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0}, /* p */
+ {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x06}, /* q */
+ {0x00, 0x00, 0x6e, 0x70, 0x60, 0x60, 0x60, 0x00}, /* r */
+ {0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00}, /* s */
+ {0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00}, /* t */
+ {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00}, /* u */
+ {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00}, /* v */
+ {0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x00}, /* w */
+ {0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00}, /* x */
+ {0x00, 0x00, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x7c}, /* y */
+ {0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00}, /* z */
+ {0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00}, /* { */
+ {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, /* | */
+ {0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00}, /* } */
+ {0x00, 0x00, 0x70, 0x9a, 0x0e, 0x00, 0x00, 0x00}, /* ~ */
+ {0x00, 0x00, 0x18, 0x3c, 0x66, 0xff, 0x00, 0x00} /* Ascii 127 */
+};
+/*@=charint@*/
+
+void
+GifDrawText8x8(SavedImage *Image,
+ const int x, const int y,
+ const char *legend,
+ const int color)
+{
+ int i, j;
+ int base;
+ const char *cp;
+
+ for (i = 0; i < GIF_FONT_HEIGHT; i++) {
+ base = Image->ImageDesc.Width * (y + i) + x;
+
+ for (cp = legend; *cp; cp++)
+ for (j = 0; j < GIF_FONT_WIDTH; j++) {
+ if (GifAsciiTable8x8[(short)(*cp)][i] & (1 << (GIF_FONT_WIDTH - j)))
+ Image->RasterBits[base] = color;
+ base++;
+ }
+ }
+}
+
+void
+GifDrawBox(SavedImage *Image,
+ const int x, const int y,
+ const int w, const int d,
+ const int color)
+{
+ int j, base = Image->ImageDesc.Width * y + x;
+
+ for (j = 0; j < w; j++)
+ Image->RasterBits[base + j] =
+ Image->RasterBits[base + (d * Image->ImageDesc.Width) + j] = color;
+
+ for (j = 0; j < d; j++)
+ Image->RasterBits[base + j * Image->ImageDesc.Width] =
+ Image->RasterBits[base + j * Image->ImageDesc.Width + w] = color;
+}
+
+void
+GifDrawRectangle(SavedImage *Image,
+ const int x, const int y,
+ const int w, const int d,
+ const int color)
+{
+ unsigned char *bp = Image->RasterBits + Image->ImageDesc.Width * y + x;
+ int i;
+
+ for (i = 0; i < d; i++)
+ memset(bp + (i * Image->ImageDesc.Width), color, (size_t)w);
+}
+
+void
+GifDrawBoxedText8x8(SavedImage *Image,
+ const int x, const int y,
+ const char *legend,
+ const int border,
+ const int bg, const int fg)
+{
+ int i, j = 0, LineCount = 0, TextWidth = 0;
+ const char *cp;
+
+ /* compute size of text to box */
+ for (cp = legend; *cp; cp++)
+ if (*cp == '\r') {
+ if (j > TextWidth)
+ TextWidth = j;
+ j = 0;
+ LineCount++;
+ } else if (*cp != '\t')
+ ++j;
+ LineCount++; /* count last line */
+ if (j > TextWidth) /* last line might be longer than any previous */
+ TextWidth = j;
+
+ /* fill the box */
+ GifDrawRectangle(Image, x + 1, y + 1,
+ border + TextWidth * GIF_FONT_WIDTH + border - 1,
+ border + LineCount * GIF_FONT_HEIGHT + border - 1, bg);
+
+ /* draw the text */
+ i = 0;
+ cp = strtok((char *)legend, "\r\n");
+ do {
+ int leadspace = 0;
+
+ if (cp[0] == '\t')
+ leadspace = (TextWidth - strlen(++cp)) / 2;
+
+ GifDrawText8x8(Image, x + border + (leadspace * GIF_FONT_WIDTH),
+ y + border + (GIF_FONT_HEIGHT * i++), cp, fg);
+ cp = strtok((char *)NULL, "\r\n");
+ } while (cp);
+
+ /* outline the box */
+ GifDrawBox(Image, x, y, border + TextWidth * GIF_FONT_WIDTH + border,
+ border + LineCount * GIF_FONT_HEIGHT + border, fg);
+}
+
+/* end */
diff --git a/gif_lib.h b/gif_lib.h
index 23df861..ac0307d 100644
--- a/gif_lib.h
+++ b/gif_lib.h
@@ -12,12 +12,13 @@
#endif /* __cplusplus */
#define GIFLIB_MAJOR 5
-#define GIFLIB_MINOR 0
-#define GIFLIB_RELEASE 4
+#define GIFLIB_MINOR 1
+#define GIFLIB_RELEASE 1
#define GIF_ERROR 0
#define GIF_OK 1
+#include <stddef.h>
#include <stdbool.h>
#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
@@ -127,9 +128,10 @@
GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error);
GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error);
int EGifSpew(GifFileType * GifFile);
-char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
-int EGifCloseFile(GifFileType * GifFile);
+const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
+int EGifCloseFile(GifFileType *GifFile, int *ErrorCode);
+#define E_GIF_SUCCEEDED 0
#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */
#define E_GIF_ERR_WRITE_FAILED 2
#define E_GIF_ERR_HAS_SCRN_DSCR 3
@@ -178,8 +180,9 @@
GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error);
int DGifSlurp(GifFileType * GifFile);
GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */
-int DGifCloseFile(GifFileType * GifFile);
+ int DGifCloseFile(GifFileType * GifFile, int *ErrorCode);
+#define D_GIF_SUCCEEDED 0
#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
#define D_GIF_ERR_READ_FAILED 102
#define D_GIF_ERR_NOT_GIF_FILE 103
@@ -222,7 +225,7 @@
/******************************************************************************
Error handling and reporting.
******************************************************************************/
-extern char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */
+extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */
/*****************************************************************************
Everything below this point is new after version 1.2, supporting `slurp
@@ -273,6 +276,31 @@
GifFileType *GifFile,
int ImageIndex);
+/******************************************************************************
+ The library's internal utility font
+******************************************************************************/
+
+#define GIF_FONT_WIDTH 8
+#define GIF_FONT_HEIGHT 8
+extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH];
+
+extern void GifDrawText8x8(SavedImage *Image,
+ const int x, const int y,
+ const char *legend, const int color);
+
+extern void GifDrawBox(SavedImage *Image,
+ const int x, const int y,
+ const int w, const int d, const int color);
+
+extern void GifDrawRectangle(SavedImage *Image,
+ const int x, const int y,
+ const int w, const int d, const int color);
+
+extern void GifDrawBoxedText8x8(SavedImage *Image,
+ const int x, const int y,
+ const char *legend,
+ const int border, const int bg, const int fg);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gifalloc.c b/gifalloc.c
index 4cb8cde..f4118d6 100644
--- a/gifalloc.c
+++ b/gifalloc.c
@@ -60,6 +60,7 @@
Object->ColorCount = ColorCount;
Object->BitsPerPixel = GifBitSize(ColorCount);
+ Object->SortFlag = false;
if (ColorMap != NULL) {
memcpy((char *)Object->Colors,
@@ -186,9 +187,15 @@
Map[j].Red = Map[j].Green = Map[j].Blue = 0;
/* perhaps we can shrink the map? */
- if (RoundUpTo < ColorUnion->ColorCount)
- ColorUnion->Colors = (GifColorType *)realloc(Map,
+ if (RoundUpTo < ColorUnion->ColorCount) {
+ GifColorType *new_map = (GifColorType *)realloc(Map,
sizeof(GifColorType) * RoundUpTo);
+ if( new_map == NULL ) {
+ GifFreeMapObject(ColorUnion);
+ return ((ColorMapObject *) NULL);
+ }
+ ColorUnion->Colors = new_map;
+ }
}
ColorUnion->ColorCount = RoundUpTo;
@@ -224,10 +231,14 @@
if (*ExtensionBlocks == NULL)
*ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
- else
- *ExtensionBlocks = (ExtensionBlock *)realloc(*ExtensionBlocks,
+ else {
+ ExtensionBlock* ep_new = (ExtensionBlock *)realloc(*ExtensionBlocks,
sizeof(ExtensionBlock) *
(*ExtensionBlockCount + 1));
+ if( ep_new == NULL )
+ return (GIF_ERROR);
+ *ExtensionBlocks = ep_new;
+ }
if (*ExtensionBlocks == NULL)
return (GIF_ERROR);
@@ -311,8 +322,6 @@
SavedImage *
GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
{
- SavedImage *sp;
-
if (GifFile->SavedImages == NULL)
GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
else
@@ -322,7 +331,7 @@
if (GifFile->SavedImages == NULL)
return ((SavedImage *)NULL);
else {
- sp = &GifFile->SavedImages[GifFile->ImageCount++];
+ SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
memset((char *)sp, '\0', sizeof(SavedImage));
if (CopyFrom != NULL) {
diff --git a/quantize.c b/quantize.c
index fc31f36..e5d4a59 100644
--- a/quantize.c
+++ b/quantize.c
@@ -234,6 +234,17 @@
j++, QuantizedColor = QuantizedColor->Pnext)
SortArray[j] = QuantizedColor;
+ /*
+ * Because qsort isn't stable, this can produce differing
+ * results for the order of tuples depending on platform
+ * details of how qsort() is implemented.
+ *
+ * We mitigate this problem by sorting on all three axes rather
+ * than only the one specied by SortRGBAxis; that way the instability
+ * can only become an issue if there are multiple color indices
+ * referring to identical RGB tuples. Older versions of this
+ * sorted on only the one axis.
+ */
qsort(SortArray, NewColorSubdiv[Index].NumEntries,
sizeof(QuantizedColorType *), SortCmpRtn);
@@ -298,12 +309,22 @@
/****************************************************************************
Routine called by qsort to compare two entries.
*****************************************************************************/
+
static int
SortCmpRtn(const void *Entry1,
const void *Entry2) {
+ QuantizedColorType *entry1 = (*((QuantizedColorType **) Entry1));
+ QuantizedColorType *entry2 = (*((QuantizedColorType **) Entry2));
- return (*((QuantizedColorType **) Entry1))->RGB[SortRGBAxis] -
- (*((QuantizedColorType **) Entry2))->RGB[SortRGBAxis];
+ /* sort on all axes of the color space! */
+ int hash1 = entry1->RGB[SortRGBAxis] * 256 * 256
+ + entry1->RGB[(SortRGBAxis+1) % 3] * 256
+ + entry1->RGB[(SortRGBAxis+2) % 3];
+ int hash2 = entry2->RGB[SortRGBAxis] * 256 * 256
+ + entry2->RGB[(SortRGBAxis+1) % 3] * 256
+ + entry2->RGB[(SortRGBAxis+2) % 3];
+
+ return hash1 - hash2;
}
/* end */