My program reads from a data stream of indeterminate length. When it reads a PNG file it needs to store it for later and not decode it. Does libpng provide any function for
This is a simple PNG chunk-dumper. It doesn't attempt CRC verification or storing the data for the chunks, but should give at least some general notion of how to read through the chunks. Warning: this is just something I whipped together in a hurry and have never had a need to upgrade, so it's not an example of the cleanest code ever, by any stretch of the imagination. It does, however, verify that the file contains at least some of the correct signatures for a PNG file, and display the dimensions of the image contained in the file.
#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;
}