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

📄 gifdeclib.c

📁 GIF动画解码算法
💻 C
📖 第 1 页 / 共 4 页
字号:
			return BLOCK_PLAINTEXT;
			break;

		case 0xF9:
		// graphic control extension
			return BLOCK_CONTROLEXT;
			break;

		case 0xFE:
		// comment extension
			return BLOCK_COMMEXT;
			break;

		case 0xFF:
		// application extension
			return BLOCK_APPEXT;
			break;
		};
		break;
	
	case 0x3B:
	// trailer
		return BLOCK_TRAILER;
		break;

	case 0x2C:
	// image data
		return BLOCK_IMAGE;
		break;
	};

	return BLOCK_UNKNOWN;
}
BOOL SkipNextBlock(TImage *pImage)
{
	int nLen;
	if (!pImage->m_pRawData) 
		return FALSE;

	nLen = GetNextBlockLen(pImage);
	if (nLen <= 0 || pImage->m_nCurrOffset+nLen> pImage->m_nDataSize)
		return FALSE;
	pImage->m_nCurrOffset += nLen;
	return TRUE;
}
int GetNextBlockLen(TImage *pImage)
{
	int nTmp;
	enum GIFBlockTypes nBlock;
	TGIFImageDescriptor *pIDescr;
	int nLCTSize;
	
	nBlock = GetNextBlock(pImage);
	switch(nBlock)
	{
		case BLOCK_UNKNOWN:
			return -1;
			break;

		case BLOCK_TRAILER:
			return 1;
			break;

		case BLOCK_APPEXT:
			nTmp = GetSubBlocksLen(pImage,pImage->m_nCurrOffset+sizeof(TGIFAppExtension));
			if (nTmp > 0)
				return sizeof(TGIFAppExtension)+nTmp;
			break;

		case BLOCK_COMMEXT:
			nTmp = GetSubBlocksLen(pImage,pImage->m_nCurrOffset+sizeof(TGIFCommentExt));
			if (nTmp > 0)
				return sizeof(TGIFCommentExt)+nTmp;
			break;

		case BLOCK_CONTROLEXT:
			return sizeof(TGIFControlExt);
			break;

		case BLOCK_PLAINTEXT:
			nTmp = GetSubBlocksLen(pImage,pImage->m_nCurrOffset+sizeof(TGIFPlainTextExt));
			if (nTmp > 0)
				return sizeof(TGIFPlainTextExt)+nTmp;
			break;

		case BLOCK_IMAGE:
			pIDescr = (TGIFImageDescriptor *) (&(pImage->m_pRawData[pImage->m_nCurrOffset]));
			nLCTSize = (int)(GetPackedValueImD(pIDescr,ID_PACKED_LOCALCT)*3*(1 << (GetPackedValueImD(pIDescr,ID_PACKED_LOCALCTSIZE)+1)));
			nTmp = GetSubBlocksLen(pImage,pImage->m_nCurrOffset+sizeof(TGIFImageDescriptor) + nLCTSize + 1);
			if (nTmp > 0)
				return sizeof(TGIFImageDescriptor) + nLCTSize + 1 + nTmp;
			break;
	};
	return 0;
}
BOOL GetNextGraphicBlock(TImage *pImage,
        					 TFrame *pFrame,
        					 UINT *pBlockLen,
        					 UINT *pDelay, 
        					 SIZE *pBlockSize,
        					 SIZE *pBlockOffset,
        					 UINT *pDisposal,
        					 int nWidth,
							 int nHeight)
{
	enum GIFBlockTypes nBlock;
	int nStart ;	
	int nBlockLen; 
	TGIFControlExt *pControl;
	TGIFImageDescriptor *pImgDscpt ;
	HGLOBAL hGlobal;
	int nOffset = 0; 
	unsigned char *pGlobal;
	
	if (!pImage->m_pRawData) 
		return NULL;
	// GIF header + LSDescriptor [+ GCT] [+ Control block] + Data
	*pDisposal = 0;
	nBlock = GetNextBlock(pImage);

	while ((nBlock != BLOCK_CONTROLEXT) &&(nBlock != BLOCK_IMAGE) &&(nBlock != BLOCK_PLAINTEXT) &&(nBlock != BLOCK_UNKNOWN) &&(nBlock != BLOCK_TRAILER))
	{
		if (!SkipNextBlock(pImage)) 
			return NULL;
		nBlock = GetNextBlock(pImage);
	};
	if ((nBlock == BLOCK_UNKNOWN) ||(nBlock == BLOCK_TRAILER))
		return NULL;

	// it's either a controlext, an image or a plain text block
	nStart = pImage->m_nCurrOffset;
	nBlockLen = GetNextBlockLen(pImage);

	if (nBlockLen <= 0) 
		return NULL;

	if (nBlock == BLOCK_CONTROLEXT)
	{
		// get the following data
		pControl = (TGIFControlExt *)(&pImage->m_pRawData[pImage->m_nCurrOffset]);
		// store delay time
		*pDelay = pControl->m_wDelayTime;
		// store disposal method
		*pDisposal = GetPackedValueCon(pControl,GCX_PACKED_DISPOSAL);

		if (!SkipNextBlock(pImage)) 
			return NULL;
		nBlock = GetNextBlock(pImage);
		
		// skip everything until we find data to display 
		// (image block or plain-text block)
		
		while ((nBlock != BLOCK_IMAGE) &&(nBlock != BLOCK_PLAINTEXT) &&(nBlock != BLOCK_UNKNOWN) &&(nBlock != BLOCK_TRAILER))
		{
			if (!SkipNextBlock(pImage)) 
				return NULL;
			nBlock = GetNextBlock(pImage);
			nBlockLen += GetNextBlockLen(pImage);
		};

		if ((nBlock == BLOCK_UNKNOWN) || (nBlock == BLOCK_TRAILER))
			return NULL;
		nBlockLen += GetNextBlockLen(pImage);
	}
	else
		*pDelay = -1; // to indicate that there was no delay value

	if (nBlock == BLOCK_IMAGE)
	{
		// store size and offsets
		pImgDscpt = (TGIFImageDescriptor *) (&pImage->m_pRawData[pImage->m_nCurrOffset]);
		pBlockSize->cx = pImgDscpt->m_wWidth;
		pBlockSize->cy = pImgDscpt->m_wHeight;
		pBlockOffset->cx = pImgDscpt->m_wLeftPos;
		pBlockOffset->cy = pImgDscpt->m_wTopPos;
	};

	if (!SkipNextBlock(pImage)) 
		return NULL;
	if(!FrameDec(pImage,&((pImage->m_pRawData)[nStart]),nStart,nBlockLen,pFrame,nWidth,nHeight))
		return FALSE;
	return TRUE;
}

BOOL IsGIF(TImage *pImage) 
{
	return pImage->m_bIsGIF;
}

BOOL IsAnimatedGIF(TImage *pImage) 
{
	return (pImage->m_bIsGIF && (pImage->m_nFrameCount> 1));
}

BOOL IsPlaying(TImage *pImage) 
{
	return pImage->m_bIsPlaying;
}

int GetFrameCount(TImage *pImage)
{
	if (!IsAnimatedGIF(pImage))
		return 0;
	return pImage->m_nFrameCount; //to be detailed ,,yajun
}

BOOL FrameDec(TImage *pImage,
					U8 *pSData,
					int nStart,
					int nBlockLen,
					TFrame *pFrame,
					int nWidth,
					int nHeight)
{
	int 		step = 0,WritePos = 0,processImage = 1;
	int 		nBlckSze;
	U8 		i,Output,cCurByte,cCurCodeSize,Group;
	U16		NewCode , MyCode ;
	U16 		OldCode , FCode ;	
	U16		EndCode , ClearCode,BitPosition,ByteCountInBlock;	
	U16 		slot , newcodes , TopSlot;
	U8 		*sp ;
	U8      	R,G,B;
	U8 		*stack;
	U8 		*suffix;
	U16 		*prefix;
	U8		*stmp;
	U16		*ptmp;
	int		stackSize,suffixSize,prefixSize;
	int		deltaSize = 1024;
	int 		stackCount=0,suffixCount=0,prefixCount=0;

	//////////////////////////////////////////////////////////////

	int oldWidth,oldHeight,ImgMaxSide,ImgMinSide,ScrMaxSide,ScrMinSide;
	
	if(NU_SUCCESS !=NU_Allocate_Memory(&System_Memory,&stack,4096*sizeof(U8),0))
		return FALSE;
	else
		stackSize = 4096;
	if(NU_SUCCESS !=NU_Allocate_Memory(&System_Memory,&suffix,4096*sizeof(U8),0)){
		NU_Deallocate_Memory(stack);
		return FALSE;
	}
	else
		suffixSize = 4096;
	if(NU_SUCCESS !=NU_Allocate_Memory(&System_Memory,&prefix,4096*sizeof(U16),0)){
		NU_Deallocate_Memory(stack);
		NU_Deallocate_Memory(suffix);
		return FALSE;
	
	}
	else
		prefixSize = 4096;
	
	cCurByte = pSData[step++];
////////////////////////////////////////////////
	while(processImage && cCurByte!= 0x3B)
	{
		switch( cCurByte )	
		{	
			case 0x21:
				cCurByte = pSData[step++];
				switch( cCurByte )			
				{
					case 0xF9: 
						nBlckSze = pSData[step++];						
						cCurByte = pSData[step++];
						pFrame->m_TransparentFlag= cCurByte & 0x01;
						pFrame->m_controlExt.m_wDelayTime = pSData[step++];
						pFrame->m_controlExt.m_wDelayTime += ( pSData[step++] << 8);														
						pFrame->m_controlExt.m_cTColorIndex = pSData[step++];							
						cCurByte = pSData[step++];
						if ( cCurByte == 0 )
							break;

					case 0x01: 
						pFrame->m_plainTextExt.m_cBlockSize= pSData[step++] ;
						
						pFrame->m_plainTextExt.m_wLeftPos = ( pSData[step++] << 8);
						pFrame->m_plainTextExt.m_wLeftPos += pSData[step++];

						pFrame->m_plainTextExt.m_wTopPos = ( pSData[step++] << 8);
						pFrame->m_plainTextExt.m_wTopPos += pSData[step++];

						pFrame->m_plainTextExt.m_wGridWidth = (pSData[step++] << 8);
						pFrame->m_plainTextExt.m_wGridWidth += pSData[step++];
						pFrame->m_plainTextExt.m_wGridHeight = ( pSData[step++] << 8);
						pFrame->m_plainTextExt.m_wGridHeight += pSData[step++] ;

						pFrame->m_plainTextExt.m_cCellWidth = pSData[step++];
						pFrame->m_plainTextExt.m_cCellHeight = pSData[step++];

						pFrame->m_plainTextExt.m_cFgColor = pSData[step++];
						pFrame->m_plainTextExt.m_cBkColor = pSData[step++];

						nBlckSze= pSData[step++] ;
						while( nBlckSze!= 0 )
						{				
							for ( i = 0 ; i <= nBlckSze-1 ; i ++ )
								pFrame->m_PlnTexExt_plainTData[i] = pSData[step++];
							nBlckSze= pSData[step++] ;
						}
						break;
						
					case 0xFE: 
						nBlckSze = pSData[step++] ;
						while( nBlckSze != 0 )
						{				
							for ( i = 0 ; i <= nBlckSze - 1 ; i ++ )
								pFrame->m_ComExt_commentData[i] = pSData[step++];
								nBlckSze= pSData[step++];
						}
						break;
						
					case 0xFF: 
						pFrame->m_appExtension.m_cBlockSize = pSData[step++];
						for ( i = 0 ; i <= 7 ; i ++ )
							pFrame->m_appExtension.m_cAppIdentifier[i] = pSData[step++];
						for ( i = 0 ; i <= 2 ; i ++ )
							pFrame->m_appExtension.m_cAppAuth[i] = pSData[step++];	

						nBlckSze= pSData[step++];
						for ( i = 0 ; i <= nBlckSze - 1 ; i ++ )
							pFrame->m_AppExt_commentData[i] = pSData[step++];
						cCurByte = pSData[step++];
						if ( cCurByte == 0 )
							break;

					default:  
							break;
				}
				break;
				
			case 0x2C: 
				processImage = 0;
				pFrame->m_imageDescriptor.m_wLeftPos = pSData[step++];
				pFrame->m_imageDescriptor.m_wLeftPos += ( pSData[step++] << 8);

				pFrame->m_imageDescriptor.m_wTopPos = pSData[step++];
				pFrame->m_imageDescriptor.m_wTopPos += (pSData[step++] << 8);				
	
				pFrame->m_imageDescriptor.m_wWidth = pSData[step++];
				pFrame->m_imageDescriptor.m_wWidth +=( pSData[step++] << 8);
				if(pFrame->m_imageDescriptor.m_wWidth>pImage->m_PictureSize.cx)
					pImage->m_PictureSize.cx = pFrame->m_imageDescriptor.m_wWidth;

				pFrame->m_imageDescriptor.m_wHeight = pSData[step++];
				pFrame->m_imageDescriptor.m_wHeight += ( pSData[step++] << 8);
				if(pFrame->m_imageDescriptor.m_wHeight>pImage->m_PictureSize.cy)
					pImage->m_PictureSize.cy = pFrame->m_imageDescriptor.m_wHeight;
	
				cCurByte = pSData[step++] ;

				pFrame->m_ImaDesExt_sPackFields.m_LCTSize = cCurByte & 0x07;
				pFrame->m_ImaDesExt_sPackFields.m_Reserved = ( cCurByte & 0x18 ) >> 3;
				pFrame->m_ImaDesExt_sPackFields.m_SortFlag = ( cCurByte & 0x20 ) >> 5;
				pFrame->m_ImaDesExt_sPackFields.m_InterlaceFlag = ( cCurByte & 0x40 ) >> 6;
				pFrame->m_ImaDesExt_sPackFields.m_LCTFlag = ( cCurByte & 0x80 ) >> 7;
					
				if ( pFrame->m_ImaDesExt_sPackFields.m_LCTFlag )
				{
					pFrame->m_LCTPos = step + nStart;
						step += 3 * ( 2 << pFrame->m_ImaDesExt_sPackFields.m_LCTSize);
				}
				else
					pFrame->m_LCTPos = pImage->m_nGlobalCTPos;

				//////////////////////////////////////////////////////

				pFrame->m_LZWMinCodeSize = pSData[step++];
				cCurCodeSize = pFrame->m_LZWMinCodeSize + 1;
				TopSlot = 1 <<cCurCodeSize;
				ClearCode = 1 << pFrame->m_LZWMinCodeSize;
				EndCode = ClearCode + 1;
				slot = newcodes = EndCode +1;
				OldCode = FCode = 0;	
				sp = stack;
				
				Group = 1 ;
				BitPosition = 0;
				pFrame->m_nBlockSize = pSData[step++];
				cCurByte = pSData[step++] ;
				ByteCountInBlock = 1;								

				while (1)
				{ 
						if (pFrame->m_nBlockSize == 0 )
							break ;							
						NewCode = GetNewCode(pFrame,pSData,cCurCodeSize,&cCurByte,&step,&BitPosition,&ByteCountInBlock);	
						if (pFrame->m_nBlockSize == 0 )
							break ;
							
						if ( NewCode == ClearCode )
						{
							cCurCodeSize = pFrame->m_LZWMinCodeSize + 1;
							slot = newcodes ;	
							TopSlot = 1 << cCurCodeSize;
							while ((NewCode = GetNewCode(pFrame,pSData,cCurCodeSize,&cCurByte,&step,&BitPosition,&ByteCountInBlock) )== ClearCode)
								;	
							if (NewCode == EndCode)
								break;			
							if (NewCode >= slot)
								NewCode = 0; 	
							OldCode = FCode = NewCode;	
							Output =  NewCode ;
							if(pFrame->m_ImaDesExt_sPackFields.m_InterlaceFlag)
								if(!InterLaceWriteToFrame(pFrame,WritePos++,R,G,B)){
										NU_Deallocate_Memory(stack);
										NU_Deallocate_Memory(suffix);
										NU_Deallocate_Memory(prefix);
										return FALSE;
								}
							else
								if(!WriteToFrame(pFrame,WritePos++,R,G,B)){
									NU_Deallocate_Memory(stack);
									NU_Deallocate_Memory(suffix);
									NU_Deallocate_Memory(prefix);
									return FALSE;
								}
						}

						else
						{
							MyCode	= NewCode ; 
							if (MyCode >= slot)
							{
								MyCode = OldCode ;
								*sp++ = FCode;
								if(sp==stack+stackSize){
									stackSize += deltaSize; 								

⌨️ 快捷键说明

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