我正在尝试用c ++实现一个简单的Gif-Reader。
我目前坚持解压缩Imagedata。
如果图像包含清除代码,则我的解压缩算法失败
在清除代码之后,我重建了 CodeTable ,将 CodeSize 重置为 MinimumLzwCodeSize + 1。
然后我阅读下一个代码并将其添加到indexstream。问题是清除后,下一个代码包含的值大于当前代码表的大小。
例如,来自维基百科的示例文件:rotating-earth.gif的代码值为262,但GlobalColorTable仅为256.
如何处理?
我根据gif spec.实现了lzw解压缩。
这是解压缩的主要代码部分:
int prevCode = GetCode(ptr, offset, codeSize);
codeStream.push_back(prevCode);
while (true)
{
auto code = GetCode(ptr, offset, codeSize);
//
//Clear code
//
if (code == IndexClearCode)
{
//reset codesize
codeSize = blockA.LZWMinimumCodeSize + 1;
currentNodeValue = pow(2, codeSize) - 1;
//reset codeTable
codeTable.resize(colorTable.size() + 2);
//read next code
prevCode = GetCode(ptr, offset, codeSize);
codeStream.push_back(prevCode);
continue;
}
else if (code == IndexEndOfInformationCode)
break;
//exists in dictionary
if (codeTable.size() > code)
{
if (prevCode >= codeTable.size())
{
prevCode = code;
continue;
}
for (auto c : codeTable[code])
codeStream.push_back(c);
newEntry = codeTable[prevCode];
newEntry.push_back(codeTable[code][0]);
codeTable.push_back(newEntry);
prevCode = code;
if (codeTable.size() - 1 == currentNodeValue)
{
codeSize++;
currentNodeValue = pow(2, codeSize) - 1;
}
}
else
{
if (prevCode >= codeTable.size())
{
prevCode = code;
continue;
}
newEntry = codeTable[prevCode];
newEntry.push_back(codeTable[prevCode][0]);
for (auto c : newEntry)
codeStream.push_back(c);
codeTable.push_back(newEntry);
prevCode = codeTable.size() - 1;
if (codeTable.size() - 1 == currentNodeValue)
{
codeSize++;
currentNodeValue = pow(2, codeSize) - 1;
}
}
}
答案 0 :(得分:4)
找到解决方案。
它被称为延迟明确代码。
因此,当我检查codeSize是否需要递增时,我还需要检查codeSize是否已经是max(12),因为可以获得具有最大代码大小的代码。
请参阅spec-gif89a.txt。
if (codeTable.size() - 1 == currentNodeValue && codeSize < 12)
{
codeSize++;
currentNodeValue = (1 << codeSize) - 1;
}