C++提取PNG图片宽高异常求助:宽度正常高度输出错误
修正C++读取PNG宽高的错误
问题现象
输入尺寸为2264像素×2382像素的PNG图片,程序输出:Image width: 2382, Image height: 1229472850
宽度值错误,高度值完全乱码。
错误原因分析
- 块结构解析错误:PNG文件头(8字节)之后,第一个块(IHDR)的结构是「4字节块长度 + 4字节块类型 + 块数据 + 4字节CRC」。原代码跳过文件头后,直接读取后续4字节作为块类型,实际读取的是块长度字段,导致后续宽高的读取位置完全偏移。
- 宽高读取顺序颠倒: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
相关产品推荐
相关产品推荐

