Skip to content

Instantly share code, notes, and snippets.

@fluffy-critter
Created October 18, 2015 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fluffy-critter/e37a49246f7a1fcfe534 to your computer and use it in GitHub Desktop.
Save fluffy-critter/e37a49246f7a1fcfe534 to your computer and use it in GitHub Desktop.
Extract embedded .png files from an uncompressed container
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdint>
#include <iomanip>
#include <cctype>
const uint8_t magicnum[8] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
const std::string magicstr(reinterpret_cast<const char*>(magicnum), 8);
void pngextract(const std::string& fname)
{
std::stringstream readbuf;
{
std::ifstream infile(fname);
readbuf << infile.rdbuf();
}
const std::string& buffer = readbuf.str();
std::string::size_type pos = 0;
int outnum = 0;
while ((pos = buffer.find(magicstr, pos)) < buffer.size()) {
std::cerr << "Found magic number at " << pos << std::endl;
std::string::size_type start = pos;
pos += 8;
while (pos < buffer.size()) {
uint32_t size = ((uint8_t)buffer[pos] << 24) | ((uint8_t)buffer[pos + 1] << 16) | ((uint8_t)buffer[pos + 2] << 8) |
(uint8_t)buffer[pos + 3];
pos += 4;
std::string chunk = buffer.substr(pos, 4);
pos += 4;
bool isValidChunk = true;
for (char c : chunk) {
if (!isprint(c)) {
std::cerr << "Got invalid byte " << std::hex << c << " in chunk type; skipping file" << std::endl;
isValidChunk = false;
break;
}
}
if (!isValidChunk) {
break;
}
if (pos + size > buffer.size()) {
std::cerr << "png at " << start << " has invalid " << chunk << " length " << size << "; skipping file" << std::endl;
break;
}
std::cerr << " Found chunk type=" << chunk << " size=" << size << std::endl;
pos += size + 4;
if (chunk == "IEND") {
std::stringstream outfname;
outfname << fname << "-" << outnum << ".png";
std::cout << outfname.str() << ": " << start << " - " << pos << std::endl;
std::ofstream outfile(outfname.str());
outfile << buffer.substr(start, pos - start);
++outnum;
break;
}
}
}
}
int main(int argc, char* argv[])
{
for (int i = 1; i < argc; i++) {
pngextract(argv[i]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment