diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:25 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:25 -0800 |
commit | f015ec9ad03a8c22f423638c5338da0a185c5235 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /dgif_lib.c | |
parent | ff6a75e423d8333c6657e4a66494e0bc9ed34385 (diff) | |
download | android_external_giflib-f015ec9ad03a8c22f423638c5338da0a185c5235.tar.gz android_external_giflib-f015ec9ad03a8c22f423638c5338da0a185c5235.tar.bz2 android_external_giflib-f015ec9ad03a8c22f423638c5338da0a185c5235.zip |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'dgif_lib.c')
-rw-r--r-- | dgif_lib.c | 1098 |
1 files changed, 0 insertions, 1098 deletions
diff --git a/dgif_lib.c b/dgif_lib.c deleted file mode 100644 index 760d053..0000000 --- a/dgif_lib.c +++ /dev/null @@ -1,1098 +0,0 @@ -/****************************************************************************** - * "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 - -#ifdef HAVE_FCNTL_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> -#include "gif_lib.h" -#include "gif_lib_private.h" - -#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for - comment. */ - -/* avoid extra function call in case we use fread (TVT) */ -#define READ(_gif,_buf,_len) \ - (((GifFilePrivateType*)_gif->Private)->Read ? \ - ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \ - fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File)) - -static int DGifGetWord(GifFileType *GifFile, GifWord *Word); -static int DGifSetupDecompress(GifFileType *GifFile); -static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, - int LineLen); -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. - *****************************************************************************/ -GifFileType * -DGifOpenFileName(const char *FileName) { - 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; - return NULL; - } - - GifFile = DGifOpenFileHandle(FileHandle); - 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. - *****************************************************************************/ -GifFileType * -DGifOpenFileHandle(int FileHandle) { - - unsigned 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); - return NULL; - } - - memset(GifFile, '\0', sizeof(GifFileType)); - - Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); - if (Private == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - 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__ */ - - 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; - 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); - 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; - if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - _GifError = D_GIF_ERR_NOT_GIF_FILE; - fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - _GifError = 0; - - return GifFile; -} - -#endif /* _GBA_NO_FILEIO */ - -/****************************************************************************** - * GifFileType constructor with user supplied input function (TVT) - *****************************************************************************/ -GifFileType * -DGifOpen(void *userData, - InputFunc readFunc) { - - unsigned 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; - return NULL; - } - - memset(GifFile, '\0', sizeof(GifFileType)); - - Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); - if (!Private) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - free((char *)GifFile); - return NULL; - } - - GifFile->Private = (VoidPtr)Private; - Private->FileHandle = 0; - Private->File = 0; - 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; - 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; - if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - _GifError = D_GIF_ERR_NOT_GIF_FILE; - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - free((char *)Private); - free((char *)GifFile); - return NULL; - } - - _GifError = 0; - - return GifFile; -} - -/****************************************************************************** - * 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; - 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; - return GIF_ERROR; - } - - /* Put the screen descriptor into the file: */ - if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) - return GIF_ERROR; - - if (READ(GifFile, Buf, 3) != 3) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->SBackGroundColor = Buf[1]; - if (Buf[0] & 0x80) { /* Do we have global color map? */ - - GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->SColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - - /* Get the global color map: */ - for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { - if (READ(GifFile, Buf, 3) != 3) { - FreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - GifFile->SColorMap->Colors[i].Red = Buf[0]; - GifFile->SColorMap->Colors[i].Green = Buf[1]; - GifFile->SColorMap->Colors[i].Blue = Buf[2]; - } - } else { - GifFile->SColorMap = NULL; - } - - return GIF_OK; -} - -/****************************************************************************** - * This routine should be called before any attempt to read an image. - *****************************************************************************/ -int -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; - return GIF_ERROR; - } - - if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - switch (Buf) { - case ',': - *Type = IMAGE_DESC_RECORD_TYPE; - break; - case '!': - *Type = EXTENSION_RECORD_TYPE; - break; - case ';': - *Type = TERMINATE_RECORD_TYPE; - break; - default: - *Type = UNDEFINED_RECORD_TYPE; - _GifError = D_GIF_ERR_WRONG_RECORD; - return GIF_ERROR; - } - - return GIF_OK; -} - -/****************************************************************************** - * 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; - 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; - return GIF_ERROR; - } - - if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) - return GIF_ERROR; - if (READ(GifFile, Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; - 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? */ - - /*** 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); - - GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->Image.ColorMap == NULL) { - _GifError = 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; - GifFile->Image.ColorMap = NULL; - return GIF_ERROR; - } - GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; - 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; - return GIF_ERROR; - } - } else { - if ((GifFile->SavedImages = - (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } - - sp = &GifFile->SavedImages[GifFile->ImageCount]; - memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); - if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = MakeMapObject( - GifFile->Image.ColorMap->ColorCount, - GifFile->Image.ColorMap->Colors); - if (sp->ImageDesc.ColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; - } - } - sp->RasterBits = (unsigned char *)NULL; - sp->ExtensionBlockCount = 0; - sp->ExtensionBlocks = (ExtensionBlock *) NULL; - - GifFile->ImageCount++; - - Private->PixelCount = (long)GifFile->Image.Width * - (long)GifFile->Image.Height; - - DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ - - return GIF_OK; -} - -/****************************************************************************** - * Get one full scanned line (Line) of length LineLen from GIF file. - *****************************************************************************/ -int -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; - 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; - 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. */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) - return GIF_ERROR; - while (Dummy != NULL) ; - } - return GIF_OK; - } else - return GIF_ERROR; -} - -/****************************************************************************** - * Put one pixel (Pixel) into GIF file. - *****************************************************************************/ -int -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; - 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; - 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. */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) - return GIF_ERROR; - while (Dummy != NULL) ; - } - return GIF_OK; - } else - return GIF_ERROR; -} - -/****************************************************************************** - * 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. - *****************************************************************************/ -int -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; - return GIF_ERROR; - } - - if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - *ExtCode = Buf; - - return DGifGetExtensionNext(GifFile, Extension); -} - -/****************************************************************************** - * 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) { - - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (READ(GifFile, &Buf, 1) != 1) { - _GifError = 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.). */ - if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - } else - *Extension = NULL; - - return GIF_OK; -} - -/****************************************************************************** - * This routine should be called last, to close the GIF file. - *****************************************************************************/ -int -DGifCloseFile(GifFileType * GifFile) { - - GifFilePrivateType *Private; - FILE *File; - - if (GifFile == NULL) - return GIF_ERROR; - - Private = (GifFilePrivateType *) GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - File = Private->File; - - if (GifFile->Image.ColorMap) { - FreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - - if (GifFile->SColorMap) { - FreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - } - - if (Private) { - free((char *)Private); - Private = NULL; - } - - if (GifFile->SavedImages) { - FreeSavedImages(GifFile); - GifFile->SavedImages = NULL; - } - - free(GifFile); - - if (File && (fclose(File) != 0)) { - _GifError = D_GIF_ERR_CLOSE_FAILED; - return GIF_ERROR; - } - return GIF_OK; -} - -/****************************************************************************** - * Get 2 bytes (word) from the given file: - *****************************************************************************/ -static int -DGifGetWord(GifFileType * GifFile, - GifWord *Word) { - - unsigned char c[2]; - - if (READ(GifFile, c, 2) != 2) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - *Word = (((unsigned int)c[1]) << 8) + c[0]; - 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). - *****************************************************************************/ -int -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; - return GIF_ERROR; - } - - *CodeSize = Private->BitsPerPixel; - - return DGifGetCodeNext(GifFile, CodeBlock); -} - -/****************************************************************************** - * 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) { - - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - if (Buf > 0) { - *CodeBlock = Private->Buf; /* Use private unused buffer. */ - (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - } else { - *CodeBlock = NULL; - Private->Buf[0] = 0; /* Make sure the buffer is empty! */ - Private->PixelCount = 0; /* And local info. indicate image read. */ - } - - return GIF_OK; -} - -/****************************************************************************** - * Setup the LZ decompression for this image: - *****************************************************************************/ -static int -DGifSetupDecompress(GifFileType * GifFile) { - - int i, BitsPerPixel; - GifByteType CodeSize; - GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - READ(GifFile, &CodeSize, 1); /* Read Code size from file. */ - BitsPerPixel = CodeSize; - - Private->Buf[0] = 0; /* Input Buffer empty. */ - 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->StackPtr = 0; /* No pixels on the pixel stack. */ - Private->LastCode = NO_SUCH_CODE; - Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ - Private->CrntShiftDWord = 0; - - Prefix = Private->Prefix; - for (i = 0; i <= LZ_MAX_CODE; i++) - Prefix[i] = NO_SUCH_CODE; - - return GIF_OK; -} - -/****************************************************************************** - * 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) { - - int i = 0; - int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; - GifByteType *Stack, *Suffix; - GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - - StackPtr = Private->StackPtr; - Prefix = Private->Prefix; - Suffix = Private->Suffix; - Stack = Private->Stack; - EOFCode = Private->EOFCode; - ClearCode = Private->ClearCode; - LastCode = Private->LastCode; - - if (StackPtr > LZ_MAX_CODE) { - return GIF_ERROR; - } - - if (StackPtr != 0) { - /* Let pop the stack off before continueing to read the gif file: */ - while (StackPtr != 0 && i < LineLen) - Line[i++] = Stack[--StackPtr]; - } - - while (i < LineLen) { /* Decode LineLen items. */ - if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) - return GIF_ERROR; - - if (CrntCode == EOFCode) { - /* 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++; - } else if (CrntCode == ClearCode) { - /* We need to start over again: */ - for (j = 0; j <= LZ_MAX_CODE; j++) - Prefix[j] = NO_SUCH_CODE; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - LastCode = Private->LastCode = NO_SUCH_CODE; - } else { - /* Its regular code - if in pixel range simply add it to output - * stream, otherwise trace to codes linked list until the prefix - * is in pixel range: */ - if (CrntCode < ClearCode) { - /* This is simple - its pixel scalar, so add it to output: */ - Line[i++] = CrntCode; - } else { - /* Its a code to needed to be traced: trace the linked list - * until the prefix is a pixel, while pushing the suffix - * 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) { - /* 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 { - _GifError = 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 && - 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; - return GIF_ERROR; - } - /* Push the last character on stack: */ - Stack[StackPtr++] = CrntPrefix; - - /* Now lets pop all the stack into output: */ - while (StackPtr != 0 && i < LineLen) - Line[i++] = Stack[--StackPtr]; - } - if (LastCode != NO_SUCH_CODE) { - Prefix[Private->RunningCode - 2] = LastCode; - - if (CrntCode == Private->RunningCode - 2) { - /* 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! */ - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, LastCode, ClearCode); - } else { - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, CrntCode, ClearCode); - } - } - LastCode = CrntCode; - } - } - - Private->LastCode = LastCode; - Private->StackPtr = StackPtr; - - return GIF_OK; -} - -/****************************************************************************** - * 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) { - - int i = 0; - - while (Code > ClearCode && i++ <= LZ_MAX_CODE) { - if (Code > LZ_MAX_CODE) { - return NO_SUCH_CODE; - } - Code = Prefix[Code]; - } - return Code; -} - -/****************************************************************************** - * 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) { - - GifByteType *CodeBlock; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) - return GIF_ERROR; - - if (*Code == Private->EOFCode) { - /* Skip rest of codes (hopefully only NULL terminating block): */ - do { - if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) - return GIF_ERROR; - } while (CodeBlock != NULL) ; - - *Code = -1; - } else if (*Code == Private->ClearCode) { - /* We need to start over again: */ - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - } - - return GIF_OK; -} - -/****************************************************************************** - * 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. - *****************************************************************************/ -static int -DGifDecompressInput(GifFileType * GifFile, - int *Code) { - - 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; - return GIF_ERROR; - } - - while (Private->CrntShiftState < Private->RunningBits) { - /* Needs to get more bytes from input stream for next code: */ - if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) { - return GIF_ERROR; - } - Private->CrntShiftDWord |= - ((unsigned long)NextByte) << Private->CrntShiftState; - Private->CrntShiftState += 8; - } - *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; - - Private->CrntShiftDWord >>= Private->RunningBits; - Private->CrntShiftState -= Private->RunningBits; - - /* If code cannot fit into RunningBits bits, must raise its size. Note - * however that codes above 4095 are used for special signaling. - * If we're using LZ_BITS bits already and we're at the max code, just - * 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->MaxCode1 <<= 1; - Private->RunningBits++; - } - return GIF_OK; -} - -/****************************************************************************** - * 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) { - - 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; - 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) { - _GifError = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) { - _GifError = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - *NextByte = Buf[1]; - Buf[1] = 2; /* We use now the second place as last char read! */ - Buf[0]--; - } else { - *NextByte = Buf[Buf[1]++]; - Buf[0]--; - } - - 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(). - ******************************************************************************/ -int -DGifSlurp(GifFileType * GifFile) { - - int ImageSize; - GifRecordType RecordType; - SavedImage *sp; - GifByteType *ExtData; - SavedImage temp_save; - - temp_save.ExtensionBlocks = NULL; - temp_save.ExtensionBlockCount = 0; - - do { - if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) - return (GIF_ERROR); - - switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - if (DGifGetImageDesc(GifFile) == GIF_ERROR) - return (GIF_ERROR); - - sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; - ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; - - sp->RasterBits = (unsigned char *)malloc(ImageSize * - 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; - } - break; - - case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) == - 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; - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: /* Should be trapped by DGifGetRecordType */ - break; - } - } 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 */ |