gpt4 book ai didi

c - 解码字典中没有的 TIFF LZW 代码

转载 作者:太空宇宙 更新时间:2023-11-04 07:48:04 24 4
gpt4 key购买 nike

我做了一个 LZW 压缩的 TIFF 图像解码器,所有部分都工作,它可以在有或没有水平预测的情况下解码各种位深度的大图像,除了一种情况。虽然它可以很好地解码大多数程序(如 Photoshop 和具有各种编码选项的 Krita)编写的文件,但 ImageMagick 的 convert 创建的文件有一些非常奇怪的地方,它会生成 LZW 代码,这些代码还没有出现在字典,我不知道如何处理它。

大多数时候,字典中还没有的 LZW 流中的 9 到 12 位代码是我的解码算法将尝试放入字典中的下一个代码(我不确定应该是这是一个问题,虽然我的算法在包含此类情况的图像上失败了),但有时它甚至可能是 future 的数百个代码。在一种情况下,明文代码 (256) 之后的第一个代码是 364,这似乎是不可能的,因为明文代码清除了我的所有代码 258 及以上的字典,在另一种情况下,当我的字典只达到 317 时,代码是 501 !

我不知道如何处理它,但似乎只有我有这个问题,其他程序中的解码器可以很好地加载此类图像。那么他们是怎么做到的呢?

这是我的解码算法的核心,显然由于涉及的代码太多,我无法以紧凑的方式提供完整的可编译代码,但由于这是一个算法逻辑问题,这应该足够了。它严格遵循官方TIFF specification中描述的算法。 (第 61 页),实际上大部分规范的伪代码都在注释中。

void tiff_lzw_decode(uint8_t *coded, buffer_t *dec)
{
buffer_t word={0}, outstring={0};
size_t coded_pos; // position in bits
int i, new_index, code, maxcode, bpc;

buffer_t *dict={0};
size_t dict_as=0;

bpc = 9; // starts with 9 bits per code, increases later
tiff_lzw_calc_maxcode(bpc, &maxcode);
new_index = 258; // index at which new dict entries begin
coded_pos = 0; // bit position

lzw_dict_init(&dict, &dict_as);

while ((code = get_bits_in_stream(coded, coded_pos, bpc)) != 257) // while ((Code = GetNextCode()) != EoiCode)
{
coded_pos += bpc;

if (code >= new_index)
printf("Out of range code %d (new_index %d)\n", code, new_index);

if (code == 256) // if (Code == ClearCode)
{
lzw_dict_init(&dict, &dict_as); // InitializeTable();
bpc = 9;
tiff_lzw_calc_maxcode(bpc, &maxcode);
new_index = 258;

code = get_bits_in_stream(coded, coded_pos, bpc); // Code = GetNextCode();
coded_pos += bpc;

if (code == 257) // if (Code == EoiCode)
break;

append_buf(dec, &dict[code]); // WriteString(StringFromCode(Code));

clear_buf(&word);
append_buf(&word, &dict[code]); // OldCode = Code;
}
else if (code < 4096)
{
if (dict[code].len) // if (IsInTable(Code))
{
append_buf(dec, &dict[code]); // WriteString(StringFromCode(Code));

lzw_add_to_dict(&dict, &dict_as, new_index, 0, word.buf, word.len, &bpc);
lzw_add_to_dict(&dict, &dict_as, new_index, 1, dict[code].buf, 1, &bpc); // AddStringToTable
new_index++;
tiff_lzw_calc_bpc(new_index, &bpc, &maxcode);

clear_buf(&word);
append_buf(&word, &dict[code]); // OldCode = Code;
}
else
{
clear_buf(&outstring);
append_buf(&outstring, &word);
bufwrite(&outstring, word.buf, 1); // OutString = StringFromCode(OldCode) + FirstChar(StringFromCode(OldCode));

append_buf(dec, &outstring); // WriteString(OutString);

lzw_add_to_dict(&dict, &dict_as, new_index, 0, outstring.buf, outstring.len, &bpc); // AddStringToTable
new_index++;
tiff_lzw_calc_bpc(new_index, &bpc, &maxcode);

clear_buf(&word);
append_buf(&word, &dict[code]); // OldCode = Code;
}
}

}

free_buf(&word);
free_buf(&outstring);
for (i=0; i < dict_as; i++)
free_buf(&dict[i]);
free(dict);
}

至于我的代码在这种情况下产生的结果,从外观上可以很清楚地看出,只有少数代码解码不当,之前和之后的所有内容都已正确解码,但显然在大多数情况下,后续图像在一个之后这些神秘的 future 代码中的一部分由于将其余解码字节移动了几个位置而被破坏了。这意味着我对 9 到 12 位码流的读取是正确的,所以这实际上意味着我在 256 位字典清除码之后看到了 364 码。

编辑:Here's an example file包含如此奇怪的代码。我还找到了 small TIFF LZW loading library遇到同样的问题,it crashes我的加载程序在该图像中找到第一个奇怪的代码的地方(当字典仅达到 2051 时代码为 3073)。好处是,由于它是一个小型库,您可以使用以下代码对其进行测试:

#include "loadtiff.h"
#include "loadtiff.c"
void loadtiff_test(char *path)
{
int width, height, format;
floadtiff(fopen(path, "rb"), &width, &height, &format);
}

如果有人坚持深入研究我的代码(这应该是不必要的,而且它是一个大库)here's where to start .

最佳答案

伪造的代码来自于尝试解码比我们预期的更多。问题是 LZW strip 有时可能不会以 End-of-Information 257 代码结束,因此当输出一定数量的解码字节时,解码循环必须停止。每个 strip 的字节数由 TIFF 标记 ROWSPERSTRIP * IMAGEWIDTH * BITSPERSAMPLE/8 确定,如果 PLANARCONFIG 为 1(这意味着交错 channel 而不是平面),则将其全部乘以 SAMPLESPERPIXEL。因此,除了在遇到代码 257 时停止解码循环之外,还必须在达到解码字节数后停止循环。

关于c - 解码字典中没有的 TIFF LZW 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55674925/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com