⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dgif_lib.c

📁 支持各种栅格图像和矢量图像读取的库
💻 C
📖 第 1 页 / 共 3 页
字号:
    unsigned int *Prefix;    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;    StackPtr = Private->StackPtr;    Prefix = Private->Prefix;    Suffix = Private->Suffix;    Stack = Private->Stack;    EOFCode = Private->EOFCode;    ClearCode = Private->ClearCode;    LastCode = Private->LastCode;    if (StackPtr != 0) {	/* Let pop the stack off before continueing to read the gif file: */	while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];    }    while (i < LineLen) {			    /* Decode LineLen items. */	if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)    	    return GIF_ERROR;	if (CrntCode == EOFCode) {	    /* Note however that usually we will not be here as we will stop */	    /* decoding as soon as we got all the pixel, or EOF code will    */	    /* not be read at all, and DGifGetLine/Pixel clean everything.   */	    if (i != LineLen - 1 || Private->PixelCount != 0) {		_GifError = D_GIF_ERR_EOF_TOO_SOON;		return GIF_ERROR;	    }	    i++;	}	else if (CrntCode == ClearCode) {	    /* We need to start over again: */	    for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;	    Private->RunningCode = Private->EOFCode + 1;	    Private->RunningBits = Private->BitsPerPixel + 1;	    Private->MaxCode1 = 1 << Private->RunningBits;	    LastCode = Private->LastCode = NO_SUCH_CODE;	}	else {	    /* Its regular code - if in pixel range simply add it to output  */	    /* stream, otherwise trace to codes linked list until the prefix */	    /* is in pixel range:					     */	    if (CrntCode < ClearCode) {		/* This is simple - its pixel scalar, so add it to output:   */		Line[i++] = CrntCode;	    }	    else {		/* Its a code to needed to be traced: trace the linked list  */		/* until the prefix is a pixel, while pushing the suffix     */		/* pixels on our stack. If we done, pop the stack in reverse */		/* (thats what stack is good for!) order to output.	     */		if (Prefix[CrntCode] == NO_SUCH_CODE) {		    /* Only allowed if CrntCode is exactly the running code: */		    /* In that case CrntCode = XXXCode, CrntCode or the	     */		    /* prefix code is last code and the suffix char is	     */		    /* exactly the prefix of last code!			     */		    if (CrntCode == Private->RunningCode - 2) {			CrntPrefix = LastCode;			Suffix[Private->RunningCode - 2] =			Stack[StackPtr++] = DGifGetPrefixChar(Prefix,							LastCode, ClearCode);		    }		    else {			_GifError = D_GIF_ERR_IMAGE_DEFECT;			return GIF_ERROR;		    }		}		else		    CrntPrefix = CrntCode;		/* Now (if image is O.K.) we should not get an NO_SUCH_CODE  */		/* During the trace. As we might loop forever, in case of    */		/* defective image, we count the number of loops we trace    */		/* and stop if we got LZ_MAX_CODE. obviously we can not      */		/* loop more than that.					     */		j = 0;		while (j++ <= LZ_MAX_CODE &&		       CrntPrefix > ClearCode &&		       CrntPrefix <= LZ_MAX_CODE) {		    Stack[StackPtr++] = Suffix[CrntPrefix];		    CrntPrefix = Prefix[CrntPrefix];		}		if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {		    _GifError = D_GIF_ERR_IMAGE_DEFECT;		    return GIF_ERROR;		}		/* Push the last character on stack: */		Stack[StackPtr++] = CrntPrefix;		/* Now lets pop all the stack into output: */		while (StackPtr != 0 && i < LineLen)		    Line[i++] = Stack[--StackPtr];	    }	    if (LastCode != NO_SUCH_CODE) {		Prefix[Private->RunningCode - 2] = LastCode;		if (CrntCode == Private->RunningCode - 2) {		    /* Only allowed if CrntCode is exactly the running code: */		    /* In that case CrntCode = XXXCode, CrntCode or the	     */		    /* prefix code is last code and the suffix char is	     */		    /* exactly the prefix of last code!			     */		    Suffix[Private->RunningCode - 2] =			DGifGetPrefixChar(Prefix, LastCode, ClearCode);		}		else {		    Suffix[Private->RunningCode - 2] =			DGifGetPrefixChar(Prefix, CrntCode, ClearCode);		}	    }	    LastCode = CrntCode;	}    }    Private->LastCode = LastCode;    Private->StackPtr = StackPtr;    return GIF_OK;}/******************************************************************************* Routine to trace the Prefixes linked list until we get a prefix which is    ** not code, but a pixel value (less than ClearCode). Returns that pixel value.** If image is defective, we might loop here forever, so we limit the loops to ** the maximum possible if image O.k. - LZ_MAX_CODE times.		      *******************************************************************************/static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode){    int i = 0;    while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];    return Code;}/*******************************************************************************   Interface for accessing the LZ codes directly. Set Code to the real code  ** (12bits), or to -1 if EOF code is returned.				      *******************************************************************************/int DGifGetLZCodes(GifFileType *GifFile, int *Code){    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;    }    if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)	return GIF_ERROR;    if (*Code == Private->EOFCode) {	/* Skip rest of codes (hopefully only NULL terminating block): */	do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)    	    return GIF_ERROR;	while (CodeBlock != NULL);	*Code = -1;    }    else if (*Code == Private->ClearCode) {	/* We need to start over again: */	Private->RunningCode = Private->EOFCode + 1;	Private->RunningBits = Private->BitsPerPixel + 1;	Private->MaxCode1 = 1 << Private->RunningBits;    }    return GIF_OK;}/*******************************************************************************   The LZ decompression input routine:					      **   This routine is responsable for the decompression of the bit stream from  ** 8 bits (bytes) packets, into the real codes.				      **   Returns GIF_OK if read succesfully.					      *******************************************************************************/static int DGifDecompressInput(GifFileType *GifFile, int *Code){    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;    GifByteType NextByte;    static unsigned int CodeMasks[] = {	0x0000, 0x0001, 0x0003, 0x0007,	0x000f, 0x001f, 0x003f, 0x007f,	0x00ff, 0x01ff, 0x03ff, 0x07ff,	0x0fff    };    while (Private->CrntShiftState < Private->RunningBits) {	/* Needs to get more bytes from input stream for next code: */	if (DGifBufferedInput(GifFile, Private->Buf, &NextByte)	    == GIF_ERROR) {	    return GIF_ERROR;	}	Private->CrntShiftDWord |=		((unsigned long) NextByte) << Private->CrntShiftState;	Private->CrntShiftState += 8;    }    *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];    Private->CrntShiftDWord >>= Private->RunningBits;    Private->CrntShiftState -= Private->RunningBits;    /* If code cannt fit into RunningBits bits, must raise its size. Note */    /* however that codes above 4095 are used for special signaling.      */    if (++Private->RunningCode > Private->MaxCode1 &&	Private->RunningBits < LZ_BITS) {	Private->MaxCode1 <<= 1;	Private->RunningBits++;    }    return GIF_OK;}/*******************************************************************************   This routines read one gif data block at a time and buffers it internally ** so that the decompression routine could access it.			      **   The routine returns the next byte from its internal buffer (or read next  ** block in if buffer empty) and returns GIF_OK if succesful.		      *******************************************************************************/static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,						      GifByteType *NextByte){    if (Buf[0] == 0) {	/* Needs to read the next buffer - this one is empty: */	if (READ(GifFile, Buf, 1) != 1)	{	    _GifError = D_GIF_ERR_READ_FAILED;	    return GIF_ERROR;	}	if (READ(GifFile,&Buf[1], Buf[0]) != Buf[0])	{	    _GifError = D_GIF_ERR_READ_FAILED;	    return GIF_ERROR;	}	*NextByte = Buf[1];	Buf[1] = 2;	   /* We use now the second place as last char read! */	Buf[0]--;    }    else {	*NextByte = Buf[Buf[1]++];	Buf[0]--;    }    return GIF_OK;}/******************************************************************************* This routine reads an entire GIF into core, hanging all its state info off  ** the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()   ** first to initialize I/O.  Its inverse is EGifSpew().			      **  ******************************************************************************/int DGifSlurp(GifFileType *GifFile){    int ImageSize;    GifRecordType RecordType;    SavedImage *sp;    GifByteType *ExtData;    SavedImage temp_save;    temp_save.ExtensionBlocks=NULL;    temp_save.ExtensionBlockCount=0;      do {	if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)	    return(GIF_ERROR);	switch (RecordType) {	    case IMAGE_DESC_RECORD_TYPE:		if (DGifGetImageDesc(GifFile) == GIF_ERROR)		    return(GIF_ERROR);		sp = &GifFile->SavedImages[GifFile->ImageCount-1];		ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;		sp->RasterBits		    = (GifPixelType*) malloc(ImageSize * sizeof(GifPixelType));		if (DGifGetLine(GifFile, sp->RasterBits, ImageSize)		    == GIF_ERROR)		    return(GIF_ERROR);        if (temp_save.ExtensionBlocks) {            sp->ExtensionBlocks = temp_save.ExtensionBlocks;            sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;            temp_save.ExtensionBlocks = NULL;            temp_save.ExtensionBlockCount=0;        /* FIXME: The following is wrong.  It is left in only for backwards         * compatibility.  Someday it should go away.  Use the         * sp->ExtensionBlocks->Function variable instead.         */            sp->Function = sp->ExtensionBlocks[0].Function;        }		break;	    case EXTENSION_RECORD_TYPE:		if (DGifGetExtension(GifFile,&temp_save.Function,&ExtData)==GIF_ERROR)		    return(GIF_ERROR);		while (ExtData != NULL) {                        /* Create an extension block with our data */            if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1])               == GIF_ERROR)                return (GIF_ERROR);             		    if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)			    return(GIF_ERROR);            temp_save.Function = 0;		}		break;	    case TERMINATE_RECORD_TYPE:		break;	    default:	/* Should be trapped by DGifGetRecordType */		break;	}    } while (RecordType != TERMINATE_RECORD_TYPE);    /* Just in case the Gif has an extension block without an associated     * image... (Should we save this into a savefile structure with no image     * instead?  Have to check if the present writing code can handle that as     * well....     */    if (temp_save.ExtensionBlocks)        FreeExtension(&temp_save);        return(GIF_OK);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -