5

我正在尝试读取 PNG 文件的宽度和高度。这是我的代码:

struct TImageSize {
    int width;
    int height;
};

bool getPngSize(const char *fileName, TImageSize &is) {
    std::ifstream file(fileName, std::ios_base::binary | std::ios_base::in);

    if (!file.is_open() || !file) {
        file.close();
        return false;
    }

    // Skip PNG file signature
    file.seekg(9, std::ios_base::cur);

    // First chunk: IHDR image header
    // Skip Chunk Length
    file.seekg(4, std::ios_base::cur);
    // Skip Chunk Type
    file.seekg(4, std::ios_base::cur);

    __int32 width, height;

    file.read((char*)&width, 4);
    file.read((char*)&height, 4);

    std::cout << file.tellg();

    is.width = width;
    is.height = height;

    file.close();

    return true;
}

例如,如果我尝试从 Wikipedia 的这张图片中阅读,我会得到这些错误的值:

252097920(应为800)
139985408(应为600)

请注意,该函数不会返回 false,因此宽度和高度变量的内容必须来自文件。

4

2 回答 2

8

看起来你偏离了一个字节:

// Skip PNG file signature
file.seekg(9, std::ios_base::cur);

PNG 规范说标头长 8 个字节,因此您希望将“9”改为“8”。职位从 0 开始。

另请注意,规范说整数是网络(大端)顺序,所以如果你在一个小端系统上,你可能想要或需要使用ntohl()或以其他方式转换字节顺序。

可能值得使用libpngstb_image或类似的东西,而不是尝试自己解析 png——除非你这样做是为了学习。

于 2012-12-29T16:51:13.360 回答
3

当您查看Portable Network Graphics Technical details时,它说签名是 8 个字节而不是 9 个。

另外,您确定您的系统具有与 PNG 标准相同的字节顺序吗?ntohl(3)将确保正确的字节顺序。也可用于 Windows。

于 2012-12-29T16:51:52.097 回答