From ff8bf2be644ea62fb438c13de2c60b33b57655b1 Mon Sep 17 00:00:00 2001 From: seven332 Date: Sat, 19 Mar 2016 00:27:44 +0800 Subject: [PATCH] Update giflib to 5.1.3 --- app/src/main/jni/giflib/Android.mk | 1 - app/src/main/jni/giflib/dgif_lib.c | 20 +- app/src/main/jni/giflib/egif_lib.c | 1150 ---------------------------- app/src/main/jni/giflib/gif_lib.h | 2 +- 4 files changed, 13 insertions(+), 1160 deletions(-) delete mode 100644 app/src/main/jni/giflib/egif_lib.c diff --git a/app/src/main/jni/giflib/Android.mk b/app/src/main/jni/giflib/Android.mk index 666ccd827..f726c519f 100644 --- a/app/src/main/jni/giflib/Android.mk +++ b/app/src/main/jni/giflib/Android.mk @@ -19,7 +19,6 @@ include $(CLEAR_VARS) LOCAL_MODULE := gif LOCAL_SRC_FILES := \ dgif_lib.c \ -egif_lib.c \ gif_hash.c \ gifalloc.c \ openbsd-reallocarray.c diff --git a/app/src/main/jni/giflib/dgif_lib.c b/app/src/main/jni/giflib/dgif_lib.c index 91c4a89e2..b0959d42e 100644 --- a/app/src/main/jni/giflib/dgif_lib.c +++ b/app/src/main/jni/giflib/dgif_lib.c @@ -97,6 +97,9 @@ DGifOpenFileHandle(int FileHandle, int *Error) free((char *)GifFile); return NULL; } + + /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType)); + #ifdef _WIN32 _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ #endif /* _WIN32 */ @@ -179,6 +182,7 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) free((char *)GifFile); return NULL; } + /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType)); GifFile->Private = (void *)Private; Private->FileHandle = 0; @@ -764,7 +768,7 @@ DGifSetupDecompress(GifFileType *GifFile) BitsPerPixel = CodeSize; /* this can only happen on a severely malformed GIF */ - if (BitsPerPixel > 8 || Private->RunningBits > 32) { + if (BitsPerPixel > 8) { GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */ return GIF_ERROR; /* Failed to read Code size. */ } @@ -1229,19 +1233,19 @@ DGifGlance(GifFileType *GifFile) if (sp->ImageDesc.Interlace) { int i, j; - /* - * The way an interlaced image should be read - + /* + * 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]; + for (j = InterlacedOffset[i]; j < sp->ImageDesc.Height; j += InterlacedJumps[i]) { - if (DGifGetLine(GifFile, - sp->RasterBits+j*sp->ImageDesc.Width, + if (DGifGetLine(GifFile, + sp->RasterBits+j*sp->ImageDesc.Width, sp->ImageDesc.Width) == GIF_ERROR) return GIF_ERROR; } @@ -1266,7 +1270,7 @@ DGifGlance(GifFileType *GifFile) /* Create an extension block with our data */ if (ExtData != NULL) { if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, + &GifFile->ExtensionBlocks, ExtFunction, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); @@ -1278,7 +1282,7 @@ DGifGlance(GifFileType *GifFile) if (ExtData != NULL) if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks, - CONTINUE_EXT_FUNC_CODE, + CONTINUE_EXT_FUNC_CODE, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); } diff --git a/app/src/main/jni/giflib/egif_lib.c b/app/src/main/jni/giflib/egif_lib.c deleted file mode 100644 index 39a62b2ef..000000000 --- a/app/src/main/jni/giflib/egif_lib.c +++ /dev/null @@ -1,1150 +0,0 @@ -/****************************************************************************** - -egif_lib.c - GIF encoding - -The functions here and in dgif_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! - -*****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#endif /* _WIN32 */ -#include - -#include "gif_lib.h" -#include "gif_lib_private.h" - -/* Masks given codes to BitsPerPixel, to make sure all codes are in range: */ -/*@+charint@*/ -static const GifPixelType CodeMask[] = { - 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff -}; -/*@-charint@*/ - -static int EGifPutWord(int Word, GifFileType * GifFile); -static int EGifSetupCompress(GifFileType * GifFile); -static int EGifCompressLine(GifFileType * GifFile, GifPixelType * Line, - int LineLen); -static int EGifCompressOutput(GifFileType * GifFile, int Code); -static int EGifBufferedOutput(GifFileType * GifFile, GifByteType * Buf, - int c); - -/* extract bytes from an unsigned word */ -#define LOBYTE(x) ((x) & 0xff) -#define HIBYTE(x) (((x) >> 8) & 0xff) - -/****************************************************************************** - Open a new GIF file for write, specified by name. If TestExistance then - if the file exists this routines fails (returns NULL). - Returns a dynamically allocated GifFileType pointer which serves as the GIF - info record. The Error member is cleared if successful. -******************************************************************************/ -GifFileType * -EGifOpenFileName(const char *FileName, const bool TestExistence, int *Error) -{ - - int FileHandle; - GifFileType *GifFile; - - if (TestExistence) - FileHandle = open(FileName, O_WRONLY | O_CREAT | O_EXCL, - S_IREAD | S_IWRITE); - else - FileHandle = open(FileName, O_WRONLY | O_CREAT | O_TRUNC, - S_IREAD | S_IWRITE); - - if (FileHandle == -1) { - if (Error != NULL) - *Error = E_GIF_ERR_OPEN_FAILED; - return NULL; - } - GifFile = EGifOpenFileHandle(FileHandle, Error); - if (GifFile == (GifFileType *) NULL) - (void)close(FileHandle); - return GifFile; -} - -/****************************************************************************** - Update a new GIF file, given its file handle, which must be opened for - write in binary mode. - Returns dynamically allocated a GifFileType pointer which serves as the GIF - info record. - Only fails on a memory allocation error. -******************************************************************************/ -GifFileType * -EGifOpenFileHandle(const int FileHandle, int *Error) -{ - GifFileType *GifFile; - GifFilePrivateType *Private; - FILE *f; - - GifFile = (GifFileType *) malloc(sizeof(GifFileType)); - if (GifFile == NULL) { - return NULL; - } - - memset(GifFile, '\0', sizeof(GifFileType)); - - Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); - if (Private == NULL) { - free(GifFile); - if (Error != NULL) - *Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return NULL; - } - if ((Private->HashTable = _InitHashTable()) == NULL) { - free(GifFile); - free(Private); - if (Error != NULL) - *Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return NULL; - } - -#ifdef _WIN32 - _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ -#endif /* _WIN32 */ - - f = fdopen(FileHandle, "wb"); /* Make it into a stream: */ - - GifFile->Private = (void *)Private; - Private->FileHandle = FileHandle; - Private->File = f; - Private->FileState = FILE_STATE_WRITE; - - Private->Write = (OutputFunc) 0; /* No user write routine (MRB) */ - GifFile->UserData = (void *)NULL; /* No user write handle (MRB) */ - - GifFile->Error = 0; - - return GifFile; -} - -/****************************************************************************** - Output constructor that takes user supplied output function. - Basically just a copy of EGifOpenFileHandle. (MRB) -******************************************************************************/ -GifFileType * -EGifOpen(void *userData, OutputFunc writeFunc, int *Error) -{ - GifFileType *GifFile; - GifFilePrivateType *Private; - - GifFile = (GifFileType *)malloc(sizeof(GifFileType)); - if (GifFile == NULL) { - if (Error != NULL) - *Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return NULL; - } - - memset(GifFile, '\0', sizeof(GifFileType)); - - Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); - if (Private == NULL) { - free(GifFile); - if (Error != NULL) - *Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return NULL; - } - - Private->HashTable = _InitHashTable(); - if (Private->HashTable == NULL) { - free (GifFile); - free (Private); - if (Error != NULL) - *Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return NULL; - } - - GifFile->Private = (void *)Private; - Private->FileHandle = 0; - Private->File = (FILE *) 0; - Private->FileState = FILE_STATE_WRITE; - - Private->Write = writeFunc; /* User write routine (MRB) */ - GifFile->UserData = userData; /* User write handle (MRB) */ - - Private->gif89 = false; /* initially, write GIF87 */ - - GifFile->Error = 0; - - return GifFile; -} - -/****************************************************************************** - Routine to compute the GIF version that will be written on output. -******************************************************************************/ -const char * -EGifGetGifVersion(GifFileType *GifFile) -{ - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - int i, j; - - /* - * Bulletproofing - always write GIF89 if we need to. - * Note, we don't clear the gif89 flag here because - * users of the sequential API might have called EGifSetGifVersion() - * in order to set that flag. - */ - for (i = 0; i < GifFile->ImageCount; i++) { - for (j = 0; j < GifFile->SavedImages[i].ExtensionBlockCount; j++) { - int function = - GifFile->SavedImages[i].ExtensionBlocks[j].Function; - - if (function == COMMENT_EXT_FUNC_CODE - || function == GRAPHICS_EXT_FUNC_CODE - || function == PLAINTEXT_EXT_FUNC_CODE - || function == APPLICATION_EXT_FUNC_CODE) - Private->gif89 = true; - } - } - for (i = 0; i < GifFile->ExtensionBlockCount; i++) { - int function = GifFile->ExtensionBlocks[i].Function; - - if (function == COMMENT_EXT_FUNC_CODE - || function == GRAPHICS_EXT_FUNC_CODE - || function == PLAINTEXT_EXT_FUNC_CODE - || function == APPLICATION_EXT_FUNC_CODE) - Private->gif89 = true; - } - - if (Private->gif89) - return GIF89_STAMP; - else - return GIF87_STAMP; -} - -/****************************************************************************** - Set the GIF version. In the extremely unlikely event that there is ever - another version, replace the bool argument with an enum in which the - GIF87 value is 0 (numerically the same as bool false) and the GIF89 value - is 1 (numerically the same as bool true). That way we'll even preserve - object-file compatibility! -******************************************************************************/ -void EGifSetGifVersion(GifFileType *GifFile, const bool gif89) -{ - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - Private->gif89 = gif89; -} - -/****************************************************************************** - All writes to the GIF should go through this. -******************************************************************************/ -static int InternalWrite(GifFileType *GifFileOut, - const unsigned char *buf, size_t len) -{ - GifFilePrivateType *Private = (GifFilePrivateType*)GifFileOut->Private; - if (Private->Write) - return Private->Write(GifFileOut,buf,len); - else - return fwrite(buf, 1, len, Private->File); -} - -/****************************************************************************** - This routine should be called before any other EGif calls, immediately - following the GIF file opening. -******************************************************************************/ -int -EGifPutScreenDesc(GifFileType *GifFile, - const int Width, - const int Height, - const int ColorRes, - const int BackGround, - const ColorMapObject *ColorMap) -{ - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - const char *write_version; - - if (Private->FileState & FILE_STATE_SCREEN) { - /* If already has screen descriptor - something is wrong! */ - GifFile->Error = E_GIF_ERR_HAS_SCRN_DSCR; - return GIF_ERROR; - } - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - write_version = EGifGetGifVersion(GifFile); - - /* First write the version prefix into the file. */ - if (InternalWrite(GifFile, (unsigned char *)write_version, - strlen(write_version)) != strlen(write_version)) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - - GifFile->SWidth = Width; - GifFile->SHeight = Height; - GifFile->SColorResolution = ColorRes; - GifFile->SBackGroundColor = BackGround; - if (ColorMap) { - GifFile->SColorMap = GifMakeMapObject(ColorMap->ColorCount, - ColorMap->Colors); - if (GifFile->SColorMap == NULL) { - GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } else - GifFile->SColorMap = NULL; - - /* - * Put the logical screen descriptor into the file: - */ - /* Logical Screen Descriptor: Dimensions */ - (void)EGifPutWord(Width, GifFile); - (void)EGifPutWord(Height, GifFile); - - /* Logical Screen Descriptor: Packed Fields */ - /* Note: We have actual size of the color table default to the largest - * possible size (7+1 == 8 bits) because the decoder can use it to decide - * how to display the files. - */ - Buf[0] = (ColorMap ? 0x80 : 0x00) | /* Yes/no global colormap */ - ((ColorRes - 1) << 4) | /* Bits allocated to each primary color */ - (ColorMap ? ColorMap->BitsPerPixel - 1 : 0x07 ); /* Actual size of the - color table. */ - if (ColorMap != NULL && ColorMap->SortFlag) - Buf[0] |= 0x08; - Buf[1] = BackGround; /* Index into the ColorTable for background color */ - Buf[2] = GifFile->AspectByte; /* Pixel Aspect Ratio */ - InternalWrite(GifFile, Buf, 3); - - /* If we have Global color map - dump it also: */ - if (ColorMap != NULL) { - int i; - for (i = 0; i < ColorMap->ColorCount; i++) { - /* Put the ColorMap out also: */ - Buf[0] = ColorMap->Colors[i].Red; - Buf[1] = ColorMap->Colors[i].Green; - Buf[2] = ColorMap->Colors[i].Blue; - if (InternalWrite(GifFile, Buf, 3) != 3) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - } - } - - /* Mark this file as has screen descriptor, and no pixel written yet: */ - Private->FileState |= FILE_STATE_SCREEN; - - return GIF_OK; -} - -/****************************************************************************** - This routine should be called before any attempt to dump an image - any - call to any of the pixel dump routines. -******************************************************************************/ -int -EGifPutImageDesc(GifFileType *GifFile, - const int Left, - const int Top, - const int Width, - const int Height, - const bool Interlace, - const ColorMapObject *ColorMap) -{ - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (Private->FileState & FILE_STATE_IMAGE && - Private->PixelCount > 0xffff0000UL) { - /* If already has active image descriptor - something is wrong! */ - GifFile->Error = E_GIF_ERR_HAS_IMAG_DSCR; - return GIF_ERROR; - } - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - GifFile->Image.Left = Left; - GifFile->Image.Top = Top; - GifFile->Image.Width = Width; - 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) { - GifFile->Error = E_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } else { - GifFile->Image.ColorMap = NULL; - } - - /* Put the image descriptor into the file: */ - Buf[0] = DESCRIPTOR_INTRODUCER; /* Image separator character. */ - InternalWrite(GifFile, Buf, 1); - (void)EGifPutWord(Left, GifFile); - (void)EGifPutWord(Top, GifFile); - (void)EGifPutWord(Width, GifFile); - (void)EGifPutWord(Height, GifFile); - Buf[0] = (ColorMap ? 0x80 : 0x00) | - (Interlace ? 0x40 : 0x00) | - (ColorMap ? ColorMap->BitsPerPixel - 1 : 0); - InternalWrite(GifFile, Buf, 1); - - /* If we have Global color map - dump it also: */ - if (ColorMap != NULL) { - int i; - for (i = 0; i < ColorMap->ColorCount; i++) { - /* Put the ColorMap out also: */ - Buf[0] = ColorMap->Colors[i].Red; - Buf[1] = ColorMap->Colors[i].Green; - Buf[2] = ColorMap->Colors[i].Blue; - if (InternalWrite(GifFile, Buf, 3) != 3) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - } - } - if (GifFile->SColorMap == NULL && GifFile->Image.ColorMap == NULL) { - GifFile->Error = E_GIF_ERR_NO_COLOR_MAP; - return GIF_ERROR; - } - - /* Mark this file as has screen descriptor: */ - Private->FileState |= FILE_STATE_IMAGE; - Private->PixelCount = (long)Width *(long)Height; - - /* Reset compress algorithm parameters. */ - (void)EGifSetupCompress(GifFile); - - return GIF_OK; -} - -/****************************************************************************** - Put one full scanned line (Line) of length LineLen into GIF file. -******************************************************************************/ -int -EGifPutLine(GifFileType * GifFile, GifPixelType *Line, int LineLen) -{ - int i; - GifPixelType Mask; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - if (!LineLen) - LineLen = GifFile->Image.Width; - if (Private->PixelCount < (unsigned)LineLen) { - GifFile->Error = E_GIF_ERR_DATA_TOO_BIG; - return GIF_ERROR; - } - Private->PixelCount -= LineLen; - - /* Make sure the codes are not out of bit range, as we might generate - * wrong code (because of overflow when we combine them) in this case: */ - Mask = CodeMask[Private->BitsPerPixel]; - for (i = 0; i < LineLen; i++) - Line[i] &= Mask; - - return EGifCompressLine(GifFile, Line, LineLen); -} - -/****************************************************************************** - Put one pixel (Pixel) into GIF file. -******************************************************************************/ -int -EGifPutPixel(GifFileType *GifFile, GifPixelType Pixel) -{ - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - if (Private->PixelCount == 0) { - GifFile->Error = E_GIF_ERR_DATA_TOO_BIG; - return GIF_ERROR; - } - --Private->PixelCount; - - /* Make sure the code is not out of bit range, as we might generate - * wrong code (because of overflow when we combine them) in this case: */ - Pixel &= CodeMask[Private->BitsPerPixel]; - - return EGifCompressLine(GifFile, &Pixel, 1); -} - -/****************************************************************************** - Put a comment into GIF file using the GIF89 comment extension block. -******************************************************************************/ -int -EGifPutComment(GifFileType *GifFile, const char *Comment) -{ - unsigned int length; - char *buf; - - length = strlen(Comment); - if (length <= 255) { - return EGifPutExtension(GifFile, COMMENT_EXT_FUNC_CODE, - length, Comment); - } else { - buf = (char *)Comment; - if (EGifPutExtensionLeader(GifFile, COMMENT_EXT_FUNC_CODE) - == GIF_ERROR) { - return GIF_ERROR; - } - - /* Break the comment into 255 byte sub blocks */ - while (length > 255) { - if (EGifPutExtensionBlock(GifFile, 255, buf) == GIF_ERROR) { - return GIF_ERROR; - } - buf = buf + 255; - length -= 255; - } - /* Output any partial block and the clear code. */ - if (length > 0) { - if (EGifPutExtensionBlock(GifFile, length, buf) == GIF_ERROR) { - return GIF_ERROR; - } - } - if (EGifPutExtensionTrailer(GifFile) == GIF_ERROR) { - return GIF_ERROR; - } - } - return GIF_OK; -} - -/****************************************************************************** - Begin an extension block (see GIF manual). More - extensions can be dumped using EGifPutExtensionBlock until - EGifPutExtensionTrailer is invoked. -******************************************************************************/ -int -EGifPutExtensionLeader(GifFileType *GifFile, const int ExtCode) -{ - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - Buf[0] = EXTENSION_INTRODUCER; - Buf[1] = ExtCode; - InternalWrite(GifFile, Buf, 2); - - return GIF_OK; -} - -/****************************************************************************** - Put extension block data (see GIF manual) into a GIF file. -******************************************************************************/ -int -EGifPutExtensionBlock(GifFileType *GifFile, - const int ExtLen, - const void *Extension) -{ - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - Buf = ExtLen; - InternalWrite(GifFile, &Buf, 1); - InternalWrite(GifFile, Extension, ExtLen); - - return GIF_OK; -} - -/****************************************************************************** - Put a terminating block (see GIF manual) into a GIF file. -******************************************************************************/ -int -EGifPutExtensionTrailer(GifFileType *GifFile) { - - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - /* Write the block terminator */ - Buf = 0; - InternalWrite(GifFile, &Buf, 1); - - return GIF_OK; -} - -/****************************************************************************** - Put an extension block (see GIF manual) into a GIF file. - Warning: This function is only useful for Extension blocks that have at - most one subblock. Extensions with more than one subblock need to use the - EGifPutExtension{Leader,Block,Trailer} functions instead. -******************************************************************************/ -int -EGifPutExtension(GifFileType *GifFile, - const int ExtCode, - const int ExtLen, - const void *Extension) { - - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - if (ExtCode == 0) - InternalWrite(GifFile, (GifByteType *)&ExtLen, 1); - else { - Buf[0] = EXTENSION_INTRODUCER; - Buf[1] = ExtCode; /* Extension Label */ - Buf[2] = ExtLen; /* Extension length */ - InternalWrite(GifFile, Buf, 3); - } - InternalWrite(GifFile, Extension, ExtLen); - Buf[0] = 0; - InternalWrite(GifFile, Buf, 1); - - return GIF_OK; -} - -/****************************************************************************** - Render a Graphics Control Block as raw extension data -******************************************************************************/ - -size_t EGifGCBToExtension(const GraphicsControlBlock *GCB, - GifByteType *GifExtension) -{ - GifExtension[0] = 0; - GifExtension[0] |= (GCB->TransparentColor == NO_TRANSPARENT_COLOR) ? 0x00 : 0x01; - GifExtension[0] |= GCB->UserInputFlag ? 0x02 : 0x00; - GifExtension[0] |= ((GCB->DisposalMode & 0x07) << 2); - GifExtension[1] = LOBYTE(GCB->DelayTime); - GifExtension[2] = HIBYTE(GCB->DelayTime); - GifExtension[3] = (char)GCB->TransparentColor; - return 4; -} - -/****************************************************************************** - Replace the Graphics Control Block for a saved image, if it exists. -******************************************************************************/ - -int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, - GifFileType *GifFile, int ImageIndex) -{ - int i; - size_t Len; - GifByteType buf[sizeof(GraphicsControlBlock)]; /* a bit dodgy... */ - - if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) - return GIF_ERROR; - - for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) { - ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; - if (ep->Function == GRAPHICS_EXT_FUNC_CODE) { - EGifGCBToExtension(GCB, ep->Bytes); - return GIF_OK; - } - } - - Len = EGifGCBToExtension(GCB, (GifByteType *)buf); - if (GifAddExtensionBlock(&GifFile->SavedImages[ImageIndex].ExtensionBlockCount, - &GifFile->SavedImages[ImageIndex].ExtensionBlocks, - GRAPHICS_EXT_FUNC_CODE, - Len, - (unsigned char *)buf) == GIF_ERROR) - return (GIF_ERROR); - - return (GIF_OK); -} - -/****************************************************************************** - Put 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 EGifPutCodeNext, until NULL block is given. - The block should NOT be freed by the user (not dynamically allocated). -******************************************************************************/ -int -EGifPutCode(GifFileType *GifFile, int CodeSize, const GifByteType *CodeBlock) -{ - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; - return GIF_ERROR; - } - - /* No need to dump code size as Compression set up does any for us: */ - /* - * Buf = CodeSize; - * if (InternalWrite(GifFile, &Buf, 1) != 1) { - * GifFile->Error = E_GIF_ERR_WRITE_FAILED; - * return GIF_ERROR; - * } - */ - - return EGifPutCodeNext(GifFile, CodeBlock); -} - -/****************************************************************************** - Continue to put the image code in compressed form. This routine should be - called with blocks of code as read via DGifGetCode/DGifGetCodeNext. If - given buffer pointer is NULL, empty block is written to mark end of code. -******************************************************************************/ -int -EGifPutCodeNext(GifFileType *GifFile, const GifByteType *CodeBlock) -{ - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (CodeBlock != NULL) { - if (InternalWrite(GifFile, CodeBlock, CodeBlock[0] + 1) - != (unsigned)(CodeBlock[0] + 1)) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - } else { - Buf = 0; - if (InternalWrite(GifFile, &Buf, 1) != 1) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - Private->PixelCount = 0; /* And local info. indicate image read. */ - } - - return GIF_OK; -} - -/****************************************************************************** - This routine should be called last, to close the GIF file. -******************************************************************************/ -int -EGifCloseFile(GifFileType *GifFile, int *ErrorCode) -{ - GifByteType Buf; - GifFilePrivateType *Private; - FILE *File; - - if (GifFile == NULL) - return GIF_ERROR; - - Private = (GifFilePrivateType *) GifFile->Private; - if (Private == NULL) - return GIF_ERROR; - if (!IS_WRITEABLE(Private)) { - /* This file was NOT open for writing: */ - if (ErrorCode != NULL) - *ErrorCode = E_GIF_ERR_NOT_WRITEABLE; - free(GifFile); - return GIF_ERROR; - } - - File = Private->File; - - Buf = TERMINATOR_INTRODUCER; - InternalWrite(GifFile, &Buf, 1); - - if (GifFile->Image.ColorMap) { - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - if (GifFile->SColorMap) { - GifFreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - } - if (Private) { - if (Private->HashTable) { - free((char *) Private->HashTable); - } - free((char *) Private); - } - - if (File && fclose(File) != 0) { - if (ErrorCode != NULL) - *ErrorCode = E_GIF_ERR_CLOSE_FAILED; - free(GifFile); - return GIF_ERROR; - } - - free(GifFile); - if (ErrorCode != NULL) - *ErrorCode = E_GIF_SUCCEEDED; - return GIF_OK; -} - -/****************************************************************************** - Put 2 bytes (a word) into the given file in little-endian order: -******************************************************************************/ -static int -EGifPutWord(int Word, GifFileType *GifFile) -{ - unsigned char c[2]; - - c[0] = LOBYTE(Word); - c[1] = HIBYTE(Word); - if (InternalWrite(GifFile, c, 2) == 2) - return GIF_OK; - else - return GIF_ERROR; -} - -/****************************************************************************** - Setup the LZ compression for this image: -******************************************************************************/ -static int -EGifSetupCompress(GifFileType *GifFile) -{ - int BitsPerPixel; - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - /* Test and see what color map to use, and from it # bits per pixel: */ - if (GifFile->Image.ColorMap) - BitsPerPixel = GifFile->Image.ColorMap->BitsPerPixel; - else if (GifFile->SColorMap) - BitsPerPixel = GifFile->SColorMap->BitsPerPixel; - else { - GifFile->Error = E_GIF_ERR_NO_COLOR_MAP; - return GIF_ERROR; - } - - Buf = BitsPerPixel = (BitsPerPixel < 2 ? 2 : BitsPerPixel); - InternalWrite(GifFile, &Buf, 1); /* Write the Code size to file. */ - - Private->Buf[0] = 0; /* Nothing was output yet. */ - Private->BitsPerPixel = BitsPerPixel; - Private->ClearCode = (1 << BitsPerPixel); - Private->EOFCode = Private->ClearCode + 1; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ - Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ - Private->CrntCode = FIRST_CODE; /* Signal that this is first one! */ - Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ - Private->CrntShiftDWord = 0; - - /* Clear hash table and send Clear to make sure the decoder do the same. */ - _ClearHashTable(Private->HashTable); - - if (EGifCompressOutput(GifFile, Private->ClearCode) == GIF_ERROR) { - GifFile->Error = E_GIF_ERR_DISK_IS_FULL; - return GIF_ERROR; - } - return GIF_OK; -} - -/****************************************************************************** - The LZ compression routine: - This version compresses the given buffer Line of length LineLen. - This routine can be called a few times (one per scan line, for example), in - order to complete the whole image. -******************************************************************************/ -static int -EGifCompressLine(GifFileType *GifFile, - GifPixelType *Line, - const int LineLen) -{ - int i = 0, CrntCode, NewCode; - unsigned long NewKey; - GifPixelType Pixel; - GifHashTableType *HashTable; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - HashTable = Private->HashTable; - - if (Private->CrntCode == FIRST_CODE) /* Its first time! */ - CrntCode = Line[i++]; - else - CrntCode = Private->CrntCode; /* Get last code in compression. */ - - while (i < LineLen) { /* Decode LineLen items. */ - Pixel = Line[i++]; /* Get next pixel from stream. */ - /* Form a new unique key to search hash table for the code combines - * CrntCode as Prefix string with Pixel as postfix char. - */ - NewKey = (((uint32_t) CrntCode) << 8) + Pixel; - if ((NewCode = _ExistsHashTable(HashTable, NewKey)) >= 0) { - /* This Key is already there, or the string is old one, so - * simple take new code as our CrntCode: - */ - CrntCode = NewCode; - } else { - /* Put it in hash table, output the prefix code, and make our - * CrntCode equal to Pixel. - */ - if (EGifCompressOutput(GifFile, CrntCode) == GIF_ERROR) { - GifFile->Error = E_GIF_ERR_DISK_IS_FULL; - return GIF_ERROR; - } - CrntCode = Pixel; - - /* If however the HashTable if full, we send a clear first and - * Clear the hash table. - */ - if (Private->RunningCode >= LZ_MAX_CODE) { - /* Time to do some clearance: */ - if (EGifCompressOutput(GifFile, Private->ClearCode) - == GIF_ERROR) { - GifFile->Error = E_GIF_ERR_DISK_IS_FULL; - return GIF_ERROR; - } - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - _ClearHashTable(HashTable); - } else { - /* Put this unique key with its relative Code in hash table: */ - _InsertHashTable(HashTable, NewKey, Private->RunningCode++); - } - } - - } - - /* Preserve the current state of the compression algorithm: */ - Private->CrntCode = CrntCode; - - if (Private->PixelCount == 0) { - /* We are done - output last Code and flush output buffers: */ - if (EGifCompressOutput(GifFile, CrntCode) == GIF_ERROR) { - GifFile->Error = E_GIF_ERR_DISK_IS_FULL; - return GIF_ERROR; - } - if (EGifCompressOutput(GifFile, Private->EOFCode) == GIF_ERROR) { - GifFile->Error = E_GIF_ERR_DISK_IS_FULL; - return GIF_ERROR; - } - if (EGifCompressOutput(GifFile, FLUSH_OUTPUT) == GIF_ERROR) { - GifFile->Error = E_GIF_ERR_DISK_IS_FULL; - return GIF_ERROR; - } - } - - return GIF_OK; -} - -/****************************************************************************** - The LZ compression output routine: - This routine is responsible for the compression of the bit stream into - 8 bits (bytes) packets. - Returns GIF_OK if written successfully. -******************************************************************************/ -static int -EGifCompressOutput(GifFileType *GifFile, - const int Code) -{ - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - int retval = GIF_OK; - - if (Code == FLUSH_OUTPUT) { - while (Private->CrntShiftState > 0) { - /* Get Rid of what is left in DWord, and flush it. */ - if (EGifBufferedOutput(GifFile, Private->Buf, - Private->CrntShiftDWord & 0xff) == GIF_ERROR) - retval = GIF_ERROR; - Private->CrntShiftDWord >>= 8; - Private->CrntShiftState -= 8; - } - Private->CrntShiftState = 0; /* For next time. */ - if (EGifBufferedOutput(GifFile, Private->Buf, - FLUSH_OUTPUT) == GIF_ERROR) - retval = GIF_ERROR; - } else { - Private->CrntShiftDWord |= ((long)Code) << Private->CrntShiftState; - Private->CrntShiftState += Private->RunningBits; - while (Private->CrntShiftState >= 8) { - /* Dump out full bytes: */ - if (EGifBufferedOutput(GifFile, Private->Buf, - Private->CrntShiftDWord & 0xff) == GIF_ERROR) - retval = GIF_ERROR; - Private->CrntShiftDWord >>= 8; - Private->CrntShiftState -= 8; - } - } - - /* If code cannt fit into RunningBits bits, must raise its size. Note */ - /* however that codes above 4095 are used for special signaling. */ - if (Private->RunningCode >= Private->MaxCode1 && Code <= 4095) { - Private->MaxCode1 = 1 << ++Private->RunningBits; - } - - return retval; -} - -/****************************************************************************** - This routines buffers the given characters until 255 characters are ready - to be output. If Code is equal to -1 the buffer is flushed (EOF). - The buffer is Dumped with first byte as its size, as GIF format requires. - Returns GIF_OK if written successfully. -******************************************************************************/ -static int -EGifBufferedOutput(GifFileType *GifFile, - GifByteType *Buf, - int c) -{ - if (c == FLUSH_OUTPUT) { - /* Flush everything out. */ - if (Buf[0] != 0 - && InternalWrite(GifFile, Buf, Buf[0] + 1) != (unsigned)(Buf[0] + 1)) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - /* Mark end of compressed data, by an empty block (see GIF doc): */ - Buf[0] = 0; - if (InternalWrite(GifFile, Buf, 1) != 1) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - } else { - if (Buf[0] == 255) { - /* Dump out this buffer - it is full: */ - if (InternalWrite(GifFile, Buf, Buf[0] + 1) != (unsigned)(Buf[0] + 1)) { - GifFile->Error = E_GIF_ERR_WRITE_FAILED; - return GIF_ERROR; - } - Buf[0] = 0; - } - Buf[++Buf[0]] = c; - } - - return GIF_OK; -} - -/****************************************************************************** - This routine writes to disk an in-core representation of a GIF previously - created by DGifSlurp(). -******************************************************************************/ - -static int -EGifWriteExtensions(GifFileType *GifFileOut, - ExtensionBlock *ExtensionBlocks, - int ExtensionBlockCount) -{ - if (ExtensionBlocks) { - ExtensionBlock *ep; - int j; - - for (j = 0; j < ExtensionBlockCount; j++) { - ep = &ExtensionBlocks[j]; - if (ep->Function != CONTINUE_EXT_FUNC_CODE) - if (EGifPutExtensionLeader(GifFileOut, ep->Function) == GIF_ERROR) - return (GIF_ERROR); - if (EGifPutExtensionBlock(GifFileOut, ep->ByteCount, ep->Bytes) == GIF_ERROR) - return (GIF_ERROR); - if (j == ExtensionBlockCount - 1 || (ep+1)->Function != CONTINUE_EXT_FUNC_CODE) - if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR) - return (GIF_ERROR); - } - } - - return (GIF_OK); -} - -int -EGifSpew(GifFileType *GifFileOut) -{ - int i, j; - - if (EGifPutScreenDesc(GifFileOut, - GifFileOut->SWidth, - GifFileOut->SHeight, - GifFileOut->SColorResolution, - GifFileOut->SBackGroundColor, - GifFileOut->SColorMap) == GIF_ERROR) { - return (GIF_ERROR); - } - - for (i = 0; i < GifFileOut->ImageCount; i++) { - SavedImage *sp = &GifFileOut->SavedImages[i]; - int SavedHeight = sp->ImageDesc.Height; - int SavedWidth = sp->ImageDesc.Width; - - /* this allows us to delete images by nuking their rasters */ - if (sp->RasterBits == NULL) - continue; - - if (EGifWriteExtensions(GifFileOut, - sp->ExtensionBlocks, - sp->ExtensionBlockCount) == GIF_ERROR) - return (GIF_ERROR); - - if (EGifPutImageDesc(GifFileOut, - sp->ImageDesc.Left, - sp->ImageDesc.Top, - SavedWidth, - SavedHeight, - sp->ImageDesc.Interlace, - sp->ImageDesc.ColorMap) == GIF_ERROR) - return (GIF_ERROR); - - if (sp->ImageDesc.Interlace) { - /* - * The way an interlaced image should be written - - * offsets and jumps... - */ - int InterlacedOffset[] = { 0, 4, 2, 1 }; - int InterlacedJumps[] = { 8, 8, 4, 2 }; - int k; - /* Need to perform 4 passes on the images: */ - for (k = 0; k < 4; k++) - for (j = InterlacedOffset[k]; - j < SavedHeight; - j += InterlacedJumps[k]) { - if (EGifPutLine(GifFileOut, - sp->RasterBits + j * SavedWidth, - SavedWidth) == GIF_ERROR) - return (GIF_ERROR); - } - } else { - for (j = 0; j < SavedHeight; j++) { - if (EGifPutLine(GifFileOut, - sp->RasterBits + j * SavedWidth, - SavedWidth) == GIF_ERROR) - return (GIF_ERROR); - } - } - } - - if (EGifWriteExtensions(GifFileOut, - GifFileOut->ExtensionBlocks, - GifFileOut->ExtensionBlockCount) == GIF_ERROR) - return (GIF_ERROR); - - if (EGifCloseFile(GifFileOut, NULL) == GIF_ERROR) - return (GIF_ERROR); - - return (GIF_OK); -} - -/* end */ diff --git a/app/src/main/jni/giflib/gif_lib.h b/app/src/main/jni/giflib/gif_lib.h index 0293e09a1..7d639206d 100644 --- a/app/src/main/jni/giflib/gif_lib.h +++ b/app/src/main/jni/giflib/gif_lib.h @@ -13,7 +13,7 @@ extern "C" { #define GIFLIB_MAJOR 5 #define GIFLIB_MINOR 1 -#define GIFLIB_RELEASE 2 +#define GIFLIB_RELEASE 3 #define GIF_ERROR 0 #define GIF_OK 1