📄 dgif_lib.c
字号:
/****************************************************************************** * "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. *****************************************************************************/intDGifGetScreenDesc(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. *****************************************************************************/intDGifGetRecordType(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. *****************************************************************************/intDGifGetImageDesc(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++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -