gif 解码问题(郁闷中)
最近在研究gif解码,理论是基本理解了,于是从网上下了个比较精简的源代码,其中解码部分如下:
哪位大哥能帮帮忙详细解释一下该代码原理吗?本人已经郁闷了很久,不解决心里又总不爽,先谢了!
LPUSTR CGIF::GetCodeDataOnBits (LPUSTR CodeDataStr, UINT InitLen, UINT &CodeDataLen)
{
LPUSTR p = CodeDataStr;
LPUSTR pData = (LPUSTR )GlobalAlloc(GPTR , m_CurWidth*m_CurHeight*2);
LPUSTR pTrueData = pData;
int i = 0;
UINT BitsCount = 0;
USHORT TCode,s = m_GifInfo.ColorType + 2; // string table 解码时从EOI + 1 开始
UINT TableLen,iLen = InitLen; // InitLen 为 图像位数+1
UINT Pos,index,j = 0;
UINT SrcCodeLEN = CodeDataLen;
while (1)
{
TCode = GetOneCode(p ,CodeDataLen,BitsCount / 8, BitsCount % 8, iLen);
BitsCount += iLen;
if (TCode < m_GifInfo.ColorType) // 在表内
{
LZWTable[j].Header = TCode;
LZWTable[j].Code = s++;
if (j != 0)
{
LZWTable[j - 1].Tail = TCode;
}
j++;
}
else if (TCode > m_GifInfo.ColorType + 1)// 不在表内
{
if (j == 0)
{
continue;
}
LZWTable[j].Header = TCode;
LZWTable[j].Code = s++;
ASSERT( LZWTable[j].Header < LZWTable[j].Code);
index = j - 1;
Pos = j;
while (1)
{
Pos = LZWTable[Pos].Header-(m_GifInfo.ColorType+2) ;
if (LZWTable[Pos].Header < m_GifInfo.ColorType) break;
}
LZWTable[index].Tail = LZWTable[Pos].Header;
j++;
}
else if (TCode == m_GifInfo.ColorType)// clear
{
iLen = InitLen;
TableLen = j;
j = 0;
GetPartImageDataFromTable(pData, LZWTable, TableLen);
s = m_GifInfo.ColorType + 2 ;
}
else if (TCode == m_GifInfo.ColorType + 1) // 结束
{
iLen = InitLen;
TableLen = j;
GetPartImageDataFromTable(pData, LZWTable, TableLen);
s = m_GifInfo.ColorType + 2;
break;
}
/*********************************************************************
我看别的源码里都是s==(1<<iLen)时就iLen++, 为何这里的一定要如此
**********************************************************************/
if ((s == (1<<iLen)+1) && (iLen < 12))
{
iLen++;
}
if (BitsCount / 8 > SrcCodeLEN)
{
iLen = InitLen;
TableLen = j;
GetPartImageDataFromTable(pData, LZWTable, TableLen);
s = m_GifInfo.ColorType + 2;
break;
}
}
CodeDataLen = BitsCount / 8;
return pTrueData;
}
void CGIF::GetPartImageDataFromTable(LPUSTR &pImage, LZWTABLE * Table, UINT TableLen)
{
UINT i;
LPUSTR p = pImage;
USHORT *TailStack = new USHORT[5200];
int j;
int sp;
for (i = 0 ; i < TableLen; i++)
{
if (Table[i].Header < m_GifInfo.ColorType)
{
*p++ = (UCHAR)Table[i].Header ;
}
else
{
sp = 0;
j = Table[i].Header - (m_GifInfo.ColorType + 2);
while (Table[j].Header > m_GifInfo.ColorType + 1)
{
TailStack[sp++] = Table[j].Tail ;
j = Table[j].Header;
j -= (m_GifInfo.ColorType + 2);
ASSERT(sp < 5200);
}
*p++ = (UCHAR)Table[j].Header;
*p++ = (UCHAR)Table[j].Tail;
sp --;
while (sp >= 0)
{
*p++ = (UCHAR)TailStack[sp--];
}
}
}
int len = p - pImage;
pImage = p;
delete []TailStack;
}
问题点数:100、回复次数:4Top
1 楼marcoxiong(marco)回复于 2005-05-31 16:53:10 得分 0
顺便付上源码下载地址:
http://www.try2it.com/show.asp?id=55
谢谢大家了!Top
2 楼marcoxiong(marco)回复于 2005-06-01 10:27:31 得分 0
等待中......................Top
3 楼NeoXiong(Neo)回复于 2005-06-02 18:05:19 得分 100
看了一下代码,以前也搞过一下gif。以下的标准gif解码参照gif89a。
在你的代码中,我觉得 LZWTABLE 由Header 与Tail 组成一个字符串,对于在表内的码解码时只算Head 这个字符。一旦遇到表外的码(这里跟标准gif解码不同,在标准gif解码中表外指还没有出现过的大于(1<<n)+1 的码,而该代码中则是只要大于就认为在表外),找到oldcode的第一个字符,这里我也没怎么看懂,是通过 - (m_GifInfo.ColorType + 2)实现的。解码时只要是表内的直接输出,表外的先找oldcode的第一个字符,再顺序输出,跟标准gif解码的思想差不多,不过个人觉得标准gif解码的代码实现很容易看懂又比较精简。对于 if ((s == (1<<iLen)+1) && (iLen < 12))
{
iLen++;
}
在gif89a 中是s == (1<<iLen) 时就++, 这里是因为clear 后的第一项也作
为一般的加进了string table 中,而gif89a 中的clear 后第一项是没加
进string table 直接输出的,因而这里的为(1<<iLen)+1
基本上就这些了,大家多交流一下。Top
4 楼marcoxiong(marco)回复于 2005-06-04 09:28:08 得分 0
好,谢了!Top




