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

📄 gif_pic.c

📁 GIF图片解压成RGB格式的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************/
/*       本软件所有权归深圳诺亚舟软件有限公司,任何未经          	*/
/*   授权使用或复制均属侵权行为,本公司有权予以追究。            	*/
/*                                        特  此  审  明!         	*/
/*  文件名:   Forula.h                                             	*/
/*  功  能:   图片预览窗口,GIF图片处理程序                        	*/
/*  版  本:   V0.10                                                	*/
/*  作  者: 														*/
/********************************************************************/
#include "..\\noahsys\\noahsys.h"
#include "..\\neplayer\\nepgdi.h"
#include "gif_pic.h"

#define GIFSIGN "GIF89a"
#define LZW_MAXCODES 4096
#define LZW_MAXBITS 12
#define TABLESIZES 4999
#define NOCODE -1
#define UINT_MAX 65536
#define TIMER_DELAY 20		//一个timer周期的时间

typedef struct{
	BYTE  *BlockBuf;
	INT32   *EncodeTable;
	INT32   InitBits;
	INT32   ClearCode;
	INT32   EofCode;
	INT32   Encode;
	INT32   RunBits;
	INT32   MaxCodeSize;
	INT32   ByteCount;
	INT32   ShiftBits;
	DWORD TempCode;
}LZWEncodeType;

static INT32 MaskCode[] = {
	0x0000,0x0001,0x0003,0x0007,
	0x000f,0x001f,0x003f,0x007f,
	0x00ff,0x01ff,0x03ff,0x07ff,
	0x0fff
};

static INT32 LineStart[] = {0,4,2,1};
static INT32 RowCount[]  = {8,8,4,2};
static void GetGifLine(Image *Img, BYTE* LineBuf, WORD LineCount, WORD LineBytes);
static int DecodeGifImage(Image *Img, PFILE File, BYTE Mode );

HPICVIEW hPicview;
/***************************************************
 功能: 根据所传入图象文件的名称,先申请所需要的Image数据结构
       存储单元,在读取该文件内的识别信息和图象数据
 输入: FileName ==> GIF图象文件名
 输出:
 返回:
 成功时,返回申请给Image数据结构的存贮单元指针
 失败时,则返回NULL值

***************************************************/
Image *ImageGifFileRead(PFILE File)
{
	Image	*Img = NULL;
	INT32	RetVal = SUCCESS;
	char	ByteBuf[16]; //= NULL;
	char	*Palette = NULL;
	BYTE	Lable;
	WORD	Type,GColorBits,ColorBytes;

	hPicview->nMaxPic = 0;

	//申请12个字节,用来保存GIF的文件头
// 	if( (ByteBuf = (BYTE*)NepMalloc(14)) == NULL )
// 	{
// 		hPicview->fError = MEMERROR;
// 		RetVal = MEMERROR;
// 		return Img;
// 	}

	if( NepFsRead(File,ByteBuf,13) != 13)
	{
		hPicview->fError = READERROR;
		RetVal = READERROR;
		return Img;
	}

	/* 读取表头信息 */
	if( !RetVal && strncmp(ByteBuf,"GIF",3) != 0 )
	{
		hPicview->fError = LABELERROR;
		RetVal = LABELERROR;
		return Img;
	}
	else
	{	//得到全局调色板的个数
		GColorBits = (ByteBuf[10] & 0x07 ) + 1;
		ColorBytes = 3 * ( 1 << GColorBits);

		//根据全居调色板的颜色个数,设置图象显得显示模式
		if( GColorBits == 1 )
			Type = 1;
		else if( GColorBits == 4 )
			Type = 2;
		else if( GColorBits == 8 )
			Type = 3;
		else
		{
			Type = 0;
			hPicview->fError = COLORERROR;
			RetVal = COLORERROR;
			return Img;
		}

		/* 读取通用调色板数据 */
		if( ByteBuf[10] & 0x80 )
		{
			if( (Palette = (BYTE*)NepMalloc(ColorBytes))== NULL)
			{
				hPicview->fError = MEMERROR;
				RetVal = MEMERROR;
				return Img;
			}
			else
			{
				if( NepFsRead(File,Palette,ColorBytes) != ColorBytes )
				{
					NepFree(Palette);
					Palette = NULL;
					hPicview->fError = LABELERROR;
					RetVal = LABELERROR;
					return Img;
				}

				//保存全局颜色变量
				memcpy(hPicview->pExternPattle,Palette,ColorBytes);
				hPicview->nColorBytes = 1 << GColorBits;
				NepFree(Palette);
				Palette = NULL;
			}
		}
	}

	NepFsRead(File,&Lable,1);
	while( !RetVal && (Lable == ',' || Lable == '!' || Lable == 0 ))
	{
		if( Lable == ',' )
		{
			//WORD* WordBuf;
			WORD  Width;
			WORD  Height;
			WORD  Color;
			WORD  LColorBits;

			//读取图象描述块的结构
			if( !RetVal && NepFsRead(File,ByteBuf,9) != 9 )
			{
				hPicview->fError = LABELERROR;
				RetVal = LABELERROR;
				return Img;
			}

			//WordBuf = (WORD*)ByteBuf;
			//Width = WordBuf[2];			//图象的宽度
			//Height = WordBuf[3];		//图象的高度
			Width = ((WORD)ByteBuf[5]<<8) + (ByteBuf[4]&0x00ff);
			Height = ((WORD)ByteBuf[7]<<8) + (ByteBuf[6]&0x00ff);

			LColorBits = (ByteBuf[8] & 0x07 ) + 1;	//得到图象是否存在局部调色板标志位

			//读取图象的局部调色板
			if( !RetVal && ByteBuf[8] & 0x80 )
			{
				if( LColorBits == 1 )
					Type = 1;
				else if( LColorBits == 4 )
					Type = 2;
				else if( LColorBits == 8 )
					Type = 3;
				else
				{
					Type = 0;
					hPicview->fError = COLORERROR;
					RetVal = COLORERROR;
					return Img;
				}
				
				ColorBytes = 3 * ( 1<< LColorBits );

				if( Palette != NULL && LColorBits > GColorBits )
				{
					NepFree( Palette );
					Palette = NULL;
				}

				/* 读取局部调色板数据 */
				if( Palette == NULL )
				{
					if( (Palette = (BYTE*)NepMalloc(ColorBytes)) ==NULL )
					{
						hPicview->fError = MEMERROR;
						RetVal = MEMERROR;
						return NULL;
					}
					else
					{
						if( !RetVal && NepFsRead(File,Palette,ColorBytes) != ColorBytes )
						{
							//NepFree(Palette);
							//Palette = NULL;
							hPicview->fError = READERROR;
							RetVal = READERROR;
							return NULL;
						}
					}
				}
			}

			//判断是否存在调色板(无论是局部调色板还是全局调色板)
			if( Palette == NULL )
				Color = 0;
			else
				Color = 1;

			//申请image
			if( !RetVal && Type && (Img = ImageAlloc(Type,Width,Height,1)) != NULL )
			{
				//判断是否需要初始化调色板
				if( Color )
				{
					if( ByteBuf[8] & 0x80)
					{	//保存局部颜色变量
						memcpy( Img->Color, Palette,ColorBytes);
						NepFree(Palette);
						Palette = NULL;
						Img->ColorBytes = 1<< LColorBits;
					}
					else
					{	//保存全局颜色变量
						memcpy( Img->Color, hPicview->pExternPattle,ColorBytes);
						Img->ColorBytes = hPicview->nColorBytes;
					}
				}
				else
				{	//保存全局颜色变量
					memcpy( Img->Color, hPicview->pExternPattle,ColorBytes);
					Img->ColorBytes = hPicview->nColorBytes;
				}

				//利用LZW解压缩方式解压图象数据
				if( RetVal = DecodeGifImage(Img,File, ByteBuf[8] & 0x40 ))
				{	//解压失败,退出
					GifImageFree(Img);
					Img = NULL;
				}
				else
				{
					//保存GIF的一桢图片数据
					hPicview->pImg[hPicview->nMaxPic] = Img;
					hPicview->nMaxPic++;
				}
			}
			else
			{
				if( !RetVal )
				{
					if(Type)
					{
						hPicview->fError = MEMERROR;
						RetVal = MEMERROR;
					}
					else
					{
						hPicview->fError = COLORERROR;
						RetVal = COLORERROR;
					}
				}
			}
		}
		else if( Lable == '!' )
		{
			//图形控制模块,0x21 + 0xf9
			//无格式文本扩展模块,0x21 + 0x01
			//注释模块,0x21 + 0xfe
			//应用扩展模块,0x21 + 0xff
			//匀以0x00结束
			BYTE Data;

			NepFsRead(File,&Data,1);

			if( Data == 0xf9 )
			{	//图形控制模块,0x21 + 0xf9
				BYTE  length;
				BYTE* pInfo;

				//
				NepFsRead(File,&length,1);		//读取块的长度
				pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * length);
				NepFsRead(File,pInfo,length);	//读取块信息

				//计算下一副图片的时间长度
				hPicview->PicTimeDelayBuf[hPicview->nMaxPic] = (pInfo[2]<<8) + pInfo[3];
				hPicview->PicTimeDelayBuf[hPicview->nMaxPic] /= TIMER_DELAY;
				if( hPicview->PicTimeDelayBuf[hPicview->nMaxPic] == 0 )
					hPicview->PicTimeDelayBuf[hPicview->nMaxPic] = 1;

				NepFree(pInfo);
			}
			else if( Data == 0xff )
			{	//应用扩展模块,0x21 + 0xff
				BYTE  length;
				BYTE* pInfo;

				//读取Application Identifier和Appl. Authentication Code
				//Application Identifier为8个字节,用来提供程序设计者的补充命名字
				//Appl. Authentication Code为3个字节,用来做扩展标识符号
				NepFsRead(File,&length,1);		//读取块的长度
				pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * length);
				NepFsRead(File,pInfo,length);	//读取块信息
				NepFree(pInfo);

				//读取Application Data
				//2007-7-21 tqh modify
				//修改原因,应用扩展块的结构为11个字节的标记+N个数据子块
				NepFsRead(File,&Data,1);
				while( Data != 0 )
				{
					//读取数据块的大小
					pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * Data);
					NepFsRead(File,pInfo,Data);	//读取块信息
					NepFree(pInfo);

					NepFsRead(File,&Data,1);
				}
			}
			else if( Data == 0x01 )
			{	//无格式文本扩展模块,0x21 + 0x01
				BYTE  length;
				BYTE* pInfo;

				NepFsRead(File,&length,1);		//读取块的长度
				pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * length);
				NepFsRead(File,pInfo,length);	//读取块信息
				NepFree(pInfo);
			}
			else
			{	//注释模块,0x21 + 0xfe
				while( Data != 0 )
				{
					NepFsRead(File,&Data,1);
				}
			}
		}
		NepFsRead(File,&Lable,1);
	}
	if(Palette != NULL)
	{
		NepFree(Palette);
		Palette = NULL;
	}

// 	if( ByteBuf!= NULL )
// 	{
// 		NepFree( ByteBuf );
// 		ByteBuf = NULL;
// 	}

	return Img;
}

/***************************************************
 功能: 解译GIF图象文件内以LZW压缩法编码的图象数据
       存储单元,在读取该文件内的识别信息和图象数据
 输入: Img ==> 存放Image数据结构的存储单元指针
       File ==> 图象文件的文件指针
	   mode ==> 设定图象数据的处理方式
	            0x00 顺序排列
				0x40 交叉排列
 输出:
 返回:
 成功时,返回SUCCESS
 失败时,则返回错误代码
***************************************************/
/*static*/ int DecodeGifImage(Image *Img, PFILE File, BYTE Mode )
{
	BYTE *SuffixTable;		//字尾表
	BYTE *StackTable;		//堆栈表
	BYTE *LineBuf;
	BYTE *BlockBuf;

	BYTE  *PrefixTable;		//字头表
	INT32   TableIndex = 0;	//代表字头及字尾索引值,也是字符对代码的启始值
	INT32   StackIndex = 0;
	INT32   InitBits = 0;		//代表图象点的Bits数
	INT32   EofCode = 0;		//代表结束码
	INT32   ClearCode = 0;	//代表清除码
	INT32   RunBits = 0;		//代表压缩数据的长度
	INT32   MaxCodeSize = 0;
	INT32   CurrentCode = 0;
	INT32   LastCode = 0;
	INT32   PrefixCode = 0;
	INT32   SuffixCode = 0;
	INT32   BlockIndex = 0;
	INT32   RetVal = SUCCESS;

	WORD  LineCount = 0;
	WORD  Pass = 0;
	int   DataCount = 0;
	WORD  ByteCount = 0;
	WORD  ShiftBits = 0;
	WORD  LineBytes = 0;

	DWORD TempCode;

	if( Img->Type == 1 || Img->Type == 2 )
	{
		LineBytes = (Img->width / 8 + (Img->width %8 ? 1:0)) * (Img->Type==2?4:1);
	}
	else
		LineBytes = Img->width;

	ByteCount = (LZW_MAXCODES<<2) + 256 + Img->width;
	StackTable = (BYTE*)NepMalloc(ByteCount*2);

	if( StackTable == NULL )
	{
		hPicview->fError = MEMERROR;
		RetVal = MEMERROR;
		return RetVal;
	}

	PrefixTable = (BYTE*)&StackTable[LZW_MAXCODES];
	SuffixTable = (BYTE*)&PrefixTable[LZW_MAXCODES*2];
	BlockBuf    = &SuffixTable[LZW_MAXCODES];
	LineBuf     = &BlockBuf[256];

	NepFsRead(File,&InitBits,1);
	ClearCode = 1 << InitBits;
	EofCode = ClearCode + 1;
	RunBits = InitBits + 1;
	LineCount = Pass = DataCount = ByteCount = ShiftBits = 0;
	BlockIndex = 0;
	TempCode = 0;

	while(!RetVal)
	{
		while(!RetVal && ShiftBits < RunBits )
		{
			if( BlockIndex == DataCount )
			{
				BlockIndex = 0;

				NepFsRead(File, &DataCount,1);
				if( !RetVal && DataCount == EOF )
				{
					hPicview->fError = DECODEERROR;
					RetVal = DECODEERROR;
				}
				if( !RetVal && NepFsRead(File,BlockBuf,DataCount) != DataCount )
				{
					hPicview->fError = DECODEERROR;
					RetVal = DECODEERROR;
				}
			}

			TempCode |= (DWORD)BlockBuf[BlockIndex++] << ShiftBits;
			ShiftBits += 8;
		}

		CurrentCode = TempCode & MaskCode[RunBits];
		TempCode >>= RunBits;
		ShiftBits -= RunBits;

		if( CurrentCode == EofCode )
			break;

		if( CurrentCode == ClearCode )
		{
			RunBits = InitBits + 1;
			TableIndex = EofCode + 1;
			MaxCodeSize = 1 << RunBits;
			PrefixCode = SuffixCode = NOCODE;
		}
		else
		{
			LastCode = CurrentCode;
			StackIndex = 0;
			if( CurrentCode == TableIndex )
			{
				StackTable[StackIndex++] = SuffixCode;
				CurrentCode = PrefixCode;
			}

			while( CurrentCode > EofCode && StackIndex < LZW_MAXCODES )
			{
				StackTable[StackIndex++] = SuffixTable[CurrentCode];
				//CurrentCode = PrefixTable[CurrentCode];
				CurrentCode = PrefixTable[2*CurrentCode] + ((WORD)PrefixTable[2*CurrentCode+1]<<8);
			}

			if( !RetVal && CurrentCode > EofCode || StackIndex >= LZW_MAXCODES )
			{
				hPicview->fError = DECODEERROR;
				RetVal = DECODEERROR;
			}

			SuffixCode = CurrentCode;
			while(!RetVal)
			{
				LineBuf[ByteCount++] = CurrentCode;

				if( ByteCount >= Img->width )
				{
					GetGifLine(Img,LineBuf,LineCount,LineBytes);

					ByteCount = 0 ;
					if( Mode != 0 )
					{
						LineCount += RowCount[Pass];
						if( LineCount >= Img->height)
						{
							Pass++;
							LineCount = LineStart[Pass];
						}
					}
					else
						LineCount++;
				}

				if( StackIndex == 0 )
					break;

				CurrentCode = StackTable[--StackIndex];

⌨️ 快捷键说明

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