📄 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). *******************************************************************************/#if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__)#include <io.h>#include <alloc.h>#include <stdlib.h>#include <sys\stat.h>#else#include <sys/types.h>#include <sys/stat.h>#endif /* __MSDOS__ */#ifdef unix#include <unistd.h>#endif#ifndef __MSDOS__#include <stdlib.h>#endif#include <fcntl.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. */#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1#define GIF_VERSION_POS 3 /* Version first character in stamp. *//* 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, int *Word);static int DGifSetupDecompress(GifFileType *GifFile);static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen);static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);static int DGifDecompressInput(GifFileType *GifFile, int *Code);static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte);/******************************************************************************* 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#ifdef O_BINARY | O_BINARY#endif /* __MSDOS__ */ )) == -1) { _GifError = D_GIF_ERR_OPEN_FAILED; return NULL; } GifFile = DGifOpenFileHandle(FileHandle); if (GifFile == (GifFileType *)NULL) close(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){ char Buf[GIF_STAMP_LEN+1]; GifFileType *GifFile; GifFilePrivateType *Private; FILE *f; if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return NULL; } memset(GifFile, '\0', sizeof(GifFileType)); if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; free((char *) GifFile); return NULL; }#if defined(__MSDOS__) || defined(WIN32) setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/#else f = fdopen(FileHandle, "rb"); /* Make it into a stream: */#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;}/******************************************************************************* GifFileType constructor with user supplied input function (TVT) ** *******************************************************************************/GifFileType *DGifOpen( void* userData, InputFunc readFunc ){ char Buf[GIF_STAMP_LEN+1]; GifFileType *GifFile; GifFilePrivateType *Private; if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return NULL; } memset(GifFile, '\0', sizeof(GifFileType)); if (!(Private = (GifFilePrivateType*) malloc(sizeof(GifFilePrivateType)))){ _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); /* Get the global color map: */ for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { _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]; } } return GIF_OK;}/******************************************************************************* This routine should be called before any attemp 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 attemp 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? */ if (GifFile->Image.ColorMap) { FreeMapObject(GifFile->Image.ColorMap); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -