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);
95 struct RECT readRECT(struct reader_t*reader)
100 reader_readbits(reader,&a,5);
101 reader_readsbits(reader,&b,a);
103 reader_readsbits(reader,&b,a);
105 reader_readsbits(reader,&b,a);
107 reader_readsbits(reader,&b,a);
113 void writeRECT(u8**pos, struct RECT*r)
117 writer_init(&w, *pos, 256);
118 writer_writebits(&w, 31, 5); //FIXME:count
119 writer_writebits(&w, r->x1, 31);
120 writer_writebits(&w, r->x2, 31);
121 writer_writebits(&w, r->y1, 31);
122 writer_writebits(&w, r->y2, 31);
123 writer_resetbits(&w);
124 *pos = writer_getpos(&w);
127 struct CXFORM readCXFORM(struct reader_t*r, char alpha)
131 c.hasadd=reader_readbit(r);
132 c.hasmult=reader_readbit(r);
133 bits=reader_getbits(r,4);
138 c.rmult=reader_getsbits(r,bits)/65536.0;
139 c.gmult=reader_getsbits(r,bits)/65536.0;
140 c.bmult=reader_getsbits(r,bits)/65536.0;
142 c.amult=reader_getsbits(r,bits)/65536.0;
146 c.radd=reader_getsbits(r,bits)/65536.0;
147 c.gadd=reader_getsbits(r,bits)/65536.0;
148 c.badd=reader_getsbits(r,bits)/65536.0;
150 c.aadd=reader_getsbits(r,bits)/65536.0;
155 void CXFORM_write(struct CXFORM *obj, struct writer_t*w)
158 writer_writebit(w,obj->hasadd);
159 writer_writebit(w,obj->hasmult);
160 writer_writebits(w, bits, 4);
163 writer_writebits(w, obj->rmult, bits);
164 writer_writebits(w, obj->gmult, bits);
165 writer_writebits(w, obj->bmult, bits);
167 writer_writebits(w, obj->amult, 4);
171 writer_writebits(w, obj->radd, bits);
172 writer_writebits(w, obj->gadd, bits);
173 writer_writebits(w, obj->badd, bits);
175 writer_writebits(w, obj->aadd, 4);
179 unsigned char* readSTRING(struct reader_t*r)
181 unsigned char*now = reader_getinputpos(r);
190 void MATRIX_init(struct MATRIX*m)
201 struct MATRIX readMATRIX(struct reader_t*r)
209 m.a[0][0] = m.a[1][1] = 1;
210 m.a[0][1] = m.a[1][0] = 0;
211 m.hasscale=reader_readbit(r);
214 u8 scalebits=reader_getbits(r,5);
215 s32 scalex=reader_getsbits(r,scalebits);
216 s32 scaley=reader_getsbits(r,scalebits);
217 m.a[0][0]=scalex/65536.0;
218 m.a[1][1]=scaley/65536.0;
220 m.hasrotate=reader_readbit(r);
223 u8 rotbits=reader_getbits(r,5);
224 s32 rotateskew0=reader_getsbits(r,rotbits);
225 s32 rotateskew1=reader_getsbits(r,rotbits);
226 m.a[0][1]=rotateskew0/65536.0;
227 m.a[1][0]=rotateskew1/65536.0;
230 translatebits=reader_getbits(r,5);
231 translatex=reader_getsbits(r,translatebits);
232 translatey=reader_getsbits(r,translatebits);
239 void MATRIX_write(struct MATRIX * m , struct writer_t*w)
241 writer_writebit (w, m->hasscale);
245 writer_writebits(w, bits, 5);
246 writer_writebits(w, (u32)(m->a[0][0]*65536.0), bits);
247 writer_writebits(w, (u32)(m->a[1][1]*65536.0), bits);
249 writer_writebit (w, m->hasrotate);
253 writer_writebits(w, bits, 5);
254 writer_writebits(w, (u32)(m->a[0][1]*65536.0), bits);
255 writer_writebits(w, (u32)(m->a[1][0]*65536.0), bits);
261 writer_writebits(w, bits, 5);
262 writer_writebits(w, (u32)(m->b[0]), bits);
263 writer_writebits(w, (u32)(m->b[1]), bits);
268 int swf_read_tag(struct reader_t*r, struct swf_tag* swftag)
270 u8*pos2,*pos = reader_getinputpos(r);
276 reader_input2(r, &tag);
278 taglength = tag & 0x3f;
279 if (taglength == 0x3f)
281 reader_input4(r, &taglength);
285 swftag->length = taglength;
286 swftag->data = reader_getinputpos(r);
287 reader_skip(r,taglength);
288 pos2 = reader_getinputpos(r);
289 swftag->fulllength = pos2 - pos;
290 swftag->fulldata = pos;
294 int swf_count_tags(struct reader_t*r)
296 u8*pos = reader_getinputpos(r);
302 swf_read_tag(r,&tag);
308 reader_setinputpos(r,pos);
312 void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag)
315 reader_init (&r, tag->data, tag->length);
316 obj -> id = reader_readu16(&r);
317 obj -> depth = reader_readu16(&r);
318 obj -> matrix = readMATRIX(&r);
319 obj -> hascxform = (reader_getinputpos(&r) < &tag->data[tag->length]);
321 obj -> cxform = readCXFORM(&r, 0);
324 void placeobject_write (struct PlaceObject*obj, struct writer_t*w)
326 u16 taghead = 0x3f | TAGID_PLACEOBJECT<<6;
331 writer_write(w, &taghead, 2);
332 lenpos = writer_getpos(w);
334 writer_write(w, &taghead, 2);
335 writer_write(w, &taghead, 2);
337 pos = writer_getpos(w);
339 writer_write(w, &obj->id, 2);
340 writer_write(w, &obj->depth, 2);
341 MATRIX_write(&obj->matrix, w);
345 CXFORM_write(&obj->cxform, w);
349 len = (u8*)writer_getpos(w) - pos;
356 void placeobject2_init (struct PlaceObject2*obj,struct swf_tag*tag)
360 reader_init (&r, tag->data, tag->length);
362 obj->reserved= (b>>7)&1;
363 obj->hasclipactions= (b>>6)&1;
364 obj->hasname= (b>>5)&1;
365 obj->hasratio= (b>>4)&1;
366 obj->hascolortransform=(b>>3)&1;
367 obj->hasmatrix= (b>>2)&1;
368 obj->hascharacter= (b>>1)&1;
369 obj->hasmove= (b>>0)&1;
371 obj->depth = reader_readu16(&r);
373 if(obj->hascharacter) {
374 obj->id = reader_readu16(&r);
377 obj->matrix = readMATRIX(&r);
379 if(obj->hascolortransform) {
380 obj->cxform = readCXFORM(&r,0);
383 obj->ratio=reader_readu16(&r);
387 obj->name=readSTRING(&r);
389 if(obj->hasclipactions) {
390 obj->clipactions=reader_readu16(&r);
394 void placeobject2_write (struct PlaceObject2*obj, struct writer_t*w)
396 u8 flags = obj->reserved<<7 | obj->hasclipactions<<6 | obj->hasname<<5 | obj->hasratio<<4 |
397 obj->hascolortransform<<3 | obj->hasmatrix<<2 | obj->hascharacter<<1 | obj->hasmove;
398 u16 taghead = SWAP16(0x3f | TAGID_PLACEOBJECT2<<6);
403 writer_write(w, &taghead, 2);
404 lenpos = writer_getpos(w);
405 writer_write(w, &taghead, 2);
406 writer_write(w, &taghead, 2);
408 pos = writer_getpos(w);
410 writer_writeu8(w, flags);
411 writer_writeu16(w, obj->depth);
412 if(obj->hascharacter)
413 writer_writeu16(w, obj->id);
415 MATRIX_write(&obj->matrix, w);
416 if(obj->hascolortransform)
417 CXFORM_write(&obj->cxform, w);
419 writer_writeu16(w, obj->ratio);
422 writer_write(w, obj->name, strlen(obj->name) + 1);
423 if(obj->hasclipactions)
424 writer_writeu16(w, obj->clipactions);
427 len = (u8*)writer_getpos(w) - pos;
434 void read_swf(struct swffile*swf, uchar*data, int length)
437 struct flash_header head;
440 swf_init(&r, data, length);
441 head = swf_read_header(&r);
442 logf("<debug> [HEADER] the version is %d", head.version);
443 logf("<debug> [HEADER] the length is %d", head.length);
444 logf("<debug> [HEADER] the boundingBox is %d:%d:%d:%d",
445 head.boundingBox.x1,head.boundingBox.y1,
446 head.boundingBox.x2,head.boundingBox.y2);
447 logf("<debug> [HEADER] the rate (frames/second) is %d", head.rate);
448 logf("<debug> [HEADER] the count (frame number) is %d", head.count);
450 tagnum = swf_count_tags(&r);
451 swf->tags = (struct swf_tag*)malloc(sizeof(struct swf_tag)*tagnum);
453 logf("<debug> [HEADER] the file consists of %d tags", tagnum);
459 swf_read_tag(&r, &tag);
460 logf("<debug> read tag %02x (%d bytes)", tag.id, tag.length);
461 swf->tags[pos] = tag;
463 if(tag.id == TAGID_END)
466 swf->tagnum = tagnum;
470 int definingtagids[] =
474 TAGID_DEFINEMORPHSHAPE,
479 TAGID_DEFINEEDITTEXT,
481 TAGID_DEFINEBITSJPEG2,
482 TAGID_DEFINEBITSJPEG3,
483 TAGID_DEFINEBITSLOSSLESS,
484 TAGID_DEFINEBITSLOSSLESS2,
493 // tags which may be used inside a sprite definition
499 TAGID_REMOVEOBJECT2, //?
503 TAGID_SOUNDSTREAMHEAD,
504 TAGID_SOUNDSTREAMHEAD2,
505 TAGID_SOUNDSTREAMBLOCK,
510 int getidfromtag(struct swf_tag* tag)
514 case TAGID_PLACEOBJECT2:
516 case TAGID_PLACEOBJECT: {
518 reader_init (&r, tag->data, tag->length);
520 char b = reader_readu8(&r);
525 return reader_readu16(&r);
528 case TAGID_REMOVEOBJECT:
529 return tag->data[0]+tag->data[1]*256;
531 case TAGID_REMOVEOBJECT2:
536 return tag->data[0]+tag->data[1]*256;
539 void setidintag(struct swf_tag* tag, int id)
542 tag->data[1] = id>>8;
545 char is_sprite_tag (int id)
548 while(spritetagids[t]>=0)
550 if(spritetagids[t] == id)
557 char is_defining_tag (int id)
560 while(definingtagids[t]>=0)
562 if(definingtagids[t] == id)
569 struct swf_tag* duptag(struct swf_tag*tag)
571 struct swf_tag* newtag = (struct swf_tag*)malloc(sizeof(struct swf_tag));
572 newtag->id = tag->id;
573 newtag->fulldata = (u8*)malloc(tag->fulllength);
574 newtag->fulllength = tag->fulllength;
575 newtag->data = newtag->fulldata + (tag->data - tag->fulldata);
576 newtag->length = tag->length;
577 memcpy(newtag->fulldata, tag->fulldata, tag->fulllength);