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

📄 gifapi.cpp

📁 《VisualC++数字图像处理》配套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 *
 * 参数:
 *   CFile& file			- 源GIF文件
 *   LPWORD lpwMemLen		- 缓冲区长度(指针)
 *   LPDWORD lpdwDataLen	- 剩余数据长度(指针)
 *   LPSTR lpSrcBuff		- 缓冲区指针
 *	 LPBOOL lpbEOF			- 结束标志
 *
 * 返回值:
 *   无
 *
 * 说明:
 *   该函数用来读取指定GIF文件中的图像编码,每次最多读取MAX_BUFF_SIZE
 * 字节,是否读完由标志lpbEOF指定。
 *
 *************************************************************************/
void WINAPI ReadSrcData(CFile& file, LPWORD lpwMemLen, LPDWORD lpdwDataLen,
                        LPSTR lpSrcBuff, LPBOOL lpbEOF)
{
	// 判断数据长度是否仍然大于内存大小
	if ((*lpdwDataLen) > (DWORD)(*lpwMemLen))
	{
		// 数据长度大于内存大小,表示没有解码完
		
		// 数据长度减内存大小
		(*lpdwDataLen) -= (DWORD)(*lpwMemLen);
	}
	else
	{
		// 数据长度不大于内存大小,表示解码将要完成
		
		// 内存大小就是剩余数据长度
		(*lpwMemLen)    = (WORD)(*lpdwDataLen);
		
		// EOF标志设置为TRUE
		(*lpbEOF)       = TRUE;
	}
	
	// 读取编码数据
	file.Read(lpSrcBuff, (*lpwMemLen));
	
	// 返回
	return;
}

/*************************************************************************
 *
 * 函数名称:
 *   DecodeGIF_LZW()
 *
 * 参数:
 *   CFile& file			- 源GIF文件
 *   LPSTR lpDIBBits		- 指向要保存的DIB图像指针
 *   LPGIFD_VAR lpGIFDVar	- 指向GIFC_VAR结构的指针
 *	 WORD wWidthBytes		- 每行图像字节数
 *
 * 返回值:
 *   无
 *
 * 说明:
 *   该函数对指定GIF_LZW编码数据进行解码。
 *
 *************************************************************************/
void WINAPI DecodeGIF_LZW(CFile& file, LPSTR lpDIBBits,
						  LPGIFD_VAR lpGIFDVar,WORD wWidthBytes)
{
	// 指向编码后图像数据的指针
	BYTE *	lpDst;
	
	// 内存分配句柄
	HANDLE hPrefix;
	HANDLE hSuffix;
	HANDLE hStack;
	HANDLE hImage;
	
	// 用于字串表搜索的索引
	LPWORD lpwPrefix;
	LPBYTE lpbySuffix;
	LPBYTE lpbyStack;
	LPBYTE lpbyStackBgn;
	
	// 指向图像当前行解码结果的指针
	LPSTR  lpImageBgn;
	
	// 指向当前编码像素的指针
	LPSTR  lpImage;
	
	// 计算当前数据图像的偏移量
	DWORD  dwDataNdx;
	
	// LZW_CLEAR
	WORD   wLZW_CLEAR;
	
	// LZW_EOI
	WORD   wLZW_EOI;
	
	// LZW_MinCodeLen
	BYTE   byLZW_MinCodeLen;
	
	// 字串表索引
	WORD   wNowTableNdx;
	WORD   wTopTableNdx;
	
	// 当前图像的行数
	WORD   wRowNum;
	
	// 计数
	WORD   wWidthCnt;
	WORD   wBitCnt;
	WORD   wRowCnt;
	
	// 循环变量
	WORD   wi;
	
	// 交错方式存储时每次增加的行数
	WORD   wIncTable[5]  = { 8,8,4,2,0 }; 
	
	// 交错方式存储时起始行数
	WORD   wBgnTable[5]  = { 0,4,2,1,0 }; 
	
	// 块大小
	BYTE   byBlockSize;
	
	// 块索引
	BYTE   byBlockNdx;
	
	DWORD  dwData;
	
	// 当前编码
	WORD   wCode;
	
	// 上一个编码
	WORD   wOldCode;
	
	// 临时索引
	WORD   wTempNdx;
	
	WORD   wCodeMask[13] = {0x0000,
							0x0001,0x0003,0x0007,0x000F,
							0x001F,0x003F,0x007F,0x00FF,
							0x01FF,0x03FF,0x07FF,0x0FFF
							};
	
	BYTE   byLeftBits;
	BYTE   byFirstChar;
	BYTE   byCode;
	BYTE   byCurrentBits;
	BYTE   byPass;
	
	// 临时字节变量
	BYTE   byTempChar;
	
	// 给字串表分配内存
	hPrefix          = GlobalAlloc(GHND,(DWORD)(MAX_TABLE_SIZE<<1));
	hSuffix          = GlobalAlloc(GHND,(DWORD)MAX_TABLE_SIZE);
	hStack           = GlobalAlloc(GHND,(DWORD)MAX_TABLE_SIZE);
	hImage           = GlobalAlloc(GHND,(DWORD)wWidthBytes);
	
	// 锁定内存
	lpwPrefix        = (LPWORD)GlobalLock(hPrefix);
	lpbySuffix       = (LPBYTE)GlobalLock(hSuffix);
	lpbyStack        = (LPBYTE)GlobalLock(hStack);
	lpbyStackBgn     = lpbyStack;
	lpImage          = (LPSTR)GlobalLock(hImage);
	lpImageBgn       = lpImage;
	
	// 读取GIF LZW最小编码大小
	byLZW_MinCodeLen = *lpGIFDVar->lpBgnBuff++;
	
	byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;
	
	// 计算LZW_CLEAR
	wLZW_CLEAR       = 1 << byLZW_MinCodeLen;
	
	// 计算LZW_EOI
	wLZW_EOI         = wLZW_CLEAR + 1;
	
	// 计算字串表索引
	wNowTableNdx     = wLZW_CLEAR + 2;
	wTopTableNdx     = 1 << byCurrentBits;
	
	// 赋初值
	dwData           = 0UL;
	wBitCnt          = lpGIFDVar->wBits;
	wRowNum          = 0;
	wRowCnt          = 1;
	wWidthCnt        = 0;
	wCode            = 0;
	wOldCode         = 0xFFFF;
	byBlockSize      = 0x01;
	byBlockNdx       = 0x00;
	byLeftBits       = 0x00;
	byTempChar       = 0x00;
	byPass           = 0x00;
	
	// 读取下一个编码
	while(byLeftBits < byCurrentBits)
	{
		// 读取下一个字符
		
		// 判断是否读完一个数据块
		if (++byBlockNdx == byBlockSize)
		{
			// 读取下一个数据块
			byBlockSize = *lpGIFDVar->lpBgnBuff++;
			byBlockNdx  = 0x00;
			
			// 判断是否读完
			if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
			    !lpGIFDVar->bEOF)
			{
				// 读取下一个数据块
				ReadSrcData(file,&lpGIFDVar->wMemLen,
							&lpGIFDVar->dwDataLen,
							lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
				
				// 指针重新赋值
				lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
				lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
			}
		}
		
		// 下一个字符
		byCode      = *lpGIFDVar->lpBgnBuff++;
		
		// 移位
		dwData     |= ((DWORD)byCode << byLeftBits);
		byLeftBits += 0x08;
		
		// 判断是否读完
		if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
		    !lpGIFDVar->bEOF)
		{
			// 读取下一个数据块
			ReadSrcData(file,&lpGIFDVar->wMemLen,
						&lpGIFDVar->dwDataLen,
						lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
			
			// 指针重新赋值
			lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
			lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
		}
	}
	
	wCode       = (WORD)dwData & wCodeMask[byCurrentBits];
	dwData    >>= byCurrentBits;
	byLeftBits -= byCurrentBits;
	
	// 解码
	while(wCode != wLZW_EOI)
	{
		// 当前编码不是LZW_EOI码
		
		// 判断是否是LZW_CLEAR码
		if (wCode == wLZW_CLEAR)
		{
			// 是LZW_CLEAR,清除字串表
			
			// 重新初始化字串表
			for(wi = 0; wi < wLZW_CLEAR; wi++)
			{
				*(lpwPrefix  + wi)  = 0xFFFF;
				*(lpbySuffix + wi) = (BYTE)wi;
			}
			
			for(wi = wNowTableNdx; wi < MAX_TABLE_SIZE; wi++)
			{
				*(lpwPrefix+wi)  = 0xFFFF;
				*(lpbySuffix+wi) = 0x00;
			}
			
			byCurrentBits = byLZW_MinCodeLen + (BYTE)0x01;
			wNowTableNdx  = wLZW_CLEAR + 2;
			wTopTableNdx  = 1 << byCurrentBits;
			wOldCode      = 0xFFFF;
			
			// 获取下一个编码
			while(byLeftBits < byCurrentBits)
			{
				// 读取下一个字符
				
				// 判断是否读完一个数据块
				if (++byBlockNdx == byBlockSize)
				{
					// 读取下一个数据块
					byBlockSize = *lpGIFDVar->lpBgnBuff++;
					byBlockNdx  = 0x00;
					
					// 判断是否读完
					if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
						!lpGIFDVar->bEOF)
					{
						// 读取下一个数据块
						ReadSrcData(file, &lpGIFDVar->wMemLen,
									&lpGIFDVar->dwDataLen,
									lpGIFDVar->lpDataBuff,
									&lpGIFDVar->bEOF);
						
						// 指针重新赋值
						lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
						lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff +
											   lpGIFDVar->wMemLen;
					}
				}
				byCode      = *lpGIFDVar->lpBgnBuff++;
				dwData     |= ((DWORD)byCode << byLeftBits);
				byLeftBits += 0x08;
				
				// 判断是否读完
				if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
					 !lpGIFDVar->bEOF)
				{
					// 读取下一个数据块
					ReadSrcData(file,&lpGIFDVar->wMemLen,
								&lpGIFDVar->dwDataLen,
								lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
					
					// 指针重新赋值
					lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
					lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
				}
			}
			wCode       = (WORD)dwData & wCodeMask[byCurrentBits];
			dwData    >>= byCurrentBits;
			byLeftBits -= byCurrentBits;
			
			// 判断编码是否为LZW_EOI
			if (wCode!=wLZW_EOI)
			{
				// 这里没有用到lpbyStack[0]
				lpbyStack  ++;
				
				// 将数据压入堆栈
				while((*(lpwPrefix+wCode)) != 0xFFFF)
				{
					*lpbyStack++ = *(lpbySuffix+wCode);
					wCode        = *(lpwPrefix+wCode);
				}
				*lpbyStack  = *(lpbySuffix+wCode);
				byFirstChar = *lpbyStack;
				
				// 输出数据
				while(lpbyStack>lpbyStackBgn)
				{
					byTempChar |= (*lpbyStack-- << (8-wBitCnt));
					
					if (wBitCnt==8)
					{
						*lpImage++ = byTempChar;
						byTempChar = 0x00;
						wBitCnt    = lpGIFDVar->wBits;
					}
					else
					{
						wBitCnt   += lpGIFDVar->wBits;
					}
					
					wWidthCnt  ++;
					
					if (wWidthCnt==lpGIFDVar->wWidth)
					{
						if (wBitCnt!=lpGIFDVar->wBits)
						{
							*lpImage   = byTempChar;
							byTempChar = 0x00;
							wBitCnt    = lpGIFDVar->wBits;
						}
						
						// 图像当前行偏移量
						dwDataNdx = (DWORD)(lpGIFDVar->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
						
						// 图像当前行起始位置
						lpDst = (BYTE *)lpDIBBits + dwDataNdx;
						
						// 赋值
						memcpy(lpDst, lpImageBgn, wWidthBytes);
						
						lpImage   = lpImageBgn;
						
						// 判断是否按照交错方式保存
						if (lpGIFDVar->bInterlace)
						{
							// 交错方式
							
							// 计算下一行的行号
							wRowNum += wIncTable[byPass];
							if (wRowNum >= lpGIFDVar->wDepth)
							{
								byPass ++;
								wRowNum = wBgnTable[byPass];
							}
						}
						else
						{
							// 非交错方式,行号直接加1
							wRowNum ++;
						}
						wWidthCnt = 0;
					}
				}
			}
		}
		else
		{
			// 这里没有用到lpbyStack[0]
			lpbyStack  ++;
			
			// 判断字符串是否在字串表中
			if (wCode < wNowTableNdx)
			{
				// 不在字串表中
				wTempNdx   = wCode;
			}
			else
			{
				// 在字串表中
				wTempNdx     = wOldCode;
				*lpbyStack++ = byFirstChar;
			}
			
			// 将数据压入堆栈
			while((*(lpwPrefix+wTempNdx)) != 0xFFFF)
			{
				*lpbyStack++ = *(lpbySuffix+wTempNdx);
				wTempNdx     = *(lpwPrefix+wTempNdx);
			}
			*lpbyStack  = *(lpbySuffix+wTempNdx);
			byFirstChar = *lpbyStack;
			
			// 将字符串添加到字串表中
			*(lpwPrefix+wNowTableNdx)  = wOldCode;
			*(lpbySuffix+wNowTableNdx) = byFirstChar;
			if (++wNowTableNdx==wTopTableNdx && byCurrentBits<12)
			{
				byCurrentBits ++;
				wTopTableNdx   = 1 << byCurrentBits;
			}
			
			// 输出数据
			while(lpbyStack>lpbyStackBgn)
			{
				byTempChar |= (*lpbyStack-- << (8-wBitCnt));
				if (wBitCnt==8)
				{
					*lpImage++ = byTempChar;
					byTempChar = 0x00;
					wBitCnt    = lpGIFDVar->wBits;
				}
				else
				{
					wBitCnt   += lpGIFDVar->wBits;
				}
				
				wWidthCnt  ++;
				if (wWidthCnt==lpGIFDVar->wWidth)
				{
					if (wBitCnt!=lpGIFDVar->wBits)
					{
						*lpImage   = byTempChar;
						byTempChar = 0x00;
						wBitCnt    = lpGIFDVar->wBits;
					}
					
					// 图像当前行偏移量
					dwDataNdx = (DWORD)(lpGIFDVar->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
					
					// 图像当前行起始位置
					lpDst = (BYTE *)lpDIBBits + dwDataNdx;
					
					// 赋值
					memcpy(lpDst, lpImageBgn, wWidthBytes);
					
					lpImage   = lpImageBgn;
					
					// 判断是否按照交错方式保存
					if (lpGIFDVar->bInterlace)
					{
						// 交错方式
						
						// 计算下一行的行号
						wRowNum += wIncTable[byPass];
						if (wRowNum >= lpGIFDVar->wDepth)
						{
							byPass ++;
							wRowNum = wBgnTable[byPass];
						}
					}
					else
					{
						// 非交错方式,行号直接加1
						wRowNum ++;
					}
					wWidthCnt = 0;
				}
			}
		}
		wOldCode = wCode;
		
		// 读取下一个编码
		while(byLeftBits < byCurrentBits)
		{
			// 读取下一个字符
			
			// 判断是否读完一个数据块
			if (++byBlockNdx == byBlockSize)
			{
				// 读取下一个数据块
				byBlockSize = *lpGIFDVar->lpBgnBuff++;
				byBlockNdx  = 0x00;
				
				// 判断是否读完
				if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
					 !lpGIFDVar->bEOF)
				{
					// 读取下一个数据块
					ReadSrcData(file,&lpGIFDVar->wMemLen,
								&lpGIFDVar->dwDataLen,
								lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
					
					// 指针重新赋值
					lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
					lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
				}
			}
			byCode      = *lpGIFDVar->lpBgnBuff++;
			dwData     |= ((DWORD)byCode << byLeftBits);
			byLeftBits += 0x08;
			
			// 判断是否读完
			if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
				  !lpGIFDVar->bEOF)
			{
				// 读取下一个数据块
				ReadSrcData(file,&lpGIFDVar->wMemLen,
							&lpGIFDVar->dwDataLen,
							lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
				
				// 指针重新赋值
				lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
				lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
			}
		}
		wCode       = (WORD)dwData & wCodeMask[byCurrentBits];
		dwData    >>= byCurrentBits;
		byLeftBits -= byCurrentBits;
	}
	
	// 释放内存
	GlobalUnlock(hPrefix);
	GlobalUnlock(hSuffix);
	GlobalUnlock(hStack);
	GlobalFree(hPrefix);
	GlobalFree(hSuffix);
	GlobalFree(hStack);
	
	// 返回
	return;
}

⌨️ 快捷键说明

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