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

📄 gif_driver.c

📁 gif decoder,此代码是用于ARM9
💻 C
字号:
#include <string.h>
#include "src\widgets\fep_widgets.h"
#include "os\fsapi.h"
#include "gif_driver.h"

#define MAXCOLORMAPSIZE			256
#define LM_to_uint(a,b)			(((b)<<8)|(a))
#define BitSet(byte,bit)		(((byte) & (bit))==(bit))
#define CM_RED					0
#define CM_GREEN				1
#define CM_BLUE					2
#define INTERLACE				0x40
#define MAX_LZW_BITS			12
#define WIDTHBYTES(bits)		(((bits) + 31) / 32 * 4) 
#define LOCALCOLORMAP			0x80


typedef struct tagGIFSCREEN
{
	unsigned int Width;
	unsigned int Height;
	unsigned char ColorMap[3][MAXCOLORMAPSIZE];
	unsigned int BitPixel;
	unsigned int ColorResolution;
	unsigned int BackGround;
	unsigned int AspectRatio;
} GIFSCREEN;

typedef struct tagGIF89
{
	int transparent;
	int delayTime;
	int inputFlag;
	int disposal;
} GIF89;



GIF89 Gif89;
GIFSCREEN GifScreen;
int	ZeroDataBlock;


int	ReadColorMap (int fd, int number, uint8_t buffer[3][MAXCOLORMAPSIZE]);
int DoExtension(int fd, int label);
int	GetDataBlock (int fd, uint8_t *buf);
bool ReadImage(int fd, uint8_t  * bigMemBuf, int width, int height, uint8_t cmap[3][MAXCOLORMAPSIZE], int interlace);
int	LZWReadByte (int fd,int flag, int  input_code_size);
int	GetCode (int fd, int code_size, int flag);
///bool BGRFromRGB(uint8_t *buf, uint16_t widthPix, uint16_t height);
bool ReadOK(int fp, uint8_t *buffer, int len);
//=============================================================================




/*=========================================================
说明:
	本函数将完整的gif数据转换成bmp,放到动态申请的buffer
input:
	fd:			文件指针,一定要指向完整gif的头
	uWidth:		gif的宽度,由本函数写入
	uHeight:	gif的高度,由本函数写入
output:
	存放bmp数据的buffer头指针
=========================================================*/
uint8_t *ReadGIFFile(int32_t fd/*, uint16_t *uWidth, uint16_t *uHeight*/)
{
	uint8_t			buf[16];
	uint8_t			c;
	uint8_t			localColorMap[3][MAXCOLORMAPSIZE];
	int				useGlobalColormap;
	int				bitPixel;
	int 			w=0;
	int				h=0;
	long			bufsize;
	
	//读取gif的头数据,用以判断是否是完整的gif(GIF89a)
	ReadOK(fd,buf,6);
	
	ReadOK(fd,buf,7);
	GifScreen.Width		=	LM_to_uint((uint8_t)buf[0],(uint8_t)buf[1]);
	GifScreen.Height	=	LM_to_uint((uint8_t)buf[2],(uint8_t)buf[3]);
	GifScreen.BitPixel	=	2 << ((uint8_t)buf[4] & 0x07);
	GifScreen.ColorResolution = ((((uint8_t)buf[4] & 0x70) >> 3) + 1);
	GifScreen.BackGround =	(uint8_t)buf[5];
	GifScreen.AspectRatio=	(uint8_t)buf[6];

	//读取全局调色板(如果有)
	if (BitSet((uint8_t)buf[4],LOCALCOLORMAP)) 
		ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap);

	
	//只显示gif内的第一帧图像数据
	for(;;) 
	{	
		//读一个字节
		ReadOK(fd,&c,1);
	
		//image terminator
		if (c==';') 
		{
			c = c;
		}
	
		if (c=='!') 
		{
			ReadOK(fd,&c,1);
			DoExtension(fd,c);
			continue;
		}
	
		if (c!=',') 
		{
			//Ignoring c
			continue;
		}
		
		// read image header
		ReadOK(fd,buf,9);
		
		useGlobalColormap=!BitSet((uint8_t)buf[8],LOCALCOLORMAP);
		
		bitPixel = 1<<(((uint8_t)buf[8]&0x07)+1);                                                      
		
		w = LM_to_uint((uint8_t)buf[4],(uint8_t)buf[5]);		
		h = LM_to_uint((uint8_t)buf[6],(uint8_t)buf[7]);
		
		if((w*h)>(320*240))
		{
			return NULL;
		}
		
		bufsize = (long)w*(long)h;
		bufsize *= 3;
		
		if (!useGlobalColormap)		//使用局部调色板
		{
			ReadColorMap(fd,bitPixel,localColorMap);
			
		 	//读取图像数据
			ReadImage(fd, &decoder_buff[4], w, h, localColorMap, BitSet((uint8_t)buf[8],INTERLACE));
		} 
		else					//使用全局调色板
		{
			//读取图像数据
			ReadImage(fd, &decoder_buff[4], w, h, GifScreen.ColorMap, BitSet((uint8_t)buf[8],INTERLACE));
		}
		break;
	}
	
	/*
	*uWidth = w;
	*uHeight = h;
	*/
	//======================================================================
	
	///BGRFromRGB(&decoder_buff[4], w, h);
	{
#define BMP_565
	uint8_t data[3];
	long index1,index2,index3,i,j;
	for(i = 0; i < h; i ++)
	{
		index1 = i * w * 3;
		for(j = 0; j < w; j ++)
		{
			index2 = j*3 + index1;
			///data[0] = decoder_buff[4+ index2 + 0];
			data[0] = decoder_buff[4+ index2 + 2];
			data[1] = decoder_buff[4+ index2 + 1];
			///data[2] = decoder_buff[4+ index2 + 2];
			data[2] = decoder_buff[4+ index2 + 0];
			index3 = index2/3*2;

#ifdef BMP_565
			decoder_buff[4+ index3 + 1] = data[2]&0xf8;
			decoder_buff[4+ index3 + 1] |= data[1]>>5;
			decoder_buff[4+ index3 + 0] = (data[0]>>3)&0x1f;
			decoder_buff[4+ index3 + 0] |= (data[1]<<3) & 0xe0;
#else	//555
			decoder_buff[4+ index3 + 1] = (data[2]>>1) & 0xfc;
			decoder_buff[4+ index3 + 1] |= data[1]>>6;
			decoder_buff[4+ index3 + 0] = (data[0]>>3)&0x1f;
			decoder_buff[4+ index3 + 0] |= (data[1]<<2) & 0xe0;
#endif
		}
	}
	}
	//======================================================================
	
	return decoder_buff;
}


int ReadColorMap(int fd, int number, uint8_t buffer[3][MAXCOLORMAPSIZE])
{
	int 	i;
	uint8_t rgb[3];
	
	for (i = 0; i < number; i ++) 
	{
		ReadOK(fd,rgb,sizeof(rgb));
		
		buffer[CM_RED][i] = rgb[0];
		buffer[CM_GREEN][i] = rgb[1];
		buffer[CM_BLUE][i] = rgb[2];
	}	
	return TRUE;
}


int DoExtension(int fd, int label)
{
	static char buf[256];

	switch(label) 
	{
	case 0x01  :
	case 0xff :
		break;
	case 0xfe :
		while (GetDataBlock(fd,(uint8_t *)buf)!=0);
		return FALSE;
	case 0XF9 :
		(void)GetDataBlock(fd,(uint8_t *)buf);
		Gif89.disposal	= (buf[0]>>2) &0x7;
		Gif89.inputFlag	= (buf[0]>>1) &0x1;
		Gif89.delayTime	= LM_to_uint(buf[1],buf[2]);
		if ((buf[0]&0x1)!=0)
			Gif89.transparent = buf[3];
	
		while (GetDataBlock(fd,(uint8_t *)buf)!=0);
		return FALSE;
	default :
		break;
	}
	
	while (GetDataBlock(fd,(uint8_t *)buf) != 0);

	return FALSE;
}


int GetDataBlock(int fd, uint8_t *buf)
{
	uint8_t count;

	ReadOK(fd,&count,1);

	ZeroDataBlock = count==0;

	if ((count != 0) && (!ReadOK(fd,buf,count))) 
	{
		return -1;
	}
	return count;
}


bool ReadImage(int fd, uint8_t  * bigMemBuf, int width, int height, uint8_t cmap[3][MAXCOLORMAPSIZE], int interlace)
{
	uint8_t c;
	int color;
	int xpos=0, ypos=0, pass=0;
	long curidx;

	ReadOK(fd,&c,1);

	if (LZWReadByte(fd,TRUE,c)<0) 
	{
		return FALSE;
	}
	
	while ((color = LZWReadByte(fd,FALSE,c)) >= 0) 
	{
        curidx = (long)xpos+(long)ypos*(long)width;
        curidx *= 3;     
        
		*(bigMemBuf+curidx) = cmap[0][color];
		*(bigMemBuf+curidx+1) = cmap[1][color];
		*(bigMemBuf+curidx+2) = cmap[2][color];				

		++xpos;
		if (xpos == width) 
		{
			xpos = 0;
			if (interlace) 
			{
				switch (pass) 
				{
				case 0:
				case 1:
					ypos+=8; break;
				case 2:
					ypos+=4; break;
				case 3:
					ypos+=2; break;
				}

				if (ypos >= height) 
				{
					++pass;
					switch (pass) 
					{
					case 1: ypos=4;break;
					case 2: ypos=2;break;
					case 3: ypos=1;break;
					default : goto finish;
					}
				}
			} 
			else 
			{
				++ypos;
			}
		}
		if (ypos >=height)
			break;
	}

finish:
	return TRUE;
}


int LZWReadByte(int fd, int flag, int input_code_size)
{
	static int fresh=FALSE;
	int code, incode;
	static int code_size, set_code_size;
	static int max_code, max_code_size;
	static int firstcode, oldcode;
	static int clear_code, end_code;

	static unsigned short  next[1<<MAX_LZW_BITS];
	static uint8_t  vals[1<<MAX_LZW_BITS];
	static uint8_t  stack [1<<(MAX_LZW_BITS+1)];
	static uint8_t  *sp;
	
	register int i;

	if(flag)
	{
		set_code_size = input_code_size;
		code_size = set_code_size+1;
		clear_code = 1<<set_code_size;
		end_code = clear_code+1;
		max_code = clear_code+2;
		max_code_size = 2*clear_code;

		GetCode(fd,0,TRUE);

		fresh = TRUE;
	
		for(i=0; i<clear_code; i++) 
		{
			next[i] = 0;
			vals[i] = i;
		}

		for (; i<(1<<MAX_LZW_BITS); i++)
			next[i] = vals[0] = 0;
	
		sp = stack;

		return 0;
	} 
	else if(fresh) 
	{
		fresh=FALSE;
		do 
		{
			firstcode=oldcode=GetCode(fd,code_size,FALSE);
		} while (firstcode==clear_code);
		return firstcode;
	}

	if (sp > stack)
		return *--sp;

	while ((code= GetCode(fd,code_size,FALSE)) >=0) 
	{
		if (code==clear_code) 
		{
			for (i=0;i<clear_code;++i) 
			{
				next[i] = 0;
				vals[i] = i;
			}
			for (; i<(1<<MAX_LZW_BITS); ++i)	
				next[i]=vals[i]=0;

			code_size=set_code_size+1;
			max_code_size=2*clear_code;
			max_code=clear_code+2;
			sp=stack;
			firstcode=oldcode=GetCode(fd,code_size,FALSE);
			return firstcode;
		} 
		else if (code == end_code) 
		{
			int count;
			uint8_t buf[260];
		
			if (ZeroDataBlock)
				return -2;

			while ((count=GetDataBlock(fd,buf)) >0);

			if (count!=0)
				return -2;	
		}

		incode = code;

		if (code >= max_code) 
		{
			*sp++=firstcode;
			code=oldcode;
		}

		while (code >=clear_code) 
		{
			*sp ++= vals[code];
			if (code==(int)next[code]) 
			{
				return -1;
			}
			code=next[code];
		}

		*sp++ = firstcode=vals[code];

		if ((code=max_code) <(1<<MAX_LZW_BITS)) 
		{
			next[code]=oldcode;
			vals[code]=firstcode;
			++max_code;
			if ((max_code >=max_code_size) && (max_code_size < (1<<MAX_LZW_BITS))) 
			{
				max_code_size*=2;
				++code_size;
			}
		}

	oldcode=incode;

	if (sp > stack)
		return *--sp;
	}
	return code;
}   


int GetCode(int fd, int code_size, int flag)
{
	static uint8_t buf[280];
	static int curbit, lastbit, done, last_byte;
	int i,j,ret;
	uint8_t count;

	if (flag) 
	{
		curbit = 0;
		lastbit = 0;
		done = FALSE;
		return 0;
	}

	if ((curbit+code_size) >=lastbit) 
	{
		if (done) 
		{
			if (curbit >= lastbit) 
			{
				return 0;
			}
			return -1;
		}
		buf[0]=buf[last_byte-2];	
		buf[1]=buf[last_byte-1];

		if ((count=GetDataBlock(fd,&buf[2]))==0)
			done=TRUE;

		last_byte=2+count;

		curbit=(curbit - lastbit) + 16;

		lastbit = (2+count)*8;
	}
	ret = 0;
	for (i=curbit,j=0; j<code_size; ++i,++j)
		ret|=((buf[i/8]&(1<<(i% 8)))!=0)<<j;

	curbit+=code_size;

	return ret;
}

/*
//交换RGB成BGR
bool BGRFromRGB(uint8_t *buf, uint16_t widthPix, uint16_t height)
{
	uint8_t tmp;
	uint16_t col, row;
	
	if (buf==NULL)
		return FALSE;
	
	for (row = 0; row < height; row ++) 
	{
		for (col=0;col<widthPix;col++) 
		{
			uint8_t *pRed, *pBlu;
			pRed = buf + row * widthPix * 3 + col * 3;
			pBlu = buf + row * widthPix * 3 + col * 3 + 2;

			tmp = *pRed;
			*pRed = *pBlu;
			*pBlu = tmp;
		}
	}
	return TRUE;
}
*/

bool ReadOK(int fp, uint8_t *buffer, int len)
{
	if(Fread(fp, buffer, len) != len)
		return FALSE;
	else
		return TRUE;
}

⌨️ 快捷键说明

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