Я сделал декодер сжатых LZW изображений TIFF, и все части работают, он может декодировать большие изображения с различной глубиной в битах с горизонтальным прогнозированием или без него, кроме одного случая. Хотя он прекрасно декодирует файлы, написанные большинством программ (например, Photoshop и Krita с различными вариантами кодирования), в файлах, созданных с помощью ImageMagick convert
, есть что-то очень странное, он генерирует коды LZW, которых еще нет в словаре, и я не не знаю, как с этим справиться.
В большинстве случаев 9-12-битный код в потоке LZW, которого еще нет в словаре, является следующим, который мой алгоритм декодирования попытается вставить в словарь (что, я не уверен, должно быть проблема, хотя мой алгоритм не работает на изображении, содержащем такие случаи), но иногда это может быть даже сотни кодов в будущем. В одном случае первый код после кода очистки (256) - 364, что кажется совершенно невозможным, учитывая, что код очистки очищает мой словарь от всех кодов 258 и выше, в другом случае код 501, когда мой словарь поднимается только до 317 !
Понятия не имею, как с этим справиться, но, похоже, я единственный, кто сталкивается с этой проблемой, декодеры в других программах нормально загружают такие изображения. Так как они это делают?
Вот суть моего алгоритма декодирования, очевидно, из-за того, сколько кода задействовано, я не могу компактно представить полный компилируемый код, но, поскольку это вопрос алгоритмической логики, этого должно быть достаточно. Он тесно следует алгоритму, описанному в официальной спецификации TIFF (стр. 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);
}
Что касается результатов, которые мой код дает в таких ситуациях, то из того, как это выглядит, совершенно ясно, что только те немногие коды плохо декодируются, все до и после корректно декодируется, но, очевидно, в большинстве случаев последующее изображение после из этих загадочных будущих кодов разрушается из-за смещения остальных декодированных байтов на несколько мест. Это означает, что мое чтение потока 9–12-битного кода является правильным, так что это действительно означает, что я вижу код 364 сразу после кода очистки словаря 256.
Редактировать: Вот пример файла , который содержит такие странные коды. Я также нашел небольшую загрузочную библиотеку TIFF LZW , которая страдает от той же проблемы, она вылетает , когда мой загрузчик находит первый странный код на этом изображении (код 3073, когда только словарь идет до 2051 года). Хорошо, что, поскольку это небольшая библиотека, вы можете протестировать ее с помощью следующего кода:
#include "loadtiff.h"
#include "loadtiff.c"
void loadtiff_test(char *path)
{
int width, height, format;
floadtiff(fopen(path, "rb"), &width, &height, &format);
}
И если кто-то настаивает на том, чтобы погрузиться в мой код (который должен быть ненужным, и это большая библиотека) вот с чего начать .