Z_DATA_ERROR при попытке накачать png IDAT чанк - PullRequest
0 голосов
/ 26 ноября 2018

У меня проблемы с накачкой фрагмента png IDAT обратно в данные RGB.

void PNG::IDAT()
{
    int index = 0;
    char CMF = m_data[index];
    index++;

    //big endian
    char CM = CMF & 0b00001111;
    char CINFO = CMF & 0b11110000; 
    //For CM = 8, CINFO is the base-2 logarithm of the LZ77 window  size, minus eight(CINFO = 7 indicates a 32K window size).

    char FLG = m_data[index];
    index++;

    char FCHECK = FLG & 0b00011111; 
    //The FCHECK value must be such that CMF and FLG, when viewed as a 16 - bit unsigned integer stored in MSB order(CMF * 256 + FLG),  is a multiple of 31. //effort
    char FDICT =  FLG & 0b00100000;
    char FLEVEl = FLG & 0b11000000;

    char DICTID[4];
    if (FDICT > 0)
    {
        memcpy(DICTID, &m_data[index], 4);
        index += 4;
    }

    uLong outputLength = compressBound(m_length); 
    char* output = new char[outputLength];


    z_stream infstream;
    infstream.zalloc = Z_NULL;
    infstream.zfree = Z_NULL;
    infstream.opaque = Z_NULL;
    infstream.avail_in = m_length; // size of input
    infstream.next_in = (Bytef *)m_data; // input char array
    infstream.avail_out = outputLength; // size of output
    infstream.next_out = (Bytef *)output; // output char array

    inflateInit2(&infstream, 16 + MAX_WBITS);
    inflate(&infstream, Z_NO_FLUSH);
    inflateEnd(&infstream);


    for (size_t i = 0; i < outputLength; i+= 3)
    {
        pixel temp;
        temp.r = output[i + 0];
        temp.g = output[i + 1];
        temp.b = output[i + 2];
        m_pixels.push_back(temp);
    }
}

Inflate возвращает код ошибки -3, что означает "Z_DATA_ERROR".Я следовал стандартам RFC-1950 и RFC-1951, но меня смущает вопрос, какие байты действительно должны быть направлены в функцию надувания, а какие - на удаление.m_data - это буквально данные из чанка без длины, типа и CRC.В свою очередь, m_length - это только длина, заданная этим фрагментом.

Вход также является простым RGB, с режимом сжатия 0, режимом фильтра 0 и режимом чересстрочной развертки 0.

CM равен 8.

CMINFO - 112.

FCHECK - 30.

FDICT - 0.

FLEVEL - 64.

TL; DR: что точно хочет ли / надувает функция inflate из zlib?

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

1 Ответ

0 голосов
/ 28 ноября 2018

78 5e ed d1 ... сразу после IDAT является началом потока zlib.Он имеет длину 288 байт и является допустимым потоком zlib, как и все данные PNG.Если вы правильно прочитали данные, набрали правильную порцию для раздувания и предоставили достаточно места для вывода (см. # 2 ниже), то это сработает.

Некоторые комментарии к вашему коду:

  1. Вам не нужно пытаться декодировать заголовок zlib.Просто кормите все это, чтобы надуть.
  2. compressBound() здесь бесполезен.Это только для сжатия, а не для распаковки.Эти 228 байтов сжатых данных распаковываются до 47,234 байта.Гораздо больше, чем вы выделили.
  3. Полученные распакованные данные , а не необработанные пиксели RGB.Каждая строка изображения начинается с байта фильтра, а остальные байты в строке необходимо интерпретировать соответствующим образом.
  4. Необходимо проверить код возврата и ошибки в функциях zlib. Всегда проверять коды возврата.Всегда.
...