X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfextract.c;h=13294164f5ed03ac56cd20967ebefecc04f1c60b;hb=add03ee7161255cb8ff1da5dcd9fddd7d93b3026;hp=d7cbf100411673990c392eb82ba62869533779c0;hpb=60dea7f912ca4da6854676ce3c5f70089561423e;p=swftools.git diff --git a/src/swfextract.c b/src/swfextract.c index d7cbf10..1329416 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 @@ -273,7 +285,9 @@ void extractTag(SWF*swf, char*filename) 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) { @@ -340,21 +354,64 @@ void extractTag(SWF*swf, char*filename) } if(!extractframes && !hollow) { if(!originalplaceobjects && (extractids||extractname_id>=0)) { + int number = 0; + int id = 0; int t; - int s=0; - if((objectbbox.xmin|objectbbox.ymin|objectbbox.xmax|objectbbox.ymax)!=0) - newswf.movieSize = objectbbox; + TAG* objtag = 0; + SRECT bbox; + memset(&bbox, 0, sizeof(SRECT)); + for(t=0;t<65536;t++) { + if(is_in_range(t, extractids)) { + id = t; + number++; + } + } + if(number>=2) + printf("warning! You should use the -P when extracting multiple objects\n"); + + if(number == 1) { + /* if there is only one object, we will scale it. + So let's figure out it's bounding box */ + TAG*tag = swf->firstTag; + while(tag) { + if(swf_isDefiningTag(tag) && tag->id != ST_DEFINESPRITE) { + if(swf_GetDefineID(tag) == id) + bbox = swf_GetDefineBBox(tag); + objtag = tag; + } + tag = tag->next; + } + newswf.movieSize.xmin = 0; + newswf.movieSize.ymin = 0; + newswf.movieSize.xmax = 512*20; + newswf.movieSize.ymax = 512*20; + } else { + 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)) { + MATRIX m; 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"); + swf_GetMatrix(0, &m); + if(objtag) { + int width = bbox.xmax - bbox.xmin; + int height = bbox.ymax - bbox.ymin; + int max = width>height?width:height; + m.tx = -bbox.xmin; + m.ty = -bbox.ymin; + if(max) { + m.sx = (512*20*65536)/max; + m.sy = (512*20*65536)/max; + } + //newswf.movieSize = swf_TurnRect(newswf.movieSize, &m); + } + swf_ObjectPlace(desttag, t, t, &m,0,0); } } } @@ -370,80 +427,111 @@ void extractTag(SWF*swf, char*filename) swf_FreeTags(&newswf); // cleanup } +int isOfType(int t, TAG*tag) +{ + int show = 0; + if(t == 0 && (tag->id == ST_DEFINESHAPE || + tag->id == ST_DEFINESHAPE2 || + tag->id == ST_DEFINESHAPE3)) { + show = 1; + } + if(t==1 && tag->id == ST_DEFINESPRITE) { + show = 1; + } + if(t == 2 && (tag->id == ST_DEFINEBITS || + tag->id == ST_DEFINEBITSJPEG2 || + tag->id == ST_DEFINEBITSJPEG3)) { + show = 1; + } + if(t == 3 && (tag->id == ST_DEFINEBITSLOSSLESS || + tag->id == ST_DEFINEBITSLOSSLESS2)) { + show = 1; + } + if(t == 4 && (tag->id == ST_DEFINESOUND)) { + show = 1; + } + if(t == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2)) { + show = 1; + } + return show; +} + void listObjects(SWF*swf) { TAG*tag; char first; int t; int frame = 0; - char*names[] = {"Shapes","MovieClips","JPEGs","PNGs","Sounds","Fonts"}; + char*names[] = {"Shape", "MovieClip", "JPEG", "PNG", "Sound", "Font"}; + char*options[] = {"-i", "-i", "-j", "-p", "-s", "-F"}; + int mp3=0; printf("Objects in file %s:\n",filename); + swf_FoldAll(swf); for(t=0;tfirstTag; first = 1; while(tag) { - char show = 0; + if(tag->id == ST_SOUNDSTREAMHEAD || tag->id == ST_SOUNDSTREAMHEAD2) + mp3 = 1; + if(isOfType(t,tag)) + nr++; + tag = tag->next; + } + if(!nr) + continue; + + printf(" [%s] %d %s%s: ID(s) ", options[t], nr, names[t], nr>1?"s":""); + + tag = swf->firstTag; + while(tag) { 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)); + char show = isOfType(t,tag); + int id; + if(!show) { + tag = tag->next; + continue; } + id = swf_GetDefineID(tag); - if(tag->id == ST_DEFINESPRITE) { - if (t == 1) { - show = 1; - sprintf(text,"%d", swf_GetDefineID(tag)); + if(id == lastid+1) { + follow=1; + } else { + if(first || !follow) { + if(!first) + printf(", "); + printf("%d", id); + } else { + if(lastprint + 1 == lastid) + printf(", %d, %d", lastid, id); + else + printf("-%d, %d", lastid, id); } - - while(tag->id != ST_END) - tag = tag->next; - } - - if(t == 2 && (tag->id == ST_DEFINEBITS || - tag->id == ST_DEFINEBITSJPEG2 || - tag->id == ST_DEFINEBITSJPEG3)) { - show = 1; - sprintf(text,"%d", swf_GetDefineID(tag)); - } - - 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 == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2)) { - show = 1; - sprintf(text,"%d", swf_GetDefineID(tag)); - } - - if(show) { - if(!first) - printf(", "); - else - printf("%s: ", names[t]); - printf("%s", text); + lastprint = id; first = 0; + follow = 0; } + lastid = id; tag=tag->next; } - if(!first) - printf("\n"); + if(follow) { + if(lastprint + 1 == lastid) + printf(", %d", lastid); + else + printf("-%d", lastid); + } + printf("\n"); } if(frame) - printf("Frames: 0-%d\n", frame); + printf(" [-f] %d Frames: ID(s) 0-%d\n", frame, frame); else - printf("Frames: 0\n"); + printf(" [-f] 1 Frame: ID(s) 0\n"); + + if(mp3) + printf(" [-m] 1 MP3 Soundstream\n"); } void handlefont(SWF*swf, TAG*tag) @@ -524,7 +612,7 @@ void handlejpeg(TAG*tag) /* 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) { + if(tag->id == ST_DEFINEBITSJPEG && tag->len>2 && jpegtables) { 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) @@ -533,13 +621,17 @@ void handlejpeg(TAG*tag) else if(tag->id == ST_DEFINEBITSJPEG2 && tag->len>2) { int end = tag->len; int pos = findjpegboundary(&tag->data[2], tag->len-2); - if(pos<0) - return; - pos+=2; - 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); + if(pos>=0) { + pos+=2; + 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); + } else { + fi = save_fopen(filename, "wb"); + fwrite(&tag->data[2], end-2, 1, fi); + fclose(fi); + } } else if(tag->id == ST_DEFINEBITSJPEG3 && tag->len>6) { U32 end = GET32(&tag->data[2])+6; @@ -579,7 +671,7 @@ static void make_crc32_table(void) crc32_table[t] = c; } } -static void png_write_byte(FILE*fi, U8 byte) +static inline void png_write_byte(FILE*fi, U8 byte) { fwrite(&byte,1,1,fi); mycrc32 = crc32_table[(mycrc32 ^ byte) & 0xff] ^ (mycrc32 >> 8); @@ -676,11 +768,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 { @@ -694,7 +786,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); @@ -724,8 +816,10 @@ void handlelossless(TAG*tag) png_write_byte(fi,8); if(format == 3) png_write_byte(fi,3); //indexed - else if(format == 5) + else if(format == 5 && alpha==0) png_write_byte(fi,2); //rgb + else if(format == 5 && alpha==1) + png_write_byte(fi,6); //rgba else return; png_write_byte(fi,0); //compression mode @@ -735,29 +829,49 @@ void handlelossless(TAG*tag) if(format == 3) { png_start_chunk(fi, "PLTE", 768); + for(t=0;t<256;t++) { png_write_byte(fi,palette[t].r); png_write_byte(fi,palette[t].g); png_write_byte(fi,palette[t].b); } png_end_chunk(fi); + + if(alpha) { + /* write alpha palette */ + png_start_chunk(fi, "tRNS", 256); + for(t=0;t<256;t++) { + png_write_byte(fi,palette[t].a); + } + png_end_chunk(fi); + } } { int pos2 = 0; int x,y; int srcwidth = width * (bpp/8); - datalen3 = width*height*4; + datalen3 = (width*4+5)*height; data3 = (U8*)malloc(datalen3); for(y=0;y 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); @@ -800,18 +914,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) @@ -827,25 +941,42 @@ void handledefinesound(TAG*tag) char buf[128]; char*filename = buf; FILE*fi; + char*extension = 0; + int format; U16 id; + int rate,bits,stereo; + char*rates[] = {"5500","11025","22050","44100"}; id = swf_GetU16(tag); //id - sprintf(buf, "sound%d.mp3", id); + + flags = swf_GetU8(tag); + format = flags>>4; + rate = (flags>>2)&3; + bits = flags&2?16:8; + stereo = flags&1; + + samples = swf_GetU32(tag); + extension = "raw"; + + if(format == 2) { // mp3 + swf_GetU16(tag); //numsamples_seek + extension = "mp3"; + } else if(format == 0) { // raw + printf("Sound is RAW, format: %s samples/sec, %d bit, %s\n", rates[rate], bits, stereo?"stereo":"mono"); + // TODO: convert to WAV + extension = "raw"; + } else if(format == 1) { // adpcm + printf("Sound is ADPCM, format: %s samples/sec, %d bit, %s\n", rates[rate], bits, stereo?"stereo":"mono"); + extension = "adpcm"; + } + sprintf(buf, "sound%d.%s", id, extension); if(numextracts==1) { filename = destfilename; - if(!strcmp(filename,"output.swf")) - filename = "output.mp3"; - } - flags = swf_GetU8(tag); - if((flags>>4)!=2) { - printf("Sorry, can only extract MP3 sounds. Sound %d is ADPCM or RAW.\n", id); - /* not mp3 */ - return; + if(!strcmp(filename,"output.swf")) { + sprintf(buf, "output.%s", extension); + filename = buf; + } } - samples = swf_GetU32(tag); - - swf_GetU16(tag); //(only for mp3) numsamples_seek - fi = save_fopen(filename, "wb"); fwrite(&tag->data[tag->pos], tag->len - tag->pos, 1, fi); fclose(fi); @@ -874,7 +1005,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) {