C++ 尝试膨胀png IDAT块时出现Z_数据_错误

C++ 尝试膨胀png IDAT块时出现Z_数据_错误,c++,binary,png,zlib,inflate,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 th

我无法将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);
    }
}
void PNG::IDAT()
{
int指数=0;
char CMF=m_数据[索引];
索引++;
//大端
字符CM=CMF&0b00001111;
char CINFO=CMF&0b11110000;
//对于CM=8,CINFO是LZ77窗口大小的以2为底的对数减去8(CINFO=7表示32K窗口大小)。
char FLG=m_数据[索引];
索引++;
char FCHECK=FLG&0b00011111;
//FCHECK值必须使CMF和FLG在被视为以MSB顺序(CMF*256+FLG)存储的16位无符号整数时是31的倍数
字符FDICT=FLG&0b00100000;
char FLEVEl=FLG&0b11000000;
特征[4];
如果(FDICT>0)
{
memcpy(DICTID和m_数据[索引],4);
指数+=4;
}
uLong outputLength=压缩绑定(m_长度);
字符*输出=新字符[outputLength];
z_溪注入溪;
infstream.zalloc=Z_NULL;
infstream.zfree=Z_NULL;
infstream.opaque=Z_NULL;
infstream.avail_in=m_length;//输入的大小
infstream.next_in=(Bytef*)m_data;//输入字符数组
infstream.avail\u out=outputLength;//输出的大小
infstream.next_out=(Bytef*)输出;//输出字符数组
燃烧剂2(和注入流,16+最大值);
充气(和注入流,Z_无_冲洗);
充气(和注入流);
对于(大小i=0;i
充气
返回错误代码-3,表示“Z_数据错误”。我遵循了RFC-1950和RFC-1951标准,但我不清楚究竟哪些字节需要流式传输到充气功能中,哪些字节需要剥离。 m_数据实际上只是块中的数据,没有长度、类型和CRC。 m_length反过来只是所述区块给出的长度

输入也是纯RGB,具有压缩模式0、滤波模式0和隔行模式0

厘米是8

CMINFO是112

FCHECK是30

FDICT为0

弗莱维尔64岁

TL;DR:zlib的充气功能到底想要/需要什么

这里还有一张我正在读的图像的十六进制值的图片。
IDAT
之后的
78 5e ed d1…
是zlib流的开始。它有288字节长,是一个有效的zlib流,所有PNG数据也是如此。如果您正确读取了数据,输入了正确的部分进行充气,并提供了足够的输出空间(请参见下面的#2),那么它将正常工作

对代码的一些评论:

  • 您不需要尝试解码zlib头。把整个东西都喂进去充气就行了
  • compressBound()
    在这里没有用处。这只是用于压缩,而不是解压缩。228字节的压缩数据解压为47234字节。远远超过您分配的空间
  • 得到的解压缩数据不是原始RGB像素。图像的每一行都以一个过滤器字节开始,需要相应地解释该行中的剩余字节
  • 您需要检查zlib函数的返回代码和错误。始终检查返回代码。总是

  • 这张文本图片是否显示了您尝试解压缩的确切开始位置?它从其他几个未压缩的数据块开始。@usr2564301啊,我的错,这里是一个完整的图片,但是您应该使用什么来查找输出缓冲区的大小?我想你可以根据头文件中的所有信息用PNG来解决这个问题,但除此之外,这只是一个猜测,对吗?你只是想赚大钱,这样你就不会达到一个极限,还是有某种最佳情况下的压缩率,你可以根据它的大小来计算?你可以根据标题信息精确地计算出来。47234==113*(1+139*3)。1是每行上的筛选器字节。