implemented distortionframe.
[swftools.git] / lib / python / tags.c
1 #include "pyutils.h"
2 #include "primitives.h"
3 #include "action.h"
4 #include "tag.h"
5 #include "tags.h"
6 #include "image.h"
7
8 //----------------------------------------------------------------------------
9
10 typedef struct _font_internal
11 {
12     SWFFONT* font;
13 } font_internal_t;
14 staticforward tag_internals_t font_tag;
15
16 static int font_parse(tag_internals_t*self)
17 {
18     font_internal_t*font = (font_internal_t*)self->data;
19     /* TODO */
20     PyErr_SetString(PyExc_Exception, setError("Font parsing not implemented yet"));
21     return 0;
22 }
23 static void font_dealloc(tag_internals_t*self)
24 {
25     font_internal_t*font = (font_internal_t*)self->data;
26     if(font->font) {
27         swf_FontFree(font->font);
28         font->font = 0;
29     }
30 }
31 static int font_fillTAG(tag_internals_t*self)
32 {
33     font_internal_t*fi = (font_internal_t*)self->data;
34     if(self->tag)
35         return 1;
36     self->tag = swf_InsertTag(0, ST_DEFINEFONT2);
37     swf_FontSetDefine2(self->tag, fi->font);
38     return 1;
39 }
40 static PyObject* f_DefineFont(PyObject* self, PyObject* args, PyObject* kwargs)
41 {
42     static char *kwlist[] = {"filename", NULL};
43     char*filename = 0;
44     PyObject*tag;
45     SWFFONT* font;
46
47     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &filename))
48         return NULL;
49
50     font = swf_LoadFont(filename);
51     if(!font) {
52         PyErr_SetString(PyExc_Exception, setError("Could not load %s", filename));
53         return NULL;
54     }
55
56     tag = tag_new(&font_tag);
57     tag_internals_t*itag = tag_getinternals(tag);
58     font_internal_t*fi = (font_internal_t*)itag->data;
59     font->id = 0;
60     fi->font = font;
61     return (PyObject*)tag;
62 }
63 static SWFFONT* font_getSWFFONT(PyObject*self)
64 {
65     PY_ASSERT_TYPE(self, &TagClass);
66     tag_internals_t*itag = tag_getinternals(self);
67     font_internal_t*fi = (font_internal_t*)itag->data;
68     return fi->font;
69 }
70 static tag_internals_t font_tag =
71 {
72     parse: font_parse,
73     fillTAG: font_fillTAG,
74     dealloc: font_dealloc,
75     tagfunctions: 0,
76     datasize: sizeof(font_internal_t),
77 };
78 //----------------------------------------------------------------------------
79
80 typedef struct _placeobject_internal
81 {
82     SWFPLACEOBJECT* po;
83 } placeobject_internal_t;
84 staticforward tag_internals_t placeobject_tag;
85
86 static void po_dealloc(tag_internals_t*self)
87 {
88     placeobject_internal_t*pi = (placeobject_internal_t*)self->data;
89     if(pi->po) {
90         swf_PlaceObjectFree(pi->po);
91         pi->po = 0;
92     }
93 }
94 static int po_parse(tag_internals_t*self)
95 {
96     placeobject_internal_t*pi = (placeobject_internal_t*)self->data;
97     /* TODO */
98     PyErr_SetString(PyExc_Exception, setError("Font parsing not implemented yet"));
99     return 0;
100 }
101 static int po_fillTAG(tag_internals_t*self)
102 {
103     placeobject_internal_t*pi = (placeobject_internal_t*)self->data;
104     self->tag = swf_InsertTag(0, ST_PLACEOBJECT2);
105     swf_SetPlaceObject(self->tag, pi->po);
106     return 1;
107 }
108 static PyObject* po_create(PyObject* self, PyObject* args, PyObject* kwargs,char move)
109 {
110     static char *kwlist[] = {"character", "depth", "matrix", "colortransform", "ratio", "name", "clipdepth", "action", NULL};
111     
112     PyObject*character = 0;
113     int depth;
114     int clipdepth = 0;
115     PyObject*matrix = 0;
116     PyObject*cxform = 0;
117     PyObject*action = 0;
118     int ratio = 0;
119     char* name = 0;
120     SWFPLACEOBJECT* po;
121     po = malloc(sizeof(SWFPLACEOBJECT));
122     memset(po, 0, sizeof(SWFPLACEOBJECT));
123
124     swf_GetPlaceObject(0, po);
125
126     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|O!O!isiO!", kwlist, 
127                 &character, 
128                 &depth, 
129                 &MatrixClass, &matrix, 
130                 &CXFormClass, &cxform,
131                 &ratio,
132                 &name,
133                 &clipdepth,
134                 &ActionClass, &action
135                 ))
136         return NULL;
137     po->depth = depth;
138     po->clipdepth = clipdepth;
139     po->ratio = ratio;
140     po->name = name;
141     po->move = move;
142     if(clipdepth) po->clipdepth = clipdepth;
143     if(matrix) po->matrix = matrix_getMatrix(matrix);
144     if(cxform) po->cxform = colortransform_getCXForm(cxform);
145     if(action) po->actions = action_getAction(action);
146
147     PyObject*tag;
148     tag = tag_new(&placeobject_tag);
149     tag_internals_t*itag = tag_getinternals(tag);
150     placeobject_internal_t*pi = (placeobject_internal_t*)itag->data;
151     pi->po = po;
152     if(!move) {
153         pi->po->id = tagmap_add(itag->tagmap,(PyObject*)character);
154     } else {
155         pi->po->id = 0;
156     }
157     
158     mylog("+%08x(%d) PlaceObject %08x(%d)\n", (int)tag, tag->ob_refcnt, character, character->ob_refcnt);
159
160     return (PyObject*)tag;
161 }
162 static PyObject* f_PlaceObject(PyObject* self, PyObject* args, PyObject* kwargs)
163 {
164     return po_create(self, args, kwargs, 0);
165 }
166 static PyObject* f_MoveObject(PyObject* self, PyObject* args, PyObject* kwargs)
167 {
168     return po_create(self, args, kwargs, 1);
169 }
170 static tag_internals_t placeobject_tag =
171 {
172     parse: po_parse,
173     fillTAG: po_fillTAG,
174     dealloc: po_dealloc,
175     tagfunctions: 0,
176     datasize: sizeof(placeobject_internal_t),
177 };
178 //----------------------------------------------------------------------------
179 staticforward tag_internals_t bgcolor_tag;
180 static PyObject* tag_setbackgroundcolor_getrgb(PyObject * self, PyObject*other)
181 {
182     tag_internals_t*itag = tag_getinternals(self);
183     int r,g,b;
184     r = itag->tag->data[0];
185     g = itag->tag->data[1];
186     b = itag->tag->data[2];
187     return Py_BuildValue("(iii)", r,g,b);
188 }
189 static PyMethodDef setbgcolor_methods[] = 
190 {{"getRGB", tag_setbackgroundcolor_getrgb, METH_VARARGS, "get's the color set by this tag"},
191  {NULL, NULL, 0, NULL}
192 };
193 static PyObject* f_SetBackgroundColor(PyObject* self, PyObject* args, PyObject* kwargs)
194 {
195     static char *kwlist[] = {"color", NULL};
196     int r=0,g=0,b=0;
197     PyObject*tag;
198     PyObject*color;
199     
200     tag = tag_new(&bgcolor_tag);
201     tag_internals_t*itag = tag_getinternals(tag);
202
203     /* 1st try- copy constructor */
204     if(!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &ColorClass, &color)) {
205         PyErr_Clear();
206         /* 2nd try- color's contructor */
207         color = f_Color(NULL, args, kwargs);
208     }
209     if(!color)
210         return NULL;
211
212     itag->tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
213     RGBA rgba = color_getRGBA(color);
214     swf_SetU8(itag->tag, rgba.r);
215     swf_SetU8(itag->tag, rgba.g);
216     swf_SetU8(itag->tag, rgba.b);
217     mylog(" %08x(%d) SetBackgroundColor(%02x,%02x,%02x) (colorobj=%08x(%d))\n", (int)tag, tag->ob_refcnt, rgba.r, rgba.g, rgba.b, color, color->ob_refcnt);
218     Py_DECREF(color);
219     return (PyObject*)tag;
220 }
221 static tag_internals_t bgcolor_tag =
222 {
223     parse: 0,
224     fillTAG: 0,
225     dealloc: 0,
226     tagfunctions: setbgcolor_methods,
227     datasize: 0,
228 };
229 //----------------------------------------------------------------------------
230 staticforward tag_internals_t protect_tag;
231 static PyObject* f_Protect(PyObject* self, PyObject* args, PyObject* kwargs)
232 {
233     static char *kwlist[] = {"password", NULL};
234     char*password = 0;
235
236     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &password))
237         return NULL;
238
239     PyObject*tag = tag_new(&protect_tag);
240     tag_internals_t*itag = tag_getinternals(tag);
241     itag->tag = swf_InsertTag(0, ST_PROTECT);
242     if(password) {
243         swf_SetPassword(itag->tag, password);
244     }
245     mylog("+%08x(%d) f_Protect", (int)tag, tag->ob_refcnt);
246     return (PyObject*)tag;
247 }
248 static tag_internals_t protect_tag =
249 {
250     parse: 0,
251     fillTAG: 0,
252     dealloc: 0,
253     tagfunctions: 0,
254     datasize: 0,
255 };
256 //----------------------------------------------------------------------------
257 staticforward tag_internals_t showframe_tag;
258 static PyObject* f_ShowFrame(PyObject* self, PyObject* args, PyObject* kwargs)
259 {
260     static char *kwlist[] = {"name", NULL};
261     char*name= 0;
262     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name))
263         return NULL;
264
265     PyObject*tag = tag_new(&showframe_tag);
266     tag_internals_t*itag = tag_getinternals(tag);
267     itag->tag = swf_InsertTag(0, ST_SHOWFRAME);
268     mylog("+%08x(%d) f_ShowFrame", (int)tag, tag->ob_refcnt);
269     return (PyObject*)tag;
270 }
271 static tag_internals_t showframe_tag =
272 {
273     parse: 0,
274     fillTAG: 0,
275     dealloc: 0,
276     tagfunctions: 0,
277     datasize: 0,
278 };
279 //----------------------------------------------------------------------------
280 staticforward tag_internals_t end_tag;
281 static tag_internals_t end_tag =
282 {
283     parse: 0,
284     fillTAG: 0,
285     dealloc: 0,
286     tagfunctions: 0,
287     datasize: 0,
288 };
289 //----------------------------------------------------------------------------
290 staticforward tag_internals_t text_tag;
291
292 typedef struct _text_internal
293 {
294     char*text;
295     SWFFONT* swffont;
296     RGBA rgba;
297     int size;
298 } text_internal_t;
299 staticforward tag_internals_t placeobject_tag;
300
301 static int text_fillTAG(tag_internals_t*self)
302 {
303     text_internal_t*ti = (text_internal_t*)self->data;
304     self->tag= swf_InsertTag(0, ST_DEFINETEXT2);
305     swf_SetU16(self->tag, /*ID*/0);
306     SRECT r = swf_SetDefineText(self->tag, ti->swffont, &ti->rgba, ti->text, ti->size);
307     return 1;
308 }
309 static PyObject* f_DefineText(PyObject* self, PyObject* args, PyObject* kwargs)
310 {
311     static char *kwlist[] = {"font", "text", "size", "color", NULL};
312     PyObject*tag = 0;
313     char*text = 0;
314     int textlen = 0;
315     PyObject*unicode16;
316     PyObject*unicode8;
317     int size = 0;
318     RGBA rgba = {255,0,0,0};
319     PyObject*color = 0;
320     PyObject*font = 0;
321
322     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!u#i|O!", kwlist, &TagClass, &font, &text, &textlen, &size, &ColorClass, &color))
323         return NULL;
324     
325     unicode16 = PyUnicode_DecodeUTF16(text, textlen*2, NULL, NULL);
326     unicode8 = PyUnicode_AsUTF8String(unicode16);
327     text = PyString_AS_STRING(unicode8);
328
329     if(color)
330         rgba = color_getRGBA(color);
331
332     mylog("DefineText: text = %s", text);
333     
334     tag = tag_new(&text_tag);
335     tag_internals_t* itag = tag_getinternals(tag);
336     text_internal_t*ti = (text_internal_t*)itag->data;
337
338     ti->swffont = font_getSWFFONT(font);
339     int font_id = tagmap_add(itag->tagmap, font); // add dependency on font
340     ti->swffont->id = font_id; // for swf_SetDefineTexts
341     ti->text = strdup(text);
342     ti->rgba = rgba;
343     ti->size = size;
344
345     return (PyObject*)tag;
346 }
347 static tag_internals_t text_tag =
348 {
349     parse: 0,
350     fillTAG: text_fillTAG,
351     dealloc: 0,
352     tagfunctions: 0,
353     datasize: sizeof(text_internal_t),
354 };
355 //----------------------------------------------------------------------------
356 staticforward tag_internals_t image_tag;
357
358 typedef struct _image_internal
359 {
360     RGBA*rgba;
361     int size;
362     int width;
363     int height;
364     int bpp;
365     char isindexed;
366     char islossless;
367 } image_internal_t;
368 staticforward tag_internals_t image_tag;
369
370 static int image_fillTAG(tag_internals_t*self)
371 {
372     image_internal_t*ti = (image_internal_t*)self->data;
373     self->tag= swf_InsertTag(0, ST_DEFINEBITSLOSSLESS2);
374     swf_SetU16(self->tag, /*ID*/0);
375     swf_SetLosslessBits(self->tag, ti->width, ti->height, ti->rgba, BMF_32BIT);
376     return 1;
377 }
378 static void image_dealloc(tag_internals_t*self)
379 {
380     image_internal_t*pi = (image_internal_t*)self->data;
381     if(pi->rgba) {
382         free(pi->rgba);pi->rgba = 0;
383     }
384 }
385 static int imagetag_getWidth(PyObject* self)
386 {
387     tag_internals_t*itag = tag_getinternals(self);
388     image_internal_t*pi = (image_internal_t*)itag->data;
389     return pi->width;
390 }
391 static int imagetag_getHeight(PyObject* self)
392 {
393     tag_internals_t*itag = tag_getinternals(self);
394     image_internal_t*pi = (image_internal_t*)itag->data;
395     return pi->height;
396 }
397 static PyObject* f_DefineImage(PyObject* self, PyObject* args, PyObject* kwargs)
398 {
399     static char *kwlist[] = {"image"};
400     PyObject*image = 0;
401     PyObject*tag = tag_new(&image_tag);
402
403     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &image))
404         return NULL;
405     
406     tag = tag_new(&image_tag);
407     tag_internals_t* itag = tag_getinternals(tag);
408     image_internal_t*ti = (image_internal_t*)itag->data;
409
410     ti->rgba = image_toRGBA(image);
411     if(!ti->rgba) // pass through exception
412         return 0;
413     ti->width = image_getWidth(image);
414     ti->height = image_getHeight(image);
415     ti->isindexed = 0;
416     ti->islossless = 1;
417     ti->bpp = 32;
418     ti->size = ti->width*ti->height;
419
420     return (PyObject*)tag;
421 }
422 static tag_internals_t image_tag =
423 {
424     parse: 0,
425     fillTAG: image_fillTAG,
426     dealloc: image_dealloc,
427     tagfunctions: 0,
428     datasize: sizeof(image_internal_t),
429 };
430 //----------------------------------------------------------------------------
431 staticforward tag_internals_t shape_tag;
432
433 typedef struct _shape_internal
434 {
435     SHAPE2*shape;
436 } shape_internal_t;
437 staticforward tag_internals_t shape_tag;
438
439 static int shape_fillTAG(tag_internals_t*self)
440 {
441     shape_internal_t*ti = (shape_internal_t*)self->data;
442     self->tag= swf_InsertTag(0, ST_DEFINESHAPE3);
443     swf_SetU16(self->tag, /*ID*/0);
444     swf_SetShape2(self->tag, ti->shape);
445     return 1;
446 }
447 static void shape_dealloc(tag_internals_t*self)
448 {
449     shape_internal_t*pi = (shape_internal_t*)self->data;
450     if(pi->shape) {
451         swf_Shape2Free(pi->shape);
452         pi->shape = 0;
453     }
454 }
455 static PyObject* f_DefineImageShape(PyObject* self, PyObject* args, PyObject* kwargs)
456 {
457     static char *kwlist[] = {"image"};
458     PyObject*shape = 0;
459     PyObject*tag = tag_new(&shape_tag);
460     PyObject*image = 0;
461
462     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &TagClass, &image))
463         return NULL;
464     
465     tag = tag_new(&shape_tag);
466     tag_internals_t* itag = tag_getinternals(tag);
467     shape_internal_t*ti = (shape_internal_t*)itag->data;
468     ti->shape = 0; /*HACK*/
469
470     int width = imagetag_getWidth(image);
471     int height = imagetag_getHeight(image);
472     int id = tagmap_add(itag->tagmap, image);
473     itag->tag= swf_InsertTag(0, ST_DEFINESHAPE3);
474     swf_SetU16(itag->tag, 0);
475     swf_ShapeSetBitmapRect(itag->tag, id, width, height);
476     return (PyObject*)tag;
477 }
478 static tag_internals_t shape_tag =
479 {
480     parse: 0,
481     fillTAG: shape_fillTAG,
482     dealloc: shape_dealloc,
483     tagfunctions: 0,
484     datasize: sizeof(shape_internal_t),
485 };
486 //----------------------------------------------------------------------------
487
488 typedef struct _videostream_internal
489 {
490     VIDEOSTREAM* stream;
491     int lastiframe;
492 } videostream_internal_t;
493 staticforward tag_internals_t videostream_tag;
494 staticforward tag_internals_t videoframe_tag;
495
496 static int videostream_parse(tag_internals_t*self)
497 {
498     videostream_internal_t*videostream = (videostream_internal_t*)self->data;
499     /* TODO */
500     PyErr_SetString(PyExc_Exception, setError("videostream parsing not implemented yet"));
501     return 0;
502 }
503 static void videostream_dealloc(tag_internals_t*self)
504 {
505     videostream_internal_t*videostream = (videostream_internal_t*)self->data;
506     if(videostream->stream) {
507         swf_VideoStreamClear(videostream->stream);
508         free(videostream->stream);
509         videostream->stream = 0;
510     }
511 }
512 static int videostream_fillTAG(tag_internals_t*self)
513 {
514     videostream_internal_t*fi = (videostream_internal_t*)self->data;
515     if(self->tag)
516         return 1;
517     PyErr_SetString(PyExc_Exception, setError("videostream filling not implemented"));
518     return 0;
519 }
520 static PyObject* f_DefineVideoStream(PyObject* self, PyObject* args, PyObject* kwargs)
521 {
522     PyObject*tag = tag_new(&videostream_tag);
523    
524     int width=0,height=0,frames=65535;
525     static char *kwlist[] = {"width", "height", "frames", NULL};
526     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i", kwlist, &width, &height, &frames))
527         return NULL;
528
529     printf(": %d %d\n", width, height);
530     
531     tag_internals_t*itag = tag_getinternals(tag);
532     videostream_internal_t*fi = (videostream_internal_t*)itag->data;
533     fi->stream = malloc(sizeof(VIDEOSTREAM));
534     memset(fi->stream, 0, sizeof(VIDEOSTREAM));
535
536     TAG*t = swf_InsertTag(0, ST_DEFINEVIDEOSTREAM);
537     swf_SetU16(t, 0); /* id */
538     swf_SetVideoStreamDefine(t, fi->stream, frames, width, height);
539     itag->tag = t;
540     fi->lastiframe = -65536;
541     return (PyObject*)tag;
542 }
543 static VIDEOSTREAM* videostream_getVIDEOSTREAM(PyObject*self)
544 {
545     PY_ASSERT_TYPE(self, &TagClass);
546     tag_internals_t*itag = tag_getinternals(self);
547     videostream_internal_t*fi = (videostream_internal_t*)itag->data;
548     return fi->stream;
549 }
550 static PyObject* videostream_getbwidth(PyObject*self, PyObject*args)
551 {
552     tag_internals_t*itag = tag_getinternals(self);
553     videostream_internal_t*fi = (videostream_internal_t*)itag->data;
554     int width = fi->stream->bbx;
555     return Py_BuildValue("i", width);
556 }
557 static PyObject* videostream_getbheight(PyObject*self, PyObject*args)
558 {
559     tag_internals_t*itag = tag_getinternals(self);
560     videostream_internal_t*fi = (videostream_internal_t*)itag->data;
561     int height = fi->stream->bby;
562     return Py_BuildValue("i", height);
563 }
564 static PyObject* videostream_addFrame(PyObject*self, PyObject*args, PyObject*kwargs)
565 {
566     tag_internals_t*_itag = tag_getinternals(self);
567     videostream_internal_t*fi = (videostream_internal_t*)_itag->data;
568    
569     PyObject*image = 0;
570     char*type=0; // none, "i", "p"
571     int quant=7;
572     static char *kwlist[] = {"image", "quant", "type", NULL};
573     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|is", kwlist, &image, &quant, &type))
574         return NULL;
575     if(fi->stream->width != image_getWidth(image)) {
576         PyErr_SetString(PyExc_Exception, setError("bad image width %d!=%d", image_getWidth(image), fi->stream->width));return 0;
577     }
578     if(fi->stream->height != image_getHeight(image)) {
579         PyErr_SetString(PyExc_Exception, setError("bad image width %d!=%d", image_getHeight(image), fi->stream->height));return 0;
580     }
581     PyObject*tag = tag_new(&videoframe_tag);
582     tag_internals_t*itag = tag_getinternals(tag);
583
584     RGBA*pic = image_toRGBA(image);
585     if(!pic)
586         return 0;
587
588     
589 {  int f,j=0,i=0,rr,gg,bb;
590    FILE *o;
591    RGBA*it = pic;
592    char*filename="test.ppm";
593    printf("Creating %s %dx%d\n",filename, 512,512);
594    o=fopen(filename, "wb");
595    fprintf(o,"P6\n%d %d\n255\n",512, 512);
596    
597    while(j<512*512) {
598     rr=it->r;
599     gg=it->g;
600     bb=it->b;
601     fprintf(o,"%c%c%c",rr,gg,bb);
602     it++;
603     j++;
604    }
605    fclose(o);
606 }
607
608     TAG* t = swf_InsertTag(0, ST_VIDEOFRAME);
609     if((type && (type[0]=='I' || type[0]=='i')) || (type==0 && fi->lastiframe+64 < fi->stream->frame)) {
610         swf_SetU16(t,0); /* id */
611         swf_SetVideoStreamIFrame(t, fi->stream, pic, quant);
612         fi->lastiframe = fi->stream->frame;
613     } else {
614         swf_SetU16(t,0);
615         swf_SetVideoStreamPFrame(t, fi->stream, pic, quant);
616     }
617     itag->tag = t;
618     tagmap_addMapping(itag->tagmap, 0, self);
619     free(pic);
620     return tag;
621 }
622 static PyObject* videostream_addDistortionFrame(PyObject*self, PyObject*args, PyObject*kwargs)
623 {
624     tag_internals_t*_itag = tag_getinternals(self);
625     videostream_internal_t*fi = (videostream_internal_t*)_itag->data;
626     
627     static char *kwlist[] = {"image", "quant", NULL};
628     int quant=7;
629     PyObject* array = 0;
630     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i", kwlist, &array, &quant))
631         return NULL;
632
633     signed char* movex = malloc(fi->stream->bbx * fi->stream->bby);
634     signed char* movey = malloc(fi->stream->bbx * fi->stream->bby);
635     signed char* itx=movex;
636     signed char* ity=movey;
637     int x,y;
638     if(!array || !PySequence_Check(array))
639         return PY_ERROR("Not an array");
640     if(PySequence_Length(array) < fi->stream->bby)
641         return PY_ERROR("Array (y) has to have at least %d elements, but has only %d ", fi->stream->bby, PySequence_Length(array));
642     for(y=0;y<fi->stream->bby;y++) {
643         PyObject*line = PySequence_GetItem(array, y);
644         if(!line || !PySequence_Check(line))
645             return PY_ERROR("Not an array of arrays");
646         if(PySequence_Length(line) < fi->stream->bbx)
647             return PY_ERROR("Inner arrays (x) have to be at least %d long- %dth is only %d", fi->stream->bbx, y, PySequence_Length(line));
648
649         for(x=0;x<fi->stream->bbx;x++) {
650             PyObject*pixel = PySequence_GetItem(line, x);
651             if(!pixel) {
652                 *itx = 0;
653                 *ity = 0;
654             } else {
655                 if(!PyComplex_Check(pixel)) {
656                     return PY_ERROR("Not an array of arrays of complex numbers");
657                 }
658                 *itx = (signed char)PyComplex_RealAsDouble(pixel);
659                 *ity = (signed char)PyComplex_ImagAsDouble(pixel);
660             }
661             itx++;
662             ity++;
663         }
664     }
665     
666     PyObject*tag = tag_new(&videoframe_tag);
667     tag_internals_t*itag = tag_getinternals(tag);
668     
669     TAG* t = swf_InsertTag(0, ST_VIDEOFRAME);
670     swf_SetU16(t,0); /* id */
671     swf_SetVideoStreamMover(t, fi->stream, movex, movey, quant);
672
673     itag->tag = t;
674     tagmap_addMapping(itag->tagmap, 0, self);
675
676     free(movex);
677     free(movey);
678
679     return tag;
680 }
681 static PyMethodDef videostream_methods[] = 
682 {{"xblocks", videostream_getbwidth, METH_VARARGS, "get's the number of horizontal blocks"},
683  {"yblocks", videostream_getbheight, METH_VARARGS, "get's the number of vertical blocks"},
684  {"addFrame", (PyCFunction)videostream_addFrame, METH_KEYWORDS, "add a Video Frame"},
685  {"addDistortionFrame", (PyCFunction)videostream_addDistortionFrame, METH_KEYWORDS, "add a MVD frame"},
686  {NULL, NULL, 0, NULL}
687 };
688
689 static tag_internals_t videostream_tag =
690 {
691     parse: videostream_parse,
692     fillTAG: videostream_fillTAG,
693     dealloc: videostream_dealloc,
694     tagfunctions: videostream_methods,
695     datasize: sizeof(videostream_internal_t),
696 };
697
698 //============================================================================
699
700 static tag_internals_t videoframe_tag =
701 {
702     parse: 0,
703     fillTAG: 0,
704     dealloc: 0,
705     tagfunctions: 0,
706     datasize: 0
707 };
708
709 //============================================================================
710
711 static PyMethodDef TagMethods[] = 
712 {
713     /* TAGS */
714     {"BackgroundColor", (PyCFunction)f_SetBackgroundColor, METH_KEYWORDS, "Create a SetBackGroundColor Tag."},
715     {"Protect", (PyCFunction)f_Protect, METH_KEYWORDS, "Create a Protect Tag."},
716     {"Font", (PyCFunction)f_DefineFont, METH_KEYWORDS, "Create a DefineFont Tag."},
717     {"Text", (PyCFunction)f_DefineText, METH_KEYWORDS, "Create a DefineText Tag."},
718     {"PlaceObject", (PyCFunction)f_PlaceObject, METH_KEYWORDS, "Create a PlaceObject Tag."},
719     {"MoveObject", (PyCFunction)f_MoveObject, METH_KEYWORDS, "Create a PlaceObject Move Tag."},
720     {"VideoStream", (PyCFunction)f_DefineVideoStream, METH_KEYWORDS, "Create a Videostream."},
721     {"Image", (PyCFunction)f_DefineImage, METH_KEYWORDS, "Create an SWF Image Tag."},
722     {"ImageShape", (PyCFunction)f_DefineImageShape, METH_KEYWORDS, "Create an SWF Image Shape Tag."},
723     {"ShowFrame", (PyCFunction)f_ShowFrame, METH_KEYWORDS, "Create an SWF Show Frame Tag."},
724     {NULL, NULL, 0, NULL}
725 };
726 PyMethodDef* tags_getMethods()
727 {
728     TagClass.ob_type = &PyType_Type;
729     
730     register_tag(ST_PLACEOBJECT,&placeobject_tag);
731     register_tag(ST_PLACEOBJECT2,&placeobject_tag);
732     register_tag(ST_SETBACKGROUNDCOLOR,&bgcolor_tag);
733     register_tag(ST_DEFINEFONT,&font_tag);
734     register_tag(ST_PROTECT,&protect_tag);
735     register_tag(ST_DEFINETEXT,&text_tag);
736     register_tag(ST_DEFINEBITSJPEG,&image_tag);
737     register_tag(ST_DEFINEBITSJPEG2,&image_tag);
738     register_tag(ST_DEFINEBITSJPEG3,&image_tag);
739     register_tag(ST_DEFINEBITSLOSSLESS,&image_tag);
740     register_tag(ST_DEFINEBITSLOSSLESS2,&image_tag);
741     register_tag(ST_END,&end_tag);
742
743     return TagMethods;
744 }