📄 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
#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__ */
#ifndef __MSDOS__
#include <stdlib.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "gif_lib.h"
#include "gif_lib_private.h"
/*RGL+: Debug version of malloc (only tested on MSVC)*/
#ifdef _DEBUG
#include <crtdbg.h>
#define malloc(size) _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__)
#endif
/**/
#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, 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);
/******************************************************************************
* 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;
}
#ifdef __MSDOS__
setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
#endif /* __MSDOS__ */
f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
#ifdef __MSDOS__
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;
}
/******************************************************************************
* 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 && GifFile->SavedImages == NULL)
FreeMapObject(GifFile->Image.ColorMap);
GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
/* Get the image local color map: */
for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
if (READ(GifFile,Buf, 3) != 3) {
_GifError = D_GIF_ERR_READ_FAILED;
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];
}
}
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -