2 Various routines for reading and writing swf files and tags.
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This file is distributed under the GPL, see file COPYING for details */
13 void swf_init(struct reader_t*r, uchar*newdata, int newlength)
15 reader_init (r, &newdata[3], newlength - 3);
18 struct flash_header swf_read_header(struct reader_t*r)
20 struct flash_header head;
25 u8* oldpos = reader_getinputpos(r);
27 reader_input1(r,&version);
28 head.version = version;
29 reader_input4(r,&length);
33 head.boundingBox = readRECT(r);
34 reader_input2(r,&rate);
36 reader_input2(r,&count);
39 head.headerlength = reader_getinputpos(r) - oldpos;
40 head.headerdata = oldpos;
45 void swf_write_header(struct writer_t*w, struct flash_header*head)
47 writer_writeu8(w, head->version);
48 writer_writeu32(w, head->length);
50 writer_writebits(w, 31, 5);
51 writer_writebits(w, head->boundingBox.x1, 31);
52 writer_writebits(w, head->boundingBox.x2, 31);
53 writer_writebits(w, head->boundingBox.y1, 31);
54 writer_writebits(w, head->boundingBox.y2, 31);
56 writer_writeu16(w, head->rate);
57 writer_writeu16(w, head->count);
60 struct RGB readRGB(struct reader_t*r)
63 reader_input1(r,&rgb.r);
64 reader_input1(r,&rgb.g);
65 reader_input1(r,&rgb.b);
69 struct RGBA readRGBA(struct reader_t*r)
72 reader_input1(r,&rgba.r);
73 reader_input1(r,&rgba.g);
74 reader_input1(r,&rgba.b);
75 reader_input1(r,&rgba.a);
79 struct GRADIENT readGRADIENT(struct reader_t*r, int shape)
81 struct GRADIENT gradient;
83 gradient.num = reader_readu8(r);
84 for(t=0;t<gradient.num;t++)
86 gradient.ratios[t] = reader_readu8(r);
88 gradient.rgb[t] = readRGB(r);
90 gradient.rgba[t] = readRGBA(r);
94 struct RECT readRECT(struct reader_t*reader)
99 reader_readbits(reader,&a,5);
100 reader_readsbits(reader,&b,a);
102 reader_readsbits(reader,&b,a);
104 reader_readsbits(reader,&b,a);
106 reader_readsbits(reader,&b,a);
112 void writeRECT(u8**pos, struct RECT*r)
116 writer_init(&w, *pos, 256);
117 writer_writebits(&w, 31, 5); //FIXME:count
118 writer_writebits(&w, r->x1, 31);
119 writer_writebits(&w, r->x2, 31);
120 writer_writebits(&w, r->y1, 31);
121 writer_writebits(&w, r->y2, 31);
122 writer_resetbits(&w);
123 *pos = writer_getpos(&w);
126 struct CXFORM readCXFORM(struct reader_t*r, char alpha)
130 c.hasadd=reader_readbit(r);
131 c.hasmult=reader_readbit(r);
132 bits=reader_getbits(r,4);
137 c.rmult=reader_getsbits(r,bits)/65536.0;
138 c.gmult=reader_getsbits(r,bits)/65536.0;
139 c.bmult=reader_getsbits(r,bits)/65536.0;
141 c.amult=reader_getsbits(r,bits)/65536.0;
145 c.radd=reader_getsbits(r,bits)/65536.0;
146 c.gadd=reader_getsbits(r,bits)/65536.0;
147 c.badd=reader_getsbits(r,bits)/65536.0;
149 c.aadd=reader_getsbits(r,bits)/65536.0;
154 void CXFORM_write(struct CXFORM *obj, struct writer_t*w)
157 writer_writebit(w,obj->hasadd);
158 writer_writebit(w,obj->hasmult);
159 writer_writebits(w, bits, 4);
162 writer_writebits(w, obj->rmult, bits);
163 writer_writebits(w, obj->gmult, bits);
164 writer_writebits(w, obj->bmult, bits);
166 writer_writebits(w, obj->amult, 4);
170 writer_writebits(w, obj->radd, bits);
171 writer_writebits(w, obj->gadd, bits);
172 writer_writebits(w, obj->badd, bits);
174 writer_writebits(w, obj->aadd, 4);
178 unsigned char* readSTRING(struct reader_t*r)
180 unsigned char*now = reader_getinputpos(r);
189 void MATRIX_init(struct MATRIX*m)
200 struct MATRIX readMATRIX(struct reader_t*r)
208 m.a[0][0] = m.a[1][1] = 1;
209 m.a[0][1] = m.a[1][0] = 0;
210 m.hasscale=reader_readbit(r);
213 u8 scalebits=reader_getbits(r,5);
214 s32 scalex=reader_getsbits(r,scalebits);
215 s32 scaley=reader_getsbits(r,scalebits);
216 m.a[0][0]=scalex/65536.0;
217 m.a[1][1]=scaley/65536.0;
219 m.hasrotate=reader_readbit(r);
222 u8 rotbits=reader_getbits(r,5);
223 s32 rotateskew0=reader_getsbits(r,rotbits);
224 s32 rotateskew1=reader_getsbits(r,rotbits);
225 m.a[0][1]=rotateskew0/65536.0;
226 m.a[1][0]=rotateskew1/65536.0;
229 translatebits=reader_getbits(r,5);
230 translatex=reader_getsbits(r,translatebits);
231 translatey=reader_getsbits(r,translatebits);
238 void MATRIX_write(struct MATRIX * m , struct writer_t*w)
240 writer_writebit (w, m->hasscale);
244 writer_writebits(w, bits, 5);
245 writer_writebits(w, (u32)(m->a[0][0]*65536.0), bits);
246 writer_writebits(w, (u32)(m->a[1][1]*65536.0), bits);
248 writer_writebit (w, m->hasrotate);
252 writer_writebits(w, bits, 5);
253 writer_writebits(w, (u32)(m->a[0][1]*65536.0), bits);
254 writer_writebits(w, (u32)(m->a[1][0]*65536.0), bits);
260 writer_writebits(w, bits, 5);
261 writer_writebits(w, (u32)(m->b[0]), bits);
262 writer_writebits(w, (u32)(m->b[1]), bits);
267 int swf_read_tag(struct reader_t*r, struct swf_tag* swftag)
269 u8*pos2,*pos = reader_getinputpos(r);
275 reader_input2(r, &tag);
277 taglength = tag & 0x3f;
278 if (taglength == 0x3f)
280 reader_input4(r, &taglength);
284 swftag->length = taglength;
285 swftag->data = reader_getinputpos(r);
286 reader_skip(r,taglength);
287 pos2 = reader_getinputpos(r);
288 swftag->fulllength = pos2 - pos;
289 swftag->fulldata = pos;
293 int swf_count_tags(struct reader_t*r)
295 u8*pos = reader_getinputpos(r);
301 swf_read_tag(r,&tag);
307 reader_setinputpos(r,pos);
311 void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag)
314 reader_init (&r, tag->data, tag->length);
315 obj -> id = reader_readu16(&r);
316 obj -> depth = reader_readu16(&r);
317 obj -> matrix = readMATRIX(&r);
318 obj -> hascxform = (reader_getinputpos(&r) < &tag->data[tag->length]);
320 obj -> cxform = readCXFORM(&r, 0);
323 void placeobject_write (struct PlaceObject*obj, struct writer_t*w)
325 u16 taghead = 0x3f | TAGID_PLACEOBJECT<<6;
329 writer_write(w, &taghead, 2);
330 lenpos = writer_getpos(w);
332 writer_write(w, &taghead, 2);
333 writer_write(w, &taghead, 2);
335 pos = writer_getpos(w);
337 writer_write(w, &obj->id, 2);
338 writer_write(w, &obj->depth, 2);
339 MATRIX_write(&obj->matrix, w);
343 CXFORM_write(&obj->cxform, w);
347 *(u32*)lenpos = SWAP32((u8*)writer_getpos(w) - pos);
350 void placeobject2_init (struct PlaceObject2*obj,struct swf_tag*tag)
354 reader_init (&r, tag->data, tag->length);
356 obj->reserved= (b>>7)&1;
357 obj->hasclipactions= (b>>6)&1;
358 obj->hasname= (b>>5)&1;
359 obj->hasratio= (b>>4)&1;
360 obj->hascolortransform=(b>>3)&1;
361 obj->hasmatrix= (b>>2)&1;
362 obj->hascharacter= (b>>1)&1;
363 obj->hasmove= (b>>0)&1;
365 obj->depth = reader_readu16(&r);
367 if(obj->hascharacter) {
368 obj->id = reader_readu16(&r);
371 obj->matrix = readMATRIX(&r);
373 if(obj->hascolortransform) {
374 obj->cxform = readCXFORM(&r,0);
377 obj->ratio=reader_readu16(&r);
381 obj->name=readSTRING(&r);
383 if(obj->hasclipactions) {
384 obj->clipactions=reader_readu16(&r);
388 void placeobject2_write (struct PlaceObject2*obj, struct writer_t*w)
390 u8 flags = obj->reserved<<7 | obj->hasclipactions<<6 | obj->hasname<<5 | obj->hasratio<<4 |
391 obj->hascolortransform<<3 | obj->hasmatrix<<2 | obj->hascharacter<<1 | obj->hasmove;
392 u16 taghead = SWAP16(0x3f | TAGID_PLACEOBJECT2<<6);
396 writer_write(w, &taghead, 2);
397 lenpos = writer_getpos(w);
398 writer_write(w, &taghead, 2);
399 writer_write(w, &taghead, 2);
401 pos = writer_getpos(w);
403 writer_writeu8(w, flags);
404 writer_writeu16(w, obj->depth);
405 if(obj->hascharacter)
406 writer_writeu16(w, obj->id);
408 MATRIX_write(&obj->matrix, w);
409 if(obj->hascolortransform)
410 CXFORM_write(&obj->cxform, w);
412 writer_writeu16(w, obj->ratio);
415 writer_write(w, obj->name, strlen(obj->name) + 1);
416 if(obj->hasclipactions)
417 writer_writeu16(w, obj->clipactions);
419 *(u32*)lenpos = SWAP32((u8*)writer_getpos(w) - pos);
422 void read_swf(struct swffile*swf, uchar*data, int length)
425 struct flash_header head;
428 swf_init(&r, data, length);
429 head = swf_read_header(&r);
430 logf("<debug> [HEADER] the version is %d", head.version);
431 logf("<debug> [HEADER] the length is %d", head.length);
432 logf("<debug> [HEADER] the boundingBox is %d:%d:%d:%d",
433 head.boundingBox.x1,head.boundingBox.y1,
434 head.boundingBox.x2,head.boundingBox.y2);
435 logf("<debug> [HEADER] the rate (frames/second) is %d", head.rate);
436 logf("<debug> [HEADER] the count (frame number) is %d", head.count);
438 tagnum = swf_count_tags(&r);
439 swf->tags = (struct swf_tag*)malloc(sizeof(struct swf_tag)*tagnum);
441 logf("<debug> [HEADER] the file consists of %d tags", tagnum);
447 swf_read_tag(&r, &tag);
448 logf("<debug> read tag %02x (%d bytes)", tag.id, tag.length);
449 swf->tags[pos] = tag;
451 if(tag.id == TAGID_END)
454 swf->tagnum = tagnum;
458 int definingtagids[] =
462 TAGID_DEFINEMORPHSHAPE,
467 TAGID_DEFINEEDITTEXT,
469 TAGID_DEFINEBITSJPEG2,
470 TAGID_DEFINEBITSJPEG3,
471 TAGID_DEFINEBITSLOSSLESS,
472 TAGID_DEFINEBITSLOSSLESS2,
481 // tags which may be used inside a sprite definition
487 TAGID_REMOVEOBJECT2, //?
491 TAGID_SOUNDSTREAMHEAD,
492 TAGID_SOUNDSTREAMHEAD2,
493 TAGID_SOUNDSTREAMBLOCK,
498 int getidfromtag(struct swf_tag* tag)
502 case TAGID_PLACEOBJECT2:
504 case TAGID_PLACEOBJECT: {
506 reader_init (&r, tag->data, tag->length);
508 char b = reader_readu8(&r);
513 return reader_readu16(&r);
516 case TAGID_REMOVEOBJECT:
517 return *(u16*)tag->data;
519 case TAGID_REMOVEOBJECT2:
524 return *(u16*)tag->data;
527 void setidintag(struct swf_tag* tag, int id)
529 *(u16*)tag->data = SWAP16(id);
532 char is_sprite_tag (int id)
535 while(spritetagids[t]>=0)
537 if(spritetagids[t] == id)
544 char is_defining_tag (int id)
547 while(definingtagids[t]>=0)
549 if(definingtagids[t] == id)
556 struct swf_tag* duptag(struct swf_tag*tag)
558 struct swf_tag* newtag = (struct swf_tag*)malloc(sizeof(struct swf_tag));
559 newtag->id = tag->id;
560 newtag->fulldata = (u8*)malloc(tag->fulllength);
561 newtag->fulllength = tag->fulllength;
562 newtag->data = newtag->fulldata + (tag->data - tag->fulldata);
563 newtag->length = tag->length;
564 memcpy(newtag->fulldata, tag->fulldata, tag->fulllength);