www.pudn.com > ScanDlg.rar > SckLzw.cpp


///////////////////////////////////////////////////////////////////////////// 
// SckLzw.cpp   LZW For GIF 编码和解码实现文件                             // 
// CopyRight(C)   1996,2008   TCSY 公司                                    // 
// Pentium Working Room   ShanChengKun   2003.08.18   更新                 // 
///////////////////////////////////////////////////////////////////////////// 
#include "stdafx.h" 
#include "SckLzw.h" 
 
//=========================================================================== 
// 通用LZW编码,编码阶段不需要String Table,只需要m_wTableIndex来获知写位数 
//=========================================================================== 
DWORD CSckLzw::LZW_Encode(const BYTE *InBuffer,      // 输入数据流 
						  DWORD  dwLength,           // 原数据大小 
						  BYTE *OutBuffer)           // 压缩后数据 
{ 
	WORD *pHash = new WORD [LZW_MAX_HASH_SIZE];      // Hash索引表 
	if(!pHash || !InBuffer || !OutBuffer) {if(pHash) delete[] pHash; return 0;} 
	memset(pHash, 0x00, LZW_MAX_HASH_SIZE * sizeof(WORD)); // Hash Table置位0 
	memset(OutBuffer, 0x00, dwLength * 2 + 2048);    // 目标全部清零 
 
	m_wTableIndex     = LZW_END + 1;                 // 初始化字符表 
	m_byCurrBits      = LZW_MIN_CODE_LEN + 1;        // 当前阶段码长 
	m_pCurrIn         = InBuffer;                    // 原始输入当前 
	m_pCurrOut        = OutBuffer;                   // 当前指针输出 
 
	DWORD dwCurrPixel = 0, dwHashIndex = 0;          // 当前写入点数 
	BYTE  byOutBit    = 0;                           // 输出缓冲位置 
	WORD  wPrefix     = m_pCurrIn[dwCurrPixel++];    // Hash索引前缀 
	WORD  wSuffix     = 0;                           // Hash索引后缀 
 
	Encode_WriteIndexOut(LZW_CLEAR, byOutBit);       // 写Clear首字节 
	while(dwCurrPixel < dwLength) 
	{ 
		wSuffix = m_pCurrIn[dwCurrPixel++];          // 提取当前数据 
		dwHashIndex = (wPrefix << 8) | wSuffix;      // 构造Hash地址 
 
		// 已在表中,取出索引, Hash Table中存放的是String Table的Index 
		if (pHash[dwHashIndex] != 0)                 // 编码可匹配 
		{ 
			wPrefix = pHash[dwHashIndex];            // 取出索引值 
		} 
 
		// 不在表中,把wPrefix + wSuffix添加到String Table中 
		else                                         // 没有则添加 
		{ 
			Encode_WriteIndexOut(wPrefix, byOutBit); 
			pHash[dwHashIndex] = m_wTableIndex++; 
			wPrefix = wSuffix; 
 
			if ((m_wTableIndex == 0x009) || (m_wTableIndex == 0x011) || 
				(m_wTableIndex == 0x021) || (m_wTableIndex == 0x041) || 
				(m_wTableIndex == 0x081) || (m_wTableIndex == 0x101) || 
				(m_wTableIndex == 0x201) || (m_wTableIndex == 0x401) || 
				(m_wTableIndex == 0x801)) 
				m_byCurrBits++; 
 
			// String Table(编码表)已经填满 
			else if (m_wTableIndex == LZW_MAX_TABLE_SIZE) 
			{ 
				Encode_WriteIndexOut (wSuffix,   byOutBit); 
				Encode_WriteIndexOut (LZW_CLEAR, byOutBit); 
 
				m_wTableIndex = LZW_END + 1; 
				m_byCurrBits  = LZW_MIN_CODE_LEN + 1; 
				memset(pHash, 0x00, LZW_MAX_HASH_SIZE * sizeof(WORD)); 
 
				wPrefix = m_pCurrIn[dwCurrPixel++]; 
			} 
		} 
	} 
	Encode_WriteIndexOut (wPrefix, byOutBit); 
	Encode_WriteIndexOut (LZW_END, byOutBit); 
	delete[] pHash; pHash = NULL; 
	return (m_pCurrOut - OutBuffer + 1);             // 释放并返回 
} 
 
//=========================================================================== 
// 解码到目标8位色位图,目标为8位色,自身递归调用 
//=========================================================================== 
void CSckLzw::Decode_WriteStringOut(LZW_STRING * pString, WORD wPrefix, DWORD &dwCurrPixel) 
{ 
	if(wPrefix < LZW_CLEAR) 
	{ 
		m_pCurrOut[dwCurrPixel++] = (BYTE)pString[wPrefix].wSuffix; 
	} 
	else 
	{ 
		Decode_WriteStringOut(pString, pString[wPrefix].wPrefix, dwCurrPixel); 
		Decode_WriteStringOut(pString, pString[wPrefix].wSuffix, dwCurrPixel); 
	} 
} 
 
//=========================================================================== 
// 通用LZW解码 
//=========================================================================== 
DWORD CSckLzw::LZW_Decode (const BYTE *InBuffer,     // 输入的数据流 
						   BYTE *OutBuffer)          // 解压后的数据 
{ 
	LZW_STRING *pString = new LZW_STRING[LZW_MAX_TABLE_SIZE + 32]; 
	if(!pString || !InBuffer || !OutBuffer) return 0;// 字符串表空间 
	memset(pString, 0xFF, (LZW_MAX_TABLE_SIZE + 32) * sizeof(LZW_STRING)); 
	register WORD i;                                 // 初始化串后缀 
	for(i=0; i