来自PNG的数据只能通过特定图像成功?

时间:2017-03-29 04:18:48

标签: png zlib inflate

尝试从PNG图像文件的IDAT块中充气数据时遇到了一些麻烦。到目前为止,我能够读取IHDR块并返回正确的数据。但是,当我尝试解压缩以获取文件的原始RGB值时,我只能在1个图像上成功,而从其他图像获得0。这是我用来从zlib充气的代码。

unsigned char temp[4];
fread(&temp,1,4,pf);
unsigned int ihdr_size = convert_endian(temp);

unsigned char blk[ihdr_size + 8];
fread(blk,1,ihdr_size + 8,pf);

if (check_ihdr(blk) == -1){
    fclose(pf);
    return -1;
}
this->width  = convert_endian(blk+4);
this->height = convert_endian(blk+8);
long area = this->width*this->height*3 +this->height+1;
printf("%ld x %ld\n",this->width, this->height);
printf("Bit depth: %1x\n", (unsigned char)blk[12]);
printf("Color type: %1x\n", (unsigned char)blk[13]);

while(fread(&temp,1,4,pf) > 0){
    unsigned int bsize = convert_endian(temp);
    unsigned char chunk[bsize+8] = {0};
    fread(chunk,1, bsize+8,pf);   //8 extra for block name and CRC
    if (chunk_type(chunk)== 1){ //IDAT
        this->picture = new unsigned char[area];

        z_stream infstream;
        infstream.zalloc = Z_NULL;
        infstream.zfree = Z_NULL;
        infstream.opaque = Z_NULL;
        infstream.avail_in = bsize; // size of input
        infstream.next_in = chunk+4; // input char array (without chunk name)
        infstream.avail_out = area; // size of output
        infstream.next_out = this->picture; // output char array

        inflateInit(&infstream);
        if (int er = inflate(&infstream, Z_NO_FLUSH) != Z_STREAM_END){
            printf("Error!\n");
        }
        inflateEnd(&infstream);
        printf("OUT:%d %ld\n", infstream.avail_out, area);
        for (long i = 0; i < 1000; i+=4){
            printf("%x %x %x\n",this->picture[i], this->picture[i+1], this->picture[i+2]);
        }


    }
    printf("B:%x\n",bsize);
    printf("%c%c%c%c\n",chunk[0], chunk[1], chunk[2], chunk[3]);
}

从上面开始,我成功地使用此图像获取RGB值 image#1 但是,当我尝试使用此图片时image2 (相同的图像但被裁剪),程序只能返回RGB数据的前3个字节(其余为零)。有没有我用这段代码错误实现的东西?

1 个答案:

答案 0 :(得分:1)

您没有正确解释结果。你有一个*的原因是图像的每一行都有一个过滤字节。对于“成功”的图像,过滤字节全部为零,表示没有过滤。这意味着像素值直接出现在解压缩数据中。即使在这种情况下,您也会显示像素值的错误字节,因为您没有查看并移过过滤器字节。

对于未“成功”的图像,第一行使用过滤器1,后续行使用过滤器2.过滤器1是 Sub 过滤器,表示先前的像素值已从它们中减去前一个像素值。 2表示 Up 过滤器,其中第一行之后的每个像素值都具有从该位置减去的前一行的像素值。这就是为什么在第一个之后的几乎所有(但全部)值都为零的原因。仔细看看结果。