📄 dgif_lib.c
字号:
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. *****************************************************************************/intDGifGetLine(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. *****************************************************************************/intDGifGetPixel(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 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. *****************************************************************************/intDGifGetExtension(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). *****************************************************************************/intDGifGetExtensionNext(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. *****************************************************************************/intDGifCloseFile(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 intDGifGetWord(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). *****************************************************************************/intDGifGetCode(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). *****************************************************************************/intDGifGetCodeNext(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 intDGifSetupDecompress(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -