You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++提取PNG图片宽高异常求助:宽度正常高度输出错误

修正C++读取PNG宽高的错误

问题现象

输入尺寸为2264像素×2382像素的PNG图片,程序输出:
Image width: 2382, Image height: 1229472850
宽度值错误,高度值完全乱码。

错误原因分析

  1. 块结构解析错误:PNG文件头(8字节)之后,第一个块(IHDR)的结构是「4字节块长度 + 4字节块类型 + 块数据 + 4字节CRC」。原代码跳过文件头后,直接读取后续4字节作为块类型,实际读取的是块长度字段,导致后续宽高的读取位置完全偏移。
  2. 宽高读取顺序颠倒:PNG的IHDR块数据中,宽度字段在前,高度字段在后,原代码先读取高度再读取宽度,顺序完全相反。

修正后的代码

int loadImage(std::string fileName, void(*inputConversionType)()) {
    // 提取文件扩展名
    size_t dotPos = fileName.rfind(".");
    if (dotPos == std::string::npos) {
        std::cout << "Error: invalid file name, no extension found" << std::endl;
        return 1;
    }
    std::string extension = fileName.substr(dotPos + 1);

    // 二进制模式打开文件
    std::ifstream file(fileName, std::ios::binary);
    if (!file.is_open()) {
        std::cout << "Error: unable to open file " << fileName << std::endl;
        return 1;
    }
    // 获取文件大小并读取到缓冲区
    file.seekg(0, std::ios::end);
    int fileSize = file.tellg();
    file.seekg(0, std::ios::beg);
    std::vector<unsigned char> buffer(fileSize);
    file.read(reinterpret_cast<char*>(&buffer[0]), buffer.size());
    file.close();

    if (extension == "png") {
        if (buffer.size() < 24) { // 文件头(8) + 块长度(4) + 类型(4) + 宽(4)+高(4) = 24,最小有效长度
            std::cout << "Not a valid PNG file" << std::endl;
            return 1;
        }
        std::vector<unsigned char>::iterator it = buffer.begin();
        // 验证PNG文件头
        if (*it != 137 || *(it + 1) != 80 || *(it + 2) != 78 || *(it + 3) != 71 || 
            *(it + 4) != 13 || *(it + 5) != 10 || *(it + 6) != 26 || *(it + 7) != 10) {
            std::cout << "Not a valid PNG file" << std::endl;
            return 1;
        }

        it += 8; // 跳过文件头

        // 跳过4字节的块长度(IHDR的长度固定为13,这里可以直接跳过)
        it += 4;

        // 读取并验证块类型是否为IHDR
        std::string type(it, it + 4);
        if (type != "IHDR") {
            std::cout << "IHDR block not found at expected position" << std::endl;
            return 1;
        }
        it += 4;

        // 读取宽度(大端字节序转主机字节序)
        unsigned int width = (*it++ << 24) | (*it++ << 16) | (*it++ << 8) | (*it++);
        // 读取高度
        unsigned int height = (*it++ << 24) | (*it++ << 16) | (*it++ << 8) | (*it++);

        std::cout << "Image width: " << width << ", Image height: " << height << std::endl;
    }
    return 0; // 补充缺失的返回值
}

关键修正点

  • 跳过PNG块的4字节长度字段,确保后续读取的是正确的块类型和数据。
  • 调整宽高读取顺序,先读宽度再读高度,符合PNG规范。
  • 增加IHDR块类型验证,提升鲁棒性。
  • 补充函数末尾的返回值,修复原代码的语法问题。

内容的提问来源于stack exchange,提问作者Calamaryi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:10:55