diff --git a/tools/extract/extract.cpp b/tools/extract/extract.cpp new file mode 100644 index 0000000..f31cd2d --- /dev/null +++ b/tools/extract/extract.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +const uint32_t PNG_SIGNATURE = 0x89504E47; +const uint32_t PNG_END_SIGNATURE = 0xAE426082; + +bool readFileToBuffer(const std::string& filename, std::vector& buffer) { + std::ifstream file(filename, std::ios::binary); + if (!file) { + std::cerr << "Unable to open file: " << filename << std::endl; + return false; + } + + // Read the entire file into a buffer + buffer.assign((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + return true; +} + +void extractPNGs(const std::string& outdir, const std::vector& buffer) { + size_t offset = 0; + size_t fileCount = 0; + + while (offset < buffer.size() - 8) { // Ensure there's enough data for the end signature + // Look for the PNG signature + if (buffer[offset] == 0x89 && buffer[offset + 1] == 0x50 && + buffer[offset + 2] == 0x4E && buffer[offset + 3] == 0x47) { + + // Check for the end signature starting from the PNG signature position + size_t endOffset = offset; + while (endOffset <= buffer.size() - 4) { + if (buffer[endOffset] == 0xAE && buffer[endOffset + 1] == 0x42 && + buffer[endOffset + 2] == 0x60 && buffer[endOffset + 3] == 0x82) { + + // We found the end signature; extract the PNG + std::string outputFilename = std::to_string(fileCount++) + ".png"; + std::ofstream outFile(outdir + outputFilename, std::ios::binary); + if (outFile) { + outFile.write(reinterpret_cast(&buffer[offset]), endOffset - offset + 4); // Include end signature + std::cout << "Extracted: " << outputFilename << std::endl; + } else { + std::cerr << "Unable to create file: " << outputFilename << std::endl; + } + + // Move offset to end of current PNG + offset = endOffset + 4; // Move past the end signature + break; // Break to search for the next PNG + } + endOffset++; + } + } + offset++; + } +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + const std::string filename = argv[1]; // Take the input file from command-line argument + const std::string outdir = argv[2]; + std::vector buffer; + + if (readFileToBuffer(filename, buffer)) { + extractPNGs(outdir, buffer); + } + + return 0; +} \ No newline at end of file