diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 99 |
1 files changed, 99 insertions, 0 deletions
@@ -0,0 +1,99 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <errno.h> + +int main(int argc, char *argv[]) +{ +if (!argv[1]||!argv[2]){fprintf(stderr,"Usage: %s <binary file> <granulation level (0|1|2|3|4)>\n", argv[0]); exit(1);} + +int granulation; +/* For excessively large files, it's useful to skip a number of bytes after a false positive to save time despite the (small) chance of missing some png's */ +switch (*argv[2]) + { + case '0': + granulation = 8; + break; + case '1': + granulation = 64; + break; + case '2': + granulation = 4096; + break; + case '3': + granulation = 8192; + break; + case '4': + granulation = 10000; + break; + default: + fprintf(stderr,"Valid granulation levels: 0|1|2|3|4\n"); + exit(1); + } + +FILE *fp = fopen(argv[1],"rb"); +if (!fp){fprintf(stderr,"Could not open file!\n"); exit(1);} + +fseek(fp, 0L, SEEK_END); + +int length = ftell(fp); + +/* While we could read the file chunk by chunk, it's easier to just dump it into memory */ +char *data = malloc(length); +if (!data){fprintf(stderr,"Malloc failed!\n"); exit(1);} + +rewind(fp); + + +if (fread(data, 1, length, fp) != length){fprintf(stderr, "Bytes read and filesize length do not match!"); exit(1);} +fclose(fp); + +if (mkdir("pngs", S_IRWXU | S_IRWXG) == -1 && errno != EEXIST){fprintf(stderr,"Could not create png directory!\n"); exit(1);} + + +char *header; +int offset = 0; +int size; + +int count = 0; +char filename[5+4+4+1]; + +/* Search for png magic number in file */ +while (header=memmem(data+offset, length-offset, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8)) + { + /* Check for IHDR header, if this doesn't exist, there was a false positive, so skip ahead by granulation bytes */ + if (memcmp(header+8+4,"IHDR",4)){size = granulation; goto skip;} + + fprintf(stderr,"Found png at: %d\n", offset); + + /* Check for EOF magic number */ + char *iend = memmem(header+8, length-offset-8, "IEND", 4); + if (!iend){fprintf(stderr, "Png has no end!\n"); exit(1);} + + /* +4 bytes for the IEND and +4 for the crc after IEND */ + size = iend-header+8; + fprintf(stderr,"Png size: %d\n", size); + + /* Exit if digits no longer fit in filename */ + if (count > 9999){fprintf(stderr,"What are you doing?\n"); exit(1);} + + snprintf(filename, 14, "pngs/%d.png",count++); + FILE *out = fopen(filename,"wb"); + if (!out){fprintf(stderr,"Could not write file: %s!\n", filename); exit(1);} + + fprintf(stderr,"Writing png to: %s\n",filename); + + fwrite(header, 1, size, out); + fclose(out); + + skip:; + if (offset+size >= length){break;} + offset += size; + } + +free(data); + +return 0; +} |