From: kramm Date: Sun, 2 Dec 2001 11:49:53 +0000 (+0000) Subject: * Added support for extracting frames and multiple ids. X-Git-Tag: release-0-2-1~73 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=03a812845a29458fc8d55c2f172b1677b23a0734 * Added support for extracting frames and multiple ids. * Added -w (--hollow) option. * Show list of ids if no option given. --- diff --git a/src/swfextract.c b/src/swfextract.c index d0b0c6c..005f166 100644 --- a/src/swfextract.c +++ b/src/swfextract.c @@ -17,15 +17,22 @@ char * filename = 0; char * destfilename = "output.swf"; int verbose = 2; -int extractid = -1; + +char* extractids = 0; +char* extractframes = 0; + char* extractname = 0; +char hollow = 0; + struct options_t options[] = { {"o","output"}, + {"w","hollow"}, {"v","verbose"}, {"i","id"}, {"n","name"}, + {"f","frame"}, {"V","version"}, {0,0} }; @@ -36,30 +43,38 @@ int args_callback_option(char*name,char*val) printf("swfextract - part of %s %s\n", PACKAGE, VERSION); exit(0); } - if(!strcmp(name, "o")) { + else if(!strcmp(name, "o")) { destfilename = val; return 1; } - if(!strcmp(name, "i")) { - extractid = atoi(val); + else if(!strcmp(name, "i")) { + extractids = val; if(extractname) { fprintf(stderr, "You can only supply either name or id\n"); exit(1); } return 1; } - if(!strcmp(name, "n")) { + else if(!strcmp(name, "n")) { extractname = val; - if(extractid>=0) { + if(extractids) { fprintf(stderr, "You can only supply either name or id\n"); exit(1); } return 1; } - if(!strcmp(name, "v")) { + else if(!strcmp(name, "v")) { verbose ++; return 0; } + else if(!strcmp(name, "f")) { + extractframes = val; + return 1; + } + else if(!strcmp(name, "w")) { + hollow = 1; + return 0; + } else { printf("Unknown option: -%s\n", name); return 0; @@ -75,8 +90,11 @@ void args_callback_usage(char*name) { printf("Usage: %s [-v] [-i id] file.swf\n", name); printf("\t-v , --verbose\t\t\t Be more verbose\n"); + printf("\t-o , --output filename\t\t set output filename\n"); printf("\t-i , --id ID\t\t\t ID of the object to extract\n"); - printf("\t-n , --name name\t\t\t instance name of the object to extract\n"); + printf("\t-n , --name name\t\t instance name of the object to extract\n"); + printf("\t-f , --frame frame\t\t frame number to extract\n"); + printf("\t-w , --hollow\t\t\t hollow mode: don't remove empty frames\n"); printf("\t-V , --version\t\t\t Print program version and exit\n"); } int args_callback_command(char*name,char*val) @@ -90,15 +108,21 @@ int args_callback_command(char*name,char*val) } U8 mainr,maing,mainb; +/* 1 = used, not expanded, + 3 = used, expanded + 5 = wanted, not expanded + 7 = wanted, expanded + */ char used[65536]; TAG*tags[65536]; int changed; +char * tagused; void idcallback(void*data) { - if(!used[*(U16*)data]) { + if(!(used[*(U16*)data]&1)) { changed = 1; - used[*(U16*)data] = 1; + used[*(U16*)data] |= 1; } } @@ -121,7 +145,7 @@ void enumerateIDs(TAG*tag, void(*callback)(void*)) map_ids_mem(data, len, callback); } -void extractTag(SWF*swf, int defineid, char*filename) +void extractTag(SWF*swf, char*filename) { SWF newswf; TAG*desttag; @@ -130,9 +154,9 @@ void extractTag(SWF*swf, int defineid, char*filename) char sprite; int f; int t; + int tagnum; int copy = 0; memset(&newswf,0x00,sizeof(SWF)); // set global movie parameters - memset(used, 0,65536); newswf.fileVersion = swf->fileVersion; newswf.frameRate = swf->frameRate; @@ -145,11 +169,10 @@ void extractTag(SWF*swf, int defineid, char*filename) rgb.b = mainb; swf_SetRGB(desttag,&rgb); - used[defineid] = 1; do { changed = 0; for(t=0;t<65536;t++) { - if(used[t]==1) { + if(used[t] && !(used[t]&2)) { if(tags[t]->id==ST_DEFINESPRITE) { TAG*tag = tags[t]; while(tag->id != ST_END) @@ -158,15 +181,17 @@ void extractTag(SWF*swf, int defineid, char*filename) tag = tag->next; } } - else - enumerateIDs(tags[t], idcallback); - used[t] = 2; + else + enumerateIDs(tags[t], idcallback); + used[t] |= 2; } } } while(changed); srctag = swf->firstTag; + tagnum = 0; + sprite = 0; while(srctag && (srctag->id || sprite)) { int reset = 0; if(!sprite) { @@ -183,13 +208,19 @@ void extractTag(SWF*swf, int defineid, char*filename) copy = 1; } else if (((srctag->id == ST_PLACEOBJECT || - srctag->id == ST_PLACEOBJECT2) && swf_GetPlaceID(srctag) == defineid) || - (swf_isPseudoDefiningTag(srctag) && used[swf_GetDefineID(srctag)])) + srctag->id == ST_PLACEOBJECT2 || + srctag->id == ST_STARTSOUND) && (used[swf_GetPlaceID(srctag)]&4) ) || + (swf_isPseudoDefiningTag(srctag) && used[swf_GetDefineID(srctag)]) || + (tagused[tagnum])) { if(copy == 0) reset = 1; copy = 1; } + if(srctag->id == ST_REMOVEOBJECT) { + if(!used[swf_GetPlaceID(srctag)]) + copy = 0; + } if(copy) { TAG*ttag = (TAG*)malloc(sizeof(TAG)); @@ -202,8 +233,11 @@ void extractTag(SWF*swf, int defineid, char*filename) } srctag = srctag->next; + tagnum ++; } - desttag = swf_InsertTag(desttag,ST_SHOWFRAME); + if(!extractframes && !hollow) + desttag = swf_InsertTag(desttag,ST_SHOWFRAME); + desttag = swf_InsertTag(desttag,ST_END); f = open(filename, O_TRUNC|O_WRONLY|O_CREAT, 0644); @@ -213,13 +247,87 @@ void extractTag(SWF*swf, int defineid, char*filename) swf_FreeTags(&newswf); // cleanup } +void listObjects(SWF*swf) +{ + TAG*tag; + char first; + int t; + int frame = 0; + char*names[] = {"Shapes","MovieClips","Bitmaps","Sounds","Frames"}; + printf("Objects in file %s:\n",filename); + for(t=0;t<5;t++) { + tag = swf->firstTag; + first = 1; + while(tag) { + char show = 0; + char text[80]; + if(t == 0 && + (tag->id == ST_DEFINESHAPE || + tag->id == ST_DEFINESHAPE2 || + tag->id == ST_DEFINESHAPE3)) { + show = 1; + sprintf(text,"%d", swf_GetDefineID(tag)); + } + + if(tag->id == ST_DEFINESPRITE) { + if (t == 1) { + show = 1; + sprintf(text,"%d", swf_GetDefineID(tag)); + } + + while(tag->id != ST_END) + tag = tag->next; + } + + if(t == 2 && (tag->id == ST_DEFINEBITSLOSSLESS || + tag->id == ST_DEFINEBITSJPEG2 || + tag->id == ST_DEFINEBITSLOSSLESS2 || + tag->id == ST_DEFINEBITSJPEG3)) { + show = 1; + sprintf(text,"%d", swf_GetDefineID(tag)); + } + + if(t == 3 && (tag->id == ST_DEFINESOUND)) { + show = 1; + sprintf(text,"%d", swf_GetDefineID(tag)); + } + + if(t == 4 && (tag->id == ST_SHOWFRAME)) { + show = 1; + sprintf(text,"%d", frame); + frame ++; + } + + if(show) { + if(!first) + printf(", "); + else + printf("%s: ", names[t]); + printf("%s", text); + first = 0; + } + tag=tag->next; + } + if(!first) + printf("\n"); + } +} + int main (int argc,char ** argv) { TAG*tag; SWF swf; int f; + int found = 0; + int frame = 0; + int tagnum = 0; + char depths[65536]; + char listavailable = 0; processargs(argc, argv); + if(!extractframes && !extractids && ! extractname) + listavailable = 1; + if(!filename) { fprintf(stderr, "You must supply a filename.\n"); @@ -234,19 +342,69 @@ int main (int argc,char ** argv) perror("Couldn't open file: "); exit(1); } - if FAILED(swf_ReadSWF(f,&swf)) + if (swf_ReadSWF(f,&swf) < 0) { fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename); close(f); exit(1); } + close(f); + + if(listavailable) { + listObjects(&swf); + swf_FreeTags(&swf); + return 0; + } tag = swf.firstTag; + tagnum = 0; + while(tag) { + tagnum ++; + tag = tag->next; + } + tagused = (char*)malloc(tagnum); + memset(tagused, 0, tagnum); + memset(used, 0, 65536); + memset(depths, 0, 65536); + + tag = swf.firstTag; + tagnum = 0; while(tag) { + if(swf_isAllowedSpriteTag(tag)) { + int write = 0; + if(extractframes && is_in_range(frame, extractframes)) { + write = 1; + if(tag->id == ST_PLACEOBJECT || tag->id == ST_PLACEOBJECT2) { + depths[swf_GetDepth(tag)] = 1; + } + if(tag->id == ST_REMOVEOBJECT || tag->id == ST_REMOVEOBJECT2) { + int depth = swf_GetDepth(tag); + if(!depths[depth]) + write = 0; + depths[swf_GetDepth(tag)] = 0; + } + } else { + if((tag->id == ST_REMOVEOBJECT || tag->id == ST_REMOVEOBJECT2) && + (depths[swf_GetDepth(tag)]) && hollow) { + write = 1; + depths[swf_GetDepth(tag)] = 0; + } + } + if(write) { + enumerateIDs(tag, idcallback); + found = 1; + tagused[tagnum] = 1; + } + } + if(swf_isDefiningTag(tag)) { int id = swf_GetDefineID(tag); tags[id] = tag; + if(extractids && is_in_range(id, extractids)) { + used[id] = 5; + found = 1; + } } else if (tag->id == ST_SETBACKGROUNDCOLOR) { mainr = tag->data[0]; @@ -257,17 +415,31 @@ int main (int argc,char ** argv) char*name = swf_GetName(tag); if(name && extractname && !strcmp(name, extractname)) { int id = swf_GetPlaceID(tag); - if(extractid>=0 && id != extractid) { - fprintf(stderr, "Error: More than one instance with name \"%s\"", name); - exit(1); - } - extractid = swf_GetPlaceID(tag); + used[id] = 5; + found = 1; + tagused[tagnum] = 1; + depths[swf_GetDepth(tag)] = 1; + } + } + else if(tag->id == ST_SHOWFRAME) { + frame ++; + if(hollow) { + tagused[tagnum] = 1; + found = 1; + } + } + + if(tag->id == ST_DEFINESPRITE) { + while(tag->id != ST_END) { + tag = tag->next; + tagnum ++; } } tag = tag->next; + tagnum ++; } - if(tags[extractid]) - extractTag(&swf, extractid, destfilename); + if (found) + extractTag(&swf, destfilename); swf_FreeTags(&swf); return 0;