WedX - журнал о программировании и компьютерных науках

Распаковка GIF LZW

Я пытаюсь реализовать простой Gif-Reader в C++.

В настоящее время я зациклился на распаковке данных изображения. Если изображение содержит Clear Code, мой алгоритм декомпрессии дает сбой.

После Clear Code я перестраиваю CodeTable и сбрасываю < strong>CodeSize в MinimumLzwCodeSize + 1.
Затем я читаю следующий код и добавляю его в индексный поток. Проблема в том, что после очистки следующие коды включают значения, превышающие размер текущей кодовой таблицы.
Например, пример файла из Википедии: rotating- earth.gif имеет кодовое значение 262, но GlobalColorTable — только 256.

Как с этим справиться?
Я применил распаковку lzw в соответствии с спецификацией gif.

вот основная часть кода распаковки:

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;
    }
}
}
12.11.2014

  • Рассматривали ли вы возможность взглянуть на существующие реализации C++ и понять, почему они работают, а ваши — нет? Кроме того, я действительно не рекомендую вызывать pow для вычисления степени двойки, так как для вычисления будет использоваться плавающая запятая. 12.11.2014
  • Вместо pow(2, codeSize) вы можете использовать (1 ‹‹ codeSize) . 13.11.2014
  • В настоящее время я просматриваю работающую программу чтения С#. Кажется, я получаю неправильный код после очистки. Я буду использовать сдвиг для выставки. из 2, спасибо. 13.11.2014

Ответы:


1

Решение найдено. Это называется Отложенный код очистки.
Поэтому, когда я проверяю, нужно ли увеличивать codeSize, мне также нужно проверить, является ли codeSize уже максимальным (12), так как можно получить коды с максимальным размером кода.
См. spec-gif89a.txt.

if (codeTable.size() - 1 == currentNodeValue && codeSize < 12)
{
   codeSize++;
   currentNodeValue = (1 << codeSize) - 1;
}
13.11.2014
  • просто это немного более ясно: когда таблица заполнена и имеет 4096 полей, она должна продолжать читать 12-битные целые числа без знака и должна прекратить вводить новые коды в таблицу, пока она не прочитает cc или eoi 19.02.2015
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]