From a7e64717f51b898dcaa09b4e396019c35fd10bd7 Mon Sep 17 00:00:00 2001 From: kramm Date: Sat, 5 Jan 2002 16:28:40 +0000 Subject: [PATCH] Added PNG extraction feature. --- src/swfextract.1 | 6 ++ src/swfextract.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 251 insertions(+), 6 deletions(-) diff --git a/src/swfextract.1 b/src/swfextract.1 index 5f9281f..2f2ed5f 100644 --- a/src/swfextract.1 +++ b/src/swfextract.1 @@ -23,6 +23,12 @@ Print version info and exit \fB\-i\fR, \fB\-\-id\fR \fIids\fR \fIids\fR is a range of IDs to extract. E.g. 1-10,14 .TP +\fB\-j\fR, \fB\-\-jpegs\fR \fIids\fR +\fIids\fR is a range of JPEG IDs to extract. E.g. 1-2,3,14- +.TP +\fB\-p\fR, \fB\-\-pngs\fR \fIids\fR +\fIids\fR is a range of PNG IDs to extract. E.g. -10,20-30 +.TP \fB\-f\fR, \fB\-\-frame\fR \fIframes\fR \fIframes\fR is a range of frames to extract. E.g. 1-10,20-30,40- .TP diff --git a/src/swfextract.c b/src/swfextract.c index a04ae29..126eff4 100644 --- a/src/swfextract.c +++ b/src/swfextract.c @@ -13,6 +13,7 @@ #include "../lib/rfxswf.h" #include "../lib/args.h" #include "reloc.h" +#include "zlib.h" char * filename = 0; char * destfilename = "output.swf"; @@ -21,6 +22,7 @@ int verbose = 2; char* extractids = 0; char* extractframes = 0; char* extractjpegids = 0; +char* extractpngids = 0; char* extractname = 0; @@ -33,6 +35,7 @@ struct options_t options[] = {"v","verbose"}, {"i","id"}, {"j","jpegs"}, + {"p","pngs"}, {"n","name"}, {"f","frame"}, {"V","version"}, @@ -77,6 +80,14 @@ int args_callback_option(char*name,char*val) extractjpegids = val; return 1; } + else if(!strcmp(name, "p")) { + if(extractpngids) { + fprintf(stderr, "Only one --pngs argument is allowed. (Try to use a range, e.g. -p 1,2,3)\n"); + exit(1); + } + extractpngids = val; + return 1; + } else if(!strcmp(name, "f")) { extractframes = val; return 1; @@ -103,7 +114,8 @@ void args_callback_usage(char*name) printf("\t-o , --output filename\t\t set output filename\n"); printf("\t-n , --name name\t\t instance name of the object to extract\n"); printf("\t-i , --id IDs\t\t\t ID of the object to extract\n"); - printf("\t-j , --jpeg IDs\t\t\t IDs of the jpeg pictures to extract\n"); + printf("\t-j , --jpeg IDs\t\t\t IDs of the JPEG pictures to extract\n"); + printf("\t-p , --pngs IDs\t\t\t IDs of the PNG pictures to extract\n"); printf("\t-f , --frame frames\t\t frame numbers to extract\n"); printf("\t-w , --hollow\t\t\t hollow mode: don't remove empty frames (use with -f)\n"); printf("\t-V , --version\t\t\t Print program version and exit\n"); @@ -264,9 +276,9 @@ void listObjects(SWF*swf) char first; int t; int frame = 0; - char*names[] = {"Shapes","MovieClips","JPEGs","Sounds","Frames"}; + char*names[] = {"Shapes","MovieClips","JPEGs","PNGs","Sounds","Frames"}; printf("Objects in file %s:\n",filename); - for(t=0;t<5;t++) { + for(t=0;t<6;t++) { tag = swf->firstTag; first = 1; while(tag) { @@ -297,12 +309,19 @@ void listObjects(SWF*swf) sprintf(text,"%d", swf_GetDefineID(tag)); } - if(t == 3 && (tag->id == ST_DEFINESOUND)) { + if(t == 3 && (tag->id == ST_DEFINEBITSLOSSLESS || + tag->id == ST_DEFINEBITSLOSSLESS2)) { + show = 1; + sprintf(text,"%d", swf_GetDefineID(tag)); + } + + + if(t == 4 && (tag->id == ST_DEFINESOUND)) { show = 1; sprintf(text,"%d", swf_GetDefineID(tag)); } - if(t == 4 && (tag->id == ST_SHOWFRAME)) { + if(t == 5 && (tag->id == ST_SHOWFRAME)) { show = 1; sprintf(text,"%d", frame); frame ++; @@ -398,6 +417,223 @@ void handlejpeg(TAG*tag) } } +static U32 mycrc32; + +static U32*crc32_table = 0; +static void make_crc32_table(void) +{ + int t; + if(crc32_table) + return; + crc32_table = (U32*)malloc(1024); + + for (t = 0; t < 256; t++) { + U32 c = t; + int s; + for (s = 0; s < 8; s++) { + c = (0xedb88320L*(c&1)) ^ (c >> 1); + } + crc32_table[t] = c; + } +} +static void png_write_byte(FILE*fi, U8 byte) +{ + fwrite(&byte,1,1,fi); + mycrc32 = crc32_table[(mycrc32 ^ byte) & 0xff] ^ (mycrc32 >> 8); +} +static void png_start_chunk(FILE*fi, char*type, int len) +{ + U8 mytype[4]={0,0,0,0}; + U32 mylen = REVERSESWAP32(len); + memcpy(mytype,type,strlen(type)); + fwrite(&mylen, 4, 1, fi); + mycrc32=0xffffffff; + png_write_byte(fi,mytype[0]); + png_write_byte(fi,mytype[1]); + png_write_byte(fi,mytype[2]); + png_write_byte(fi,mytype[3]); +} +static void png_write_bytes(FILE*fi, U8*bytes, int len) +{ + int t; + for(t=0;t>24); + png_write_byte(fi,dword>>16); + png_write_byte(fi,dword>>8); + png_write_byte(fi,dword); +} +static void png_end_chunk(FILE*fi) +{ + U32 tmp = REVERSESWAP32((mycrc32^0xffffffff)); + fwrite(&tmp,4,1,fi); +} + + +/* extract a lossless image (png) out of a tag + This routine was originally meant to be a one-pager. I just + didn't know png is _that_ much fun. :) -mk + */ +void handlelossless(TAG*tag) +{ + char name[80]; + FILE*fi; + int width, height; + int crc; + int id; + int t; + U8 bpp = 1; + U8 format; + U8 tmp; + U8* data=0; + U8* data2=0; + U8* data3=0; + U32 datalen; + U32 datalen2; + U32 datalen3; + U8 head[] = {137,80,78,71,13,10,26,10}; + int cols; + char alpha = tag->id == ST_DEFINEBITSLOSSLESS2; + RGBA* palette; + int pos; + int error; + U32 tmp32; + + make_crc32_table(); + + if(tag->id != ST_DEFINEBITSLOSSLESS && + tag->id != ST_DEFINEBITSLOSSLESS2) + return; + + id =swf_GetU16(tag); + format = swf_GetU8(tag); + if(format == 3) bpp = 8; + if(format == 4) bpp = 16; + if(format == 5) bpp = 32; + if(format!=3 && format!=5) { + if(format==4) + fprintf(stderr, "Can't handle 16-bit palette images yet (image %d)\n",id); + else + fprintf(stderr, "Unknown image type %d in image %d\n", format, id); + return; + } + width = swf_GetU16(tag); + height = swf_GetU16(tag); + if(format == 3) cols = swf_GetU8(tag) + 1; +// this is what format means according to the flash specification. (which is +// clearly wrong) +// if(format == 4) cols = swf_GetU16(tag) + 1; +// if(format == 5) cols = swf_GetU32(tag) + 1; + else cols = 0; + + logf(" Width %d", width); + logf(" Height %d", height); + logf(" Format %d", format); + logf(" Cols %d", cols); + logf(" Bpp %d", bpp); + + datalen = (width*height*bpp/8+cols*8); + do { + if(data) + free(data); + datalen+=4096; + data = malloc(datalen); + error = uncompress (data, &datalen, &tag->data[tag->pos], tag->len-tag->pos); + } while(error == Z_BUF_ERROR); + if(error != Z_OK) { + fprintf(stderr, "Zlib error %d (image %d)\n", error, id); + return; + } + logf(" Uncompressed image is %d bytes (%d colormap)", datalen, (3+alpha)*cols); + pos = 0; + datalen2 = datalen; + data2 = malloc(datalen2); + palette = (RGBA*)malloc(cols*sizeof(RGBA)); + + for(t=0;t Compressed data is %d bytes", datalen2); + png_start_chunk(fi, "IDAT", datalen2); + png_write_bytes(fi,data2,datalen2); + png_end_chunk(fi); + png_start_chunk(fi, "IEND", 0); + png_end_chunk(fi); + + free(data); + free(data2); + free(data3); +} + int main (int argc,char ** argv) { TAG*tag; @@ -410,7 +646,7 @@ int main (int argc,char ** argv) char listavailable = 0; processargs(argc, argv); - if(!extractframes && !extractids && ! extractname && !extractjpegids) + if(!extractframes && !extractids && ! extractname && !extractjpegids && !extractpngids) listavailable = 1; if(!filename) @@ -496,6 +732,9 @@ int main (int argc,char ** argv) if(extractjpegids && is_in_range(id, extractjpegids)) { handlejpeg(tag); } + if(extractpngids && is_in_range(id, extractpngids)) { + handlelossless(tag); + } } else if (tag->id == ST_SETBACKGROUNDCOLOR) { mainr = tag->data[0]; -- 1.7.10.4