libpng大小为png

我的程序从不确定长度的数据流中读取。 当它读取PNG文件时,需要将其存储以供以后使用而不对其进行解码。 libpng是否提供了提供PNG大小的任何function,因此它知道要存储多少字节?

如果没有,我是否必须编写自己的PNG块解析器以跳过块直到结束块? 我想我可能还包括CRCvalidation,但它似乎非常复杂,这就是为什么我希望libpng提供一种透明地完成这一操作的方法。

最简洁的答案是不。 Libpng甚至没有返回单个块的长度,所以如果你使用libpng,你确实必须跳过所有块来找到PNG数据流的末尾。

libpng不返回块长度的原因是libpng是为流式传输而设计的,因此它不一定知道不确定长度的数据流有多长。 它所知道的是它已经读过的标题的块的长度。

您可以使用“pngcheck”读取PNG文件并生成长度为一的块列表。 请参阅http://www.libpng.org/pub/png/apps/pngcheck.html Pngcheck是开源的,因此您可以根据自己的需要进行调整。

这可能是非常愚蠢的,但如果您不需要解码PNG,为什么不忘记它是PNG,只需通过分配固定的最小内存量并将分配的大小加倍来存储它就像使用realloc

这是一个简单的 PNG块式转储器。 它不会尝试CRCvalidation或存储块的数据,但至少应该给出如何读取块的一般概念。 警告:这只是我匆忙拼凑起来并且从未需要升级的东西,因此它不是任何一段时间内最干净的代码的例子。 但是,它确实validation该文件至少包含PNG文件的一些正确签名,并显示文件中包含的图像的尺寸。

 #include  #include  #include  #include  #pragma comment(lib, "ws2_32.lib") typedef unsigned int uint32_t; bool file_header(std::istream &in) { unsigned char buffer[8]; static const unsigned char valid[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; in.read((char *)&buffer, sizeof(buffer)); return std::mismatch(buffer, buffer+sizeof(buffer), valid).first == buffer+sizeof(buffer); } long read_net_long(std::istream &in) { long temp; in.read((char *)&temp, sizeof(temp)); return ntohl(temp); } bool is_iend(std::istream &in) { uint32_t length; char sig[5] = {0}; char iend[5] = "IEND"; uint32_t CRC; length = read_net_long(in); in.read((char *)&sig, 4); in.ignore(length); CRC = read_net_long(in); std::cout << "found: " << sig << ", length = " << length << "\n"; return std::mismatch(sig, sig+sizeof(sig), iend).first == sig+sizeof(sig); } #pragma pack(push, 1) class ihdr { uint32_t signature; uint32_t length; uint32_t width; uint32_t height; unsigned char depth; unsigned char color_type; unsigned char compression_method; unsigned char filter_method; unsigned char interlacing; uint32_t CRC; public: friend std::istream &operator>>(std::istream &is, ihdr &h) { is.read((char *)&h, sizeof(h)); if (h.signature != 218103808) std::cerr << "Invalid chunk: " << h.signature << "\n"; h.width = ntohl(h.width); h.height = ntohl(h.height); return is; } friend std::ostream &operator<<(std::ostream &os, ihdr const &h) { return std::cout << "width: " << h.width << ", height: " << h.height << "\n"; } }; #pragma pack(pop) void dump_ihdr(std::istream &in) { ihdr header; in >> header; std::cout << header; } int main(int argc, char **argv) { if (argc != 2) { std::cerr << "Usage: read_png "; return 1; } std::ifstream in(argv[1], std::ios::binary); std::cout << argv[1] << "\n"; if (file_header(in)) { dump_ihdr(in); while (!is_iend(in)) if (!in) { std::cout << "Reached EOF without finding IEND chunk\n"; return 1; } } else { std::cout << "Didn't find a PNG header\n"; return 1; } return 0; }