X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=src%2Fswfextract.c;h=a5f549a8d54bd7a8836d630e460edaa4bd0cf20d;hp=28a45a349e814136ffbf767120be6a2c5e3f35de;hb=f7555c9f25b9008e1996e029f83ebeaaafd95321;hpb=9477c328f97ca1221fe8aac0daa3f49c59c1d1d5 diff --git a/src/swfextract.c b/src/swfextract.c index 28a45a3..a5f549a 100644 --- a/src/swfextract.c +++ b/src/swfextract.c @@ -4,8 +4,20 @@ Part of the swftools package. Copyright (c) 2001 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - This file is distributed under the GPL, see file COPYING for details */ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include @@ -27,6 +39,7 @@ int verbose = 3; char* extractids = 0; char* extractframes = 0; char* extractjpegids = 0; +char* extractfontids = 0; char* extractpngids = 0; char* extractsoundids = 0; char extractmp3 = 0; @@ -34,6 +47,7 @@ char extractmp3 = 0; char* extractname = 0; char hollow = 0; +char originalplaceobjects = 0; int numextracts = 0; @@ -45,10 +59,12 @@ struct options_t options[] = {"i","id"}, {"j","jpegs"}, {"p","pngs"}, + {"P","placeobject"}, {"m","mp3"}, {"s","sound"}, {"n","name"}, {"f","frame"}, + {"F","font"}, {"V","version"}, {0,0} }; @@ -100,6 +116,15 @@ int args_callback_option(char*name,char*val) extractjpegids = val; return 1; } + else if(!strcmp(name, "F")) { + if(extractfontids) { + fprintf(stderr, "Only one --font argument is allowed. (Try to use a range, e.g. -s 1,2,3)\n"); + exit(1); + } + numextracts++; + extractfontids = val; + return 1; + } else if(!strcmp(name, "s")) { if(extractsoundids) { fprintf(stderr, "Only one --sound argument is allowed. (Try to use a range, e.g. -s 1,2,3)\n"); @@ -112,7 +137,7 @@ int args_callback_option(char*name,char*val) #ifdef _ZLIB_INCLUDED_ 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"); + fprintf(stderr, "Only one --png argument is allowed. (Try to use a range, e.g. -p 1,2,3)\n"); exit(1); } numextracts++; @@ -125,13 +150,17 @@ int args_callback_option(char*name,char*val) extractframes = val; return 1; } + else if(!strcmp(name, "P")) { + originalplaceobjects = 1; + return 0; + } else if(!strcmp(name, "w")) { hollow = 1; return 0; } else { printf("Unknown option: -%s\n", name); - return 0; + exit(1); } return 0; @@ -148,10 +177,14 @@ void args_callback_usage(char*name) printf("\t-V , --version\t\t\t Print program version and exit\n\n"); printf("SWF Subelement extraction:\n"); printf("\t-n , --name name\t\t instance name of the object (SWF Define) to extract\n"); - printf("\t-i , --id ID\t\t\t ID of the object (SWF Define) to extract\n"); + printf("\t-i , --id ID\t\t\t ID of the object, shape or movieclip 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\n"); printf("\t \t\t\t (use with -f)\n"); + printf("\t-P , --placeobject\t\t\t Insert original placeobject into output file\n"); + printf("\t \t\t\t (use with -i)\n"); + printf("SWF Font/Text extraction:\n"); + printf("\t-F , --font ID\t\t\t Extract font(s)\n"); printf("Picture extraction:\n"); printf("\t-j , --jpeg ID\t\t\t Extract JPEG picture(s)\n"); #ifdef _ZLIB_INCLUDED_ @@ -182,6 +215,7 @@ char used[65536]; TAG*tags[65536]; int changed; char * tagused; +int extractname_id = -1; void idcallback(void*data) { @@ -226,6 +260,7 @@ void extractTag(SWF*swf, char*filename) TAG*desttag; TAG*srctag; RGBA rgb; + SRECT objectbbox; char sprite; int f; int t; @@ -244,11 +279,15 @@ void extractTag(SWF*swf, char*filename) rgb.b = mainb; swf_SetRGB(desttag,&rgb); + swf_GetRect(0, &objectbbox); + do { changed = 0; for(t=0;t<65536;t++) { if(used[t] && !(used[t]&2)) { - if(tags[t]->id==ST_DEFINESPRITE) { + if(tags[t]==0) { + msg(" ID %d is referenced, but never defined.", t); + } else if(tags[t]->id==ST_DEFINESPRITE) { TAG*tag = tags[t]; while(tag->id != ST_END) { @@ -279,12 +318,15 @@ void extractTag(SWF*swf, char*filename) sprite = 1; if(swf_isDefiningTag(srctag)) { int id = swf_GetDefineID(srctag); - if(used[id]) + if(used[id]) { + SRECT b; copy = 1; + b = swf_GetDefineBBox(srctag); + swf_ExpandRect2(&objectbbox, &b); + } } else - if (((srctag->id == ST_PLACEOBJECT || - srctag->id == ST_PLACEOBJECT2 || - srctag->id == ST_STARTSOUND) && (used[swf_GetPlaceID(srctag)]&4) ) || + if (((((srctag->id == ST_PLACEOBJECT || srctag->id == ST_PLACEOBJECT2) && originalplaceobjects) + || srctag->id == ST_STARTSOUND) && (used[swf_GetPlaceID(srctag)]&4) ) || (swf_isPseudoDefiningTag(srctag) && used[swf_GetDefineID(srctag)]) || (tagused[tagnum])) { @@ -310,12 +352,32 @@ void extractTag(SWF*swf, char*filename) srctag = srctag->next; tagnum ++; } - if(!extractframes && !hollow) + if(!extractframes && !hollow) { + if(!originalplaceobjects && (extractids||extractname_id>=0)) { + int t; + int s=0; + if((objectbbox.xmin|objectbbox.ymin|objectbbox.xmax|objectbbox.ymax)!=0) + newswf.movieSize = objectbbox; + if(extractname_id>=0) { + desttag = swf_InsertTag(desttag, ST_PLACEOBJECT2); + swf_ObjectPlace(desttag, extractname_id, extractname_id, 0,0,extractname); + } else { + for(t=0;t<65536;t++) { + if(is_in_range(t, extractids)) { + desttag = swf_InsertTag(desttag, ST_PLACEOBJECT2); + swf_ObjectPlace(desttag, t, t, 0,0,0); + s++; + if(s==2) + printf("warning! You should use the -P when extracting multiple objects\n"); + } + } + } + } desttag = swf_InsertTag(desttag,ST_SHOWFRAME); - + } desttag = swf_InsertTag(desttag,ST_END); - f = open(filename, O_TRUNC|O_WRONLY|O_CREAT, 0644); + f = open(filename, O_TRUNC|O_WRONLY|O_CREAT|O_BINARY, 0644); if FAILED(swf_WriteSWF(f,&newswf)) fprintf(stderr,"WriteSWF() failed.\n"); close(f); @@ -328,9 +390,9 @@ void listObjects(SWF*swf) char first; int t; int frame = 0; - char*names[] = {"Shapes","MovieClips","JPEGs","PNGs","Sounds","Frames"}; + char*names[] = {"Shapes","MovieClips","JPEGs","PNGs","Sounds","Fonts"}; printf("Objects in file %s:\n",filename); - for(t=0;t<6;t++) { + for(t=0;tfirstTag; first = 1; while(tag) { @@ -373,12 +435,11 @@ void listObjects(SWF*swf) sprintf(text,"%d", swf_GetDefineID(tag)); } - if(t == 5 && (tag->id == ST_SHOWFRAME)) { + if(t == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2)) { show = 1; - sprintf(text,"%d", frame); - frame ++; + sprintf(text,"%d", swf_GetDefineID(tag)); } - + if(show) { if(!first) printf(", "); @@ -392,6 +453,37 @@ void listObjects(SWF*swf) if(!first) printf("\n"); } + + if(frame) + printf("Frames: 0-%d\n", frame); + else + printf("Frames: 0\n"); +} + +void handlefont(SWF*swf, TAG*tag) +{ + SWFFONT* f=0; + U16 id; + char name[80]; + char*filename = name; + int t; + + id = swf_GetDefineID(tag); + sprintf(name, "font%d.swf", id); + if(numextracts==1) { + filename = destfilename; + } + + swf_FontExtract(swf, id, &f); + if(!f) { + printf("Couldn't extract font %d\n", id); + return; + } + if(!f->layout) + swf_FontCreateLayout(f); + + swf_WriteFont(f, filename); + swf_FontFree(f); } U8*jpegtables = 0; @@ -434,13 +526,20 @@ int findjpegboundary(U8*data, int len) void handlejpeg(TAG*tag) { char name[80]; + char*filename = name; FILE*fi; - sprintf(name, "pic%d.jpeg", GET16(tag->data)); + + sprintf(name, "pic%d.jpg", GET16(tag->data)); + if(numextracts==1) { + filename = destfilename; + if(!strcmp(filename,"output.swf")) + filename = "output.jpg"; + } /* swf jpeg images have two streams, which both start with ff d8 and end with ff d9. The following code handles sorting the middle bytes out, so that one stream remains */ if(tag->id == ST_DEFINEBITS && tag->len>2 && jpegtables) { - fi = save_fopen(name, "wb"); + fi = save_fopen(filename, "wb"); fwrite(jpegtables, 1, jpegtablessize-2, fi); //don't write end tag (ff,d8) fwrite(&tag->data[2+2], tag->len-2-2, 1, fi); //don't write start tag (ff,d9) fclose(fi); @@ -451,7 +550,7 @@ void handlejpeg(TAG*tag) if(pos<0) return; pos+=2; - fi = save_fopen(name, "wb"); + fi = save_fopen(filename, "wb"); fwrite(&tag->data[2], pos-2, 1, fi); fwrite(&tag->data[pos+4], end-(pos+4), 1, fi); fclose(fi); @@ -462,7 +561,7 @@ void handlejpeg(TAG*tag) if(pos<0) return; pos+=6; - fi = save_fopen(name, "wb"); + fi = save_fopen(filename, "wb"); fwrite(&tag->data[6], pos-6, 1, fi); fwrite(&tag->data[pos+4], end-(pos+4), 1, fi); fclose(fi); @@ -538,6 +637,7 @@ static void png_end_chunk(FILE*fi) void handlelossless(TAG*tag) { char name[80]; + char*filename = name; FILE*fi; int width, height; int crc; @@ -590,11 +690,11 @@ void handlelossless(TAG*tag) // 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); + msg(" Width %d", width); + msg(" Height %d", height); + msg(" Format %d", format); + msg(" Cols %d", cols); + msg(" Bpp %d", bpp); datalen = (width*height*bpp/8+cols*8); do { @@ -608,7 +708,7 @@ void handlelossless(TAG*tag) fprintf(stderr, "Zlib error %d (image %d)\n", error, id); return; } - logf(" Uncompressed image is %d bytes (%d colormap)", datalen, (3+alpha)*cols); + msg(" Uncompressed image is %d bytes (%d colormap)", datalen, (3+alpha)*cols); pos = 0; datalen2 = datalen; data2 = malloc(datalen2); @@ -624,7 +724,12 @@ void handlelossless(TAG*tag) } sprintf(name, "pic%d.png", id); - fi = save_fopen(name, "wb"); + if(numextracts==1) { + filename = destfilename; + if(!strcmp(filename,"output.swf")) + filename = "output.png"; + } + fi = save_fopen(filename, "wb"); fwrite(head,sizeof(head),1,fi); png_start_chunk(fi, "IHDR", 13); @@ -683,7 +788,7 @@ void handlelossless(TAG*tag) fprintf(stderr, "zlib error in pic %d\n", id); return; } - logf(" Compressed data is %d bytes", datalen2); + msg(" Compressed data is %d bytes", datalen2); png_start_chunk(fi, "IDAT", datalen2); png_write_bytes(fi,data2,datalen2); png_end_chunk(fi); @@ -709,18 +814,18 @@ void handlesoundstream(TAG*tag) case ST_SOUNDSTREAMHEAD: if((tag->data[1]&0x30) == 0x20) { //mp3 compression mp3file = fopen(filename, "wb"); - logf(" Writing mp3 data to %s",filename); + msg(" Writing mp3 data to %s",filename); } else - logf(" Soundstream is not mp3"); + msg(" Soundstream is not mp3"); break; case ST_SOUNDSTREAMHEAD2: if((tag->data[1]&0x30) == 0x20) {//mp3 compression mp3file = fopen(filename, "wb"); - logf(" Writing mp3 data to %s",filename); + msg(" Writing mp3 data to %s",filename); } else - logf(" Soundstream is not mp3 (2)"); + msg(" Soundstream is not mp3 (2)"); break; case ST_SOUNDSTREAMBLOCK: if(mp3file) @@ -773,7 +878,7 @@ int main (int argc,char ** argv) processargs(argc, argv); if(!extractframes && !extractids && ! extractname && !extractjpegids && !extractpngids - && !extractmp3 && !extractsoundids) + && !extractmp3 && !extractsoundids && !extractfontids) listavailable = 1; if(!filename) @@ -783,7 +888,7 @@ int main (int argc,char ** argv) } initLog(0,-1,0,0,-1, verbose); - f = open(filename,O_RDONLY); + f = open(filename,O_RDONLY|O_BINARY); if (f<0) { @@ -863,6 +968,9 @@ int main (int argc,char ** argv) used[id] = 5; found = 1; } + if(extractfontids && is_in_range(id, extractfontids)) { + handlefont(&swf, tag); + } if(extractjpegids && is_in_range(id, extractjpegids)) { handlejpeg(tag); } @@ -888,6 +996,7 @@ int main (int argc,char ** argv) found = 1; tagused[tagnum] = 1; depths[swf_GetDepth(tag)] = 1; + extractname_id = id; } } else if(tag->id == ST_SHOWFRAME) {