c++ PNG报头误读了IHDR数据块的长度、宽度和高度

C++ PNG header missread IHDR data chunk length, width and height

本文关键字:高度 数据 报头 PNG IHDR c++      更新时间:2023-10-16

我试图为一个类创建一个方法,该方法简单地读取PNG文件直到IHDR图像头(没有其CRC32块)的末尾。麻烦来自于每个"超过一个字节"的整数(即IHDR数据块的长度,宽度和高度)。下面是我的代码:

#include <iostream>
#include <fstream>
using namespace std;
typedef struct PNG_HEADER pngHeader;
struct PNG_HEADER{
    unsigned char PNGSignature[8];
    size_t nb;
    unsigned char ImageHeader[4];
    size_t width;
    size_t height;
    unsigned char bitDepth;
    unsigned char colorType;
    unsigned char compressionMethod;
    unsigned char filterMethod;
    unsigned char interlaceMethod;
};
class testPNG{
public:
    bool readPNGHeader(string filename){
        pngHeader PNGheader;
        ifstream file(filename.data(), std::ios_base::binary);
        if(!file.is_open())
            return false;
        if( !file.read((char *)&PNGheader, sizeof(PNGheader)))
            return false;

        for(int i = 0; i < 8; i++)
                printf("%d ", PNGheader.PNGSignature[i]);
        printf("n");
        printf("%dn", PNGheader.nb);
        for(int i = 0; i < 4; i++)
                printf("%d ", PNGheader.ImageHeader[i]);
        printf("n");
        printf("%dn", PNGheader.width );
        printf("%dn", PNGheader.height );
        printf("%dn", PNGheader.bitDepth );
        printf("%dn", PNGheader.colorType );
        printf("%dn", PNGheader.compressionMethod );
        printf("%dn", PNGheader.filterMethod );
        printf("%dn", PNGheader.interlaceMethod );
        return true;
    }
};

int main(void)
{
    testPNG test;
    test.readPNGHeader("test.png");
    return 0;
}

打印的结果是这样的(注释显然没有显示在控制台上):

137 80 78 71 13 10 26 10 //[PNG Signature OK!][1]
218103808                //this should read 13 as the length is the sum of the number of byte needed for each data field contained in the IHDR Data chunk that follows the IHDR Image Header chunk.
73 72 68 82              //[IHDR Image Header chunk OK!][2]
1879244800               //fail to give the correct width
973078528                //fail to give the correct height
8                        // OK!
6                        // OK!
0                        // OK!
0                        // OK!
0                        // OK!

正如w3c网站上写的那样;数据块的长度值存储在"一个四字节的无符号整数"中。图像的宽度和高度也是如此。所以我也尝试了unsigned int和unsigned short,但似乎都不起作用。

即使我使用printfs(我不知道如何用cout将字符格式化为int),如果可能的话,我正在寻找c++解决方案。

谢谢

您的机器或您的编译器使用相反的顺序来存储多字节值。

参见同一参考文献中的"7.1整数和字节顺序":

所有需要一个以上字节的整数必须按网络字节顺序排列…

后面跟着一个说明它的图表。

要获得字节数的正确值,使用预定义的函数之一反转它们(我永远记不起哪个函数做什么;请参阅如何编写(可移植的)反向网络字节顺序?)或自己编写。

您的样例值218103808显示0xD000000时,以十六进制印刷;反转字节产生正确的,预期的结果0xD13