/* * PNG Extractor */ #include #include #include unsigned long swap_endian(unsigned long x) { #ifdef BIG_ENDIAN return x; #else return x << 24 | (x << 8 & 0xFF0000) | (x >> 8 & 0xFF00) | x >> 24; #endif } size_t min(size_t a, size_t b) { return a < b ? a : b; } void fcopy(FILE *dest, FILE *src, size_t len) { int buf[1024]; size_t n; for ( ; (n = fread(buf, 1, min(len, sizeof buf), src)) != 0; len -= n) fwrite(buf, 1, n, dest); } void png_extract(const char *filename) { int out_i; FILE *fin; long type; if ((fin = fopen(filename, "rb")) == NULL) return; for (out_i = 0; fread(&type, 1, 4, fin) == 4; out_i++) { char outname[FILENAME_MAX]; FILE *fout; int x; int idat; while (type != *(const long *)"IHDR") { if ((x = fgetc(fin)) == EOF) goto end; memmove(&type, (char *)&type + 1, 3); ((char *)&type)[3] = (char)x; } sprintf(outname, "%s.%04d.png", filename, out_i); printf("\rExtracting: %s -> %d", filename, out_i); if ((fout = fopen(outname, "wb")) == NULL) { printf("\n Failed to create file !!\n"); abort(); } fwrite("\x89PNG\r\n\x1A\n", 1, 8, fout); fwrite("\0\0\0\x0D" "IHDR", 1, 8, fout); fcopy(fout, fin, 0x0D + 4); for (idat = 0; ; ) { unsigned long size; if (fread(&size, 1, 4, fin) != 4 || fread(&type, 1, 4, fin) != 4) goto end; if (!idat) { if (type == *(const long *)"IDAT") idat = 1; else { fwrite(&size, 1, 4, fout); fwrite(&type, 1, 4, fout); fcopy(fout, fin, swap_endian(size) + 4); continue; } } else { if (type != *(const long *)"IDAT") break; } fwrite(&size, 1, 4, fout); fwrite(&type, 1, 4, fout); fcopy(fout, fin, swap_endian(size) + 4); } fwrite("\0\0\0\0" "IEND" "\xAE\x42\x60\x82", 1, 12, fout); fclose(fout); } end: fclose(fin); printf("\n"); } int main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) png_extract(argv[i]); return 0; }