Расшифровка кодов TIFF LZW еще нет в словаре - PullRequest
0 голосов
/ 14 апреля 2019

Я сделал декодер сжатых 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);
}

И если кто-то настаивает на том, чтобы погрузиться в мой код (который должен быть ненужным, и это большая библиотека) вот с чего начать .

1 Ответ

2 голосов
/ 16 апреля 2019

Фальшивые коды приходят от попыток декодировать больше, чем мы должны.Проблема состоит в том, что полоса LZW может иногда не заканчиваться кодом конца информации 257, поэтому цикл декодирования должен останавливаться, когда выводится определенное количество декодированных байтов.Это число байтов на полосу определяется тегами TIFF ROWSPERSTRIP * IMAGEWIDTH * BITSPERSAMPLE / 8 и, если PLANARCONFIG равен 1 (что означает чередующиеся каналы, а не плоские), умножив все это на SAMPLESPERPIXEL.Таким образом, помимо остановки цикла декодирования, когда встречается код 257, цикл также должен быть остановлен после того, как достигнуто это количество декодированных байтов.

...