📄 dgif_lib.c
字号:
} 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);
}
sp->RasterBits = (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(__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(__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 shouldbe 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);
//RGL~BUG(The FreeSavedImages only frees GifFile->SavedImages not the entire GifFile structure): GifFile = NULL;
GifFile->SavedImages= NULL; //RGL+: Correct code
}
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, int *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. his 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;
unsigned int *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, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
GifByteType *Stack, *Suffix;
unsigned int *Prefix;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -