尝试为png IDAT块充气时发生Z_DATA_ERROR

时间:2018-11-26 04:24:22

标签: c++ binary png zlib inflate

我在将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标准,但对于哪些字节实际上需要流到inflate函数中以及哪些字节需要剥离方面感到困惑。 m_data实际上只是来自块的数据,没有长度,类型和CRC。 反过来,m_length只是所述块所给定的长度。

输入也只是纯RGB,压缩模式为0,滤镜模式为0,隔行模式为0。

CM是8。

CMINFO是112。

FCHECK是30。

FDICT为0。

FLEVEL是64。

TL; DR:zlib想要/需要什么准确

这也是我尝试读取的图像的十六进制值的图片。 picture link because stackoverflow doesn't allow new users to post pics

1 个答案:

答案 0 :(得分:1)

78 5e ed d1 ...之后的IDAT是zlib流的开始。它的长度为288个字节,并且与所有PNG数据一样,都是有效的zlib流。如果您正确地读取了数据,将正确的部分充气并提供了足够的输出空间(请参阅下面的#2),那么它将起作用。

您对代码的一些评论:

  1. 您不需要尝试解码zlib标头。只需喂饱整个东西就可以充气。
  2. compressBound()在这里没有用。那仅用于压缩,而不用于解压缩。 228字节的压缩数据解压缩为47,234字节。
  3. 所得的解压缩数据不是原始RGB像素。图片的每一行都以过滤器字节开头,该行中的其余字节需要相应地解释。
  4. 您需要检查zlib函数中的返回码和错误。 始终检查返回码。总是。