Two in one:
[blender.git] / source / blender / src / seqeffects.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
27  *
28  * ***** END GPL/BL DUAL LICENSE BLOCK *****
29  */
30
31 #include <string.h>
32 #include <math.h>
33 #include <stdlib.h>
34
35 #include "MEM_guardedalloc.h"
36 #include "PIL_dynlib.h"
37
38 #include "DNA_sequence_types.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42
43 #include "BIF_interface.h"
44 #include "BIF_toolbox.h"
45
46 #include "BSE_seqeffects.h"
47 #include "BSE_sequence.h"
48
49 #include "BKE_global.h"
50 #include "BKE_ipo.h"
51 #include "BKE_plugin_types.h"
52 #include "BKE_texture.h"
53 #include "BKE_utildefines.h"
54
55 #include "IMB_imbuf_types.h"
56 #include "IMB_imbuf.h"
57
58 #include "RE_pipeline.h"                // talks to entire render API
59
60 #include "blendef.h"
61
62 /* Glow effect */
63 enum {
64         GlowR=0,
65         GlowG=1,
66         GlowB=2,
67         GlowA=3
68 };
69
70
71 /* **********************************************************************
72    PLUGINS
73    ********************************************************************** */
74
75 static void open_plugin_seq(PluginSeq *pis, const char *seqname)
76 {
77         int (*version)();
78         void* (*alloc_private)();
79         char *cp;
80
81         /* to be sure: (is tested for) */
82         pis->doit= 0;
83         pis->pname= 0;
84         pis->varstr= 0;
85         pis->cfra= 0;
86         pis->version= 0;
87         pis->instance_private_data = 0;
88
89         /* clear the error list */
90         PIL_dynlib_get_error_as_string(NULL);
91
92         /* if(pis->handle) PIL_dynlib_close(pis->handle); */
93         /* pis->handle= 0; */
94
95         /* open the needed object */
96         pis->handle= PIL_dynlib_open(pis->name);
97         if(test_dlerr(pis->name, pis->name)) return;
98
99         if (pis->handle != 0) {
100                 /* find the address of the version function */
101                 version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
102                 if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
103
104                 if (version != 0) {
105                         pis->version= version();
106                         if (pis->version >= 2 && pis->version <= 5) {
107                                 int (*info_func)(PluginInfo *);
108                                 PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");;
109
110                                 info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
111
112                                 if(info_func == NULL) error("No info func");
113                                 else {
114                                         info_func(info);
115
116                                         pis->pname= info->name;
117                                         pis->vars= info->nvars;
118                                         pis->cfra= info->cfra;
119
120                                         pis->varstr= info->varstr;
121
122                                         pis->doit= (void(*)(void))info->seq_doit;
123                                         if (info->init)
124                                                 info->init();
125                                 }
126                                 MEM_freeN(info);
127
128                                 cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
129                                 if(cp) strncpy(cp, seqname, 21);
130                         } else {
131                                 printf ("Plugin returned unrecognized version number\n");
132                                 return;
133                         }
134                 }
135                 alloc_private = (void* (*)())PIL_dynlib_find_symbol(
136                         pis->handle, "plugin_seq_alloc_private_data");
137                 if (alloc_private) {
138                         pis->instance_private_data = alloc_private();
139                 }
140                 
141                 pis->current_private_data = (void**) 
142                         PIL_dynlib_find_symbol(
143                                 pis->handle, "plugin_private_data");
144         }
145 }
146
147 static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
148 {
149         PluginSeq *pis;
150         VarStruct *varstr;
151         int a;
152
153         pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
154
155         strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE);
156         open_plugin_seq(pis, seqname);
157
158         if(pis->doit==0) {
159                 if(pis->handle==0) error("no plugin: %s", str);
160                 else error("in plugin: %s", str);
161                 MEM_freeN(pis);
162                 return 0;
163         }
164
165         /* default values */
166         varstr= pis->varstr;
167         for(a=0; a<pis->vars; a++, varstr++) {
168                 if( (varstr->type & FLO)==FLO)
169                         pis->data[a]= varstr->def;
170                 else if( (varstr->type & INT)==INT)
171                         *((int *)(pis->data+a))= (int) varstr->def;
172         }
173
174         return pis;
175 }
176
177 static void free_plugin_seq(PluginSeq *pis)
178 {
179         if(pis==0) return;
180
181         /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
182
183         if (pis->instance_private_data) {
184                 void (*free_private)(void *);
185
186                 free_private = (void (*)(void *))PIL_dynlib_find_symbol(
187                         pis->handle, "plugin_seq_free_private_data");
188                 if (free_private) {
189                         free_private(pis->instance_private_data);
190                 }
191         }
192
193         MEM_freeN(pis);
194 }
195
196 static void init_plugin(Sequence * seq, const char * fname)
197 {
198         seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2);
199 }
200
201 /* 
202  * FIXME: should query plugin! Could be generator, that needs zero inputs...
203  */
204 static int num_inputs_plugin()
205 {
206         return 1;
207 }
208
209 static void load_plugin(Sequence * seq)
210 {
211         if (seq) {
212                 open_plugin_seq(seq->plugin, seq->name+2);
213         }
214 }
215
216 static void copy_plugin(Sequence * dst, Sequence * src)
217 {
218         if(src->plugin) {
219                 dst->plugin= MEM_dupallocN(src->plugin);
220                 open_plugin_seq(dst->plugin, dst->name+2);
221         }
222 }
223
224 static ImBuf * IMB_cast_away_list(ImBuf * i)
225 {
226         if (!i) {
227                 return 0;
228         }
229         return (ImBuf*) (((void**) i) + 2);
230 }
231
232 static void do_plugin_effect(Sequence * seq,int cfra,
233                              float facf0, float facf1, int x, int y, 
234                              struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
235                              struct ImBuf *ibuf3, struct ImBuf *out)
236 {
237         char *cp;
238         int float_rendering;
239         int use_temp_bufs = 0; /* Are needed since blur.c (and maybe some other
240                                   old plugins) do very bad stuff
241                                   with imbuf-internals */
242
243         if(seq->plugin && seq->plugin->doit) {
244                 if(seq->plugin->cfra) 
245                         *(seq->plugin->cfra)= frame_to_float(cfra);
246
247                 cp = PIL_dynlib_find_symbol(
248                         seq->plugin->handle, "seqname");
249
250                 if(cp) strncpy(cp, seq->name+2, 22);
251
252                 if (seq->plugin->current_private_data) {
253                         *seq->plugin->current_private_data 
254                                 = seq->plugin->instance_private_data;
255                 }
256
257                 float_rendering = (out->rect_float != NULL);
258
259                 if (seq->plugin->version<=3 && float_rendering) {
260                         use_temp_bufs = 1;
261
262                         if (ibuf1) {
263                                 ibuf1 = IMB_dupImBuf(ibuf1);
264                                 IMB_rect_from_float(ibuf1);
265                                 imb_freerectfloatImBuf(ibuf1);
266                                 ibuf1->flags &= ~IB_rectfloat;
267                         }
268                         if (ibuf2) {
269                                 ibuf2 = IMB_dupImBuf(ibuf2);
270                                 IMB_rect_from_float(ibuf2);
271                                 imb_freerectfloatImBuf(ibuf2);
272                                 ibuf2->flags &= ~IB_rectfloat;
273                         } 
274                         if (ibuf3) {
275                                 ibuf3 = IMB_dupImBuf(ibuf3);
276                                 IMB_rect_from_float(ibuf3);
277                                 imb_freerectfloatImBuf(ibuf3);
278                                 ibuf3->flags &= ~IB_rectfloat;
279                         } 
280                         if (!out->rect) imb_addrectImBuf(out);
281                         imb_freerectfloatImBuf(out);
282                         out->flags &= ~IB_rectfloat;
283                 }
284
285                 if (seq->plugin->version<=2) {
286                         if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
287                         if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
288                         if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
289                 }
290
291                 if (seq->plugin->version<=4) {
292                         ((SeqDoit)seq->plugin->doit)(
293                                 seq->plugin->data, facf0, facf1, x, y,
294                                 IMB_cast_away_list(ibuf1), 
295                                 IMB_cast_away_list(ibuf2), 
296                                 IMB_cast_away_list(out), 
297                                 IMB_cast_away_list(ibuf3));
298                 } else {
299                         ((SeqDoit)seq->plugin->doit)(
300                                 seq->plugin->data, facf0, facf1, x, y,
301                                 ibuf1, ibuf2, out, ibuf3);
302                 }
303
304                 if (seq->plugin->version<=2) {
305                         if (!use_temp_bufs) {
306                                 if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
307                                 if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
308                                 if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
309                         }
310                         IMB_convert_rgba_to_abgr(out);
311                 }
312                 if (seq->plugin->version<=3 && float_rendering) {
313                         IMB_float_from_rect(out);
314                 }
315
316                 if (use_temp_bufs) {
317                         if (ibuf1) IMB_freeImBuf(ibuf1);
318                         if (ibuf2) IMB_freeImBuf(ibuf2);
319                         if (ibuf3) IMB_freeImBuf(ibuf3);
320                 }
321         }
322 }
323
324 static int do_plugin_early_out(struct Sequence *seq,
325                                float facf0, float facf1)
326 {
327         return 0;
328 }
329
330 static void free_plugin(struct Sequence * seq)
331 {
332         free_plugin_seq(seq->plugin);
333         seq->plugin = 0;
334 }
335
336 /* **********************************************************************
337    ALPHA OVER
338    ********************************************************************** */
339
340 static void init_alpha_over_or_under(Sequence * seq)
341 {
342         Sequence * seq1 = seq->seq1;
343         Sequence * seq2 = seq->seq2;
344
345         seq->seq2= seq1;
346         seq->seq1= seq2;
347 }
348
349 static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, 
350                                      char * rect1, char *rect2, char *out)
351 {
352         int fac2, mfac, fac, fac4;
353         int xo, tempc;
354         char *rt1, *rt2, *rt;
355
356         xo= x;
357         rt1= (char *)rect1;
358         rt2= (char *)rect2;
359         rt= (char *)out;
360
361         fac2= (int)(256.0*facf0);
362         fac4= (int)(256.0*facf1);
363
364         while(y--) {
365
366                 x= xo;
367                 while(x--) {
368
369                         /* rt = rt1 over rt2  (alpha from rt1) */
370
371                         fac= fac2;
372                         mfac= 256 - ( (fac2*rt1[3])>>8 );
373
374                         if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
375                         else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
376                         else {
377                                 tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
378                                 if(tempc>255) rt[0]= 255; else rt[0]= tempc;
379                                 tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
380                                 if(tempc>255) rt[1]= 255; else rt[1]= tempc;
381                                 tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
382                                 if(tempc>255) rt[2]= 255; else rt[2]= tempc;
383                                 tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
384                                 if(tempc>255) rt[3]= 255; else rt[3]= tempc;
385                         }
386                         rt1+= 4; rt2+= 4; rt+= 4;
387                 }
388
389                 if(y==0) break;
390                 y--;
391
392                 x= xo;
393                 while(x--) {
394
395                         fac= fac4;
396                         mfac= 256 - ( (fac4*rt1[3])>>8 );
397
398                         if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
399                         else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
400                         else {
401                                 tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
402                                 if(tempc>255) rt[0]= 255; else rt[0]= tempc;
403                                 tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
404                                 if(tempc>255) rt[1]= 255; else rt[1]= tempc;
405                                 tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
406                                 if(tempc>255) rt[2]= 255; else rt[2]= tempc;
407                                 tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
408                                 if(tempc>255) rt[3]= 255; else rt[3]= tempc;
409                         }
410                         rt1+= 4; rt2+= 4; rt+= 4;
411                 }
412         }
413 }
414
415 static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, 
416                                       float * rect1, float *rect2, float *out)
417 {
418         float fac2, mfac, fac, fac4;
419         int xo;
420         float *rt1, *rt2, *rt;
421
422         xo= x;
423         rt1= rect1;
424         rt2= rect2;
425         rt= out;
426
427         fac2= facf0;
428         fac4= facf1;
429
430         while(y--) {
431
432                 x= xo;
433                 while(x--) {
434
435                         /* rt = rt1 over rt2  (alpha from rt1) */
436
437                         fac= fac2;
438                         mfac= 1.0 - (fac2*rt1[3]) ;
439
440                         if(fac <= 0.0) {
441                                 memcpy(rt, rt2, 4 * sizeof(float));
442                         } else if(mfac <=0) {
443                                 memcpy(rt, rt1, 4 * sizeof(float));
444                         } else {
445                                 rt[0] = fac*rt1[0] + mfac*rt2[0];
446                                 rt[1] = fac*rt1[1] + mfac*rt2[1];
447                                 rt[2] = fac*rt1[2] + mfac*rt2[2];
448                                 rt[3] = fac*rt1[3] + mfac*rt2[3];
449                         }
450                         rt1+= 4; rt2+= 4; rt+= 4;
451                 }
452
453                 if(y==0) break;
454                 y--;
455
456                 x= xo;
457                 while(x--) {
458
459                         fac= fac4;
460                         mfac= 1.0 - (fac4*rt1[3]);
461
462                         if(fac <= 0.0) {
463                                 memcpy(rt, rt2, 4 * sizeof(float));
464                         } else if(mfac <= 0.0) {
465                                 memcpy(rt, rt1, 4 * sizeof(float));
466                         } else {
467                                 rt[0] = fac*rt1[0] + mfac*rt2[0];
468                                 rt[1] = fac*rt1[1] + mfac*rt2[1];
469                                 rt[2] = fac*rt1[2] + mfac*rt2[2];
470                                 rt[3] = fac*rt1[3] + mfac*rt2[3];
471                         }
472                         rt1+= 4; rt2+= 4; rt+= 4;
473                 }
474         }
475 }
476
477 static void do_alphaover_effect(Sequence * seq,int cfra,
478                                 float facf0, float facf1, int x, int y, 
479                                 struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
480                                 struct ImBuf *ibuf3, struct ImBuf *out)
481 {
482         if (out->rect_float) {
483                 do_alphaover_effect_float(
484                         facf0, facf1, x, y,
485                         ibuf1->rect_float, ibuf2->rect_float,
486                         out->rect_float);
487         } else {
488                 do_alphaover_effect_byte(
489                         facf0, facf1, x, y,
490                         (char*) ibuf1->rect, (char*) ibuf2->rect,
491                         (char*) out->rect);
492         }
493 }
494
495
496 /* **********************************************************************
497    ALPHA UNDER
498    ********************************************************************** */
499
500 void do_alphaunder_effect_byte(
501         float facf0, float facf1, int x, int y, char *rect1, 
502         char *rect2, char *out)
503 {
504         int fac2, mfac, fac, fac4;
505         int xo;
506         char *rt1, *rt2, *rt;
507
508         xo= x;
509         rt1= rect1;
510         rt2= rect2;
511         rt= out;
512
513         fac2= (int)(256.0*facf0);
514         fac4= (int)(256.0*facf1);
515
516         while(y--) {
517
518                 x= xo;
519                 while(x--) {
520
521                         /* rt = rt1 under rt2  (alpha from rt2) */
522
523                         /* this complex optimalisation is because the
524                          * 'skybuf' can be crossed in
525                          */
526                         if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
527                         else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
528                         else {
529                                 mfac= rt2[3];
530                                 fac= (fac2*(256-mfac))>>8;
531
532                                 if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
533                                 else {
534                                         rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
535                                         rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
536                                         rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
537                                         rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
538                                 }
539                         }
540                         rt1+= 4; rt2+= 4; rt+= 4;
541                 }
542
543                 if(y==0) break;
544                 y--;
545
546                 x= xo;
547                 while(x--) {
548
549                         if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
550                         else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
551                         else {
552                                 mfac= rt2[3];
553                                 fac= (fac4*(256-mfac))>>8;
554
555                                 if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
556                                 else {
557                                         rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
558                                         rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
559                                         rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
560                                         rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
561                                 }
562                         }
563                         rt1+= 4; rt2+= 4; rt+= 4;
564                 }
565         }
566 }
567
568
569 static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, 
570                                        float *rect1, float *rect2, 
571                                        float *out)
572 {
573         float fac2, mfac, fac, fac4;
574         int xo;
575         float *rt1, *rt2, *rt;
576
577         xo= x;
578         rt1= rect1;
579         rt2= rect2;
580         rt= out;
581
582         fac2= facf0;
583         fac4= facf1;
584
585         while(y--) {
586
587                 x= xo;
588                 while(x--) {
589
590                         /* rt = rt1 under rt2  (alpha from rt2) */
591
592                         /* this complex optimalisation is because the
593                          * 'skybuf' can be crossed in
594                          */
595                         if( rt2[3]<=0 && fac2>=1.0) {
596                                 memcpy(rt, rt1, 4 * sizeof(float));
597                         } else if(rt2[3]>=1.0) {
598                                 memcpy(rt, rt2, 4 * sizeof(float));
599                         } else {
600                                 mfac = rt2[3];
601                                 fac = fac2 * (1.0 - mfac);
602
603                                 if(fac == 0) {
604                                         memcpy(rt, rt2, 4 * sizeof(float));
605                                 } else {
606                                         rt[0]= fac*rt1[0] + mfac*rt2[0];
607                                         rt[1]= fac*rt1[1] + mfac*rt2[1];
608                                         rt[2]= fac*rt1[2] + mfac*rt2[2];
609                                         rt[3]= fac*rt1[3] + mfac*rt2[3];
610                                 }
611                         }
612                         rt1+= 4; rt2+= 4; rt+= 4;
613                 }
614
615                 if(y==0) break;
616                 y--;
617
618                 x= xo;
619                 while(x--) {
620
621                         if(rt2[3]<=0 && fac4 >= 1.0) {
622                                 memcpy(rt, rt1, 4 * sizeof(float));
623  
624                         } else if(rt2[3]>=1.0) {
625                                 memcpy(rt, rt2, 4 * sizeof(float));
626                         } else {
627                                 mfac= rt2[3];
628                                 fac= fac4*(1.0-mfac);
629
630                                 if(fac == 0) {
631                                         memcpy(rt, rt2, 4 * sizeof(float));
632                                 } else {
633                                         rt[0]= fac * rt1[0] + mfac * rt2[0];
634                                         rt[1]= fac * rt1[1] + mfac * rt2[1];
635                                         rt[2]= fac * rt1[2] + mfac * rt2[2];
636                                         rt[3]= fac * rt1[3] + mfac * rt2[3];
637                                 }
638                         }
639                         rt1+= 4; rt2+= 4; rt+= 4;
640                 }
641         }
642 }
643
644 static void do_alphaunder_effect(Sequence * seq,int cfra,
645                                 float facf0, float facf1, int x, int y, 
646                                 struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
647                                 struct ImBuf *ibuf3, struct ImBuf *out)
648 {
649         if (out->rect_float) {
650                 do_alphaunder_effect_float(
651                         facf0, facf1, x, y,
652                         ibuf1->rect_float, ibuf2->rect_float,
653                         out->rect_float);
654         } else {
655                 do_alphaunder_effect_byte(
656                         facf0, facf1, x, y,
657                         (char*) ibuf1->rect, (char*) ibuf2->rect,
658                         (char*) out->rect);
659         }
660 }
661
662
663 /* **********************************************************************
664    CROSS
665    ********************************************************************** */
666
667 void do_cross_effect_byte(float facf0, float facf1, int x, int y, 
668                           char *rect1, char *rect2, 
669                           char *out)
670 {
671         int fac1, fac2, fac3, fac4;
672         int xo;
673         char *rt1, *rt2, *rt;
674
675         xo= x;
676         rt1= rect1;
677         rt2= rect2;
678         rt= out;
679
680         fac2= (int)(256.0*facf0);
681         fac1= 256-fac2;
682         fac4= (int)(256.0*facf1);
683         fac3= 256-fac4;
684
685         while(y--) {
686
687                 x= xo;
688                 while(x--) {
689
690                         rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
691                         rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
692                         rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
693                         rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
694
695                         rt1+= 4; rt2+= 4; rt+= 4;
696                 }
697
698                 if(y==0) break;
699                 y--;
700
701                 x= xo;
702                 while(x--) {
703
704                         rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
705                         rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
706                         rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
707                         rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
708
709                         rt1+= 4; rt2+= 4; rt+= 4;
710                 }
711
712         }
713 }
714
715 void do_cross_effect_float(float facf0, float facf1, int x, int y, 
716                            float *rect1, float *rect2, float *out)
717 {
718         float fac1, fac2, fac3, fac4;
719         int xo;
720         float *rt1, *rt2, *rt;
721
722         xo= x;
723         rt1= rect1;
724         rt2= rect2;
725         rt= out;
726
727         fac2= facf0;
728         fac1= 1.0 - fac2;
729         fac4= facf1;
730         fac3= 1.0 - fac4;
731
732         while(y--) {
733
734                 x= xo;
735                 while(x--) {
736
737                         rt[0]= fac1*rt1[0] + fac2*rt2[0];
738                         rt[1]= fac1*rt1[1] + fac2*rt2[1];
739                         rt[2]= fac1*rt1[2] + fac2*rt2[2];
740                         rt[3]= fac1*rt1[3] + fac2*rt2[3];
741
742                         rt1+= 4; rt2+= 4; rt+= 4;
743                 }
744
745                 if(y==0) break;
746                 y--;
747
748                 x= xo;
749                 while(x--) {
750
751                         rt[0]= fac3*rt1[0] + fac4*rt2[0];
752                         rt[1]= fac3*rt1[1] + fac4*rt2[1];
753                         rt[2]= fac3*rt1[2] + fac4*rt2[2];
754                         rt[3]= fac3*rt1[3] + fac4*rt2[3];
755
756                         rt1+= 4; rt2+= 4; rt+= 4;
757                 }
758
759         }
760 }
761
762 /* carefull: also used by speed effect! */
763
764 static void do_cross_effect(Sequence * seq,int cfra,
765                             float facf0, float facf1, int x, int y, 
766                             struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
767                             struct ImBuf *ibuf3, struct ImBuf *out)
768 {
769         if (out->rect_float) {
770                 do_cross_effect_float(
771                         facf0, facf1, x, y,
772                         ibuf1->rect_float, ibuf2->rect_float,
773                         out->rect_float);
774         } else {
775                 do_cross_effect_byte(
776                         facf0, facf1, x, y,
777                         (char*) ibuf1->rect, (char*) ibuf2->rect,
778                         (char*) out->rect);
779         }
780 }
781
782
783 /* **********************************************************************
784    GAMMA CROSS
785    ********************************************************************** */
786
787 /* copied code from initrender.c */
788 static unsigned short *gamtab = 0;
789 static unsigned short *igamtab1 = 0;
790 static int gamma_tabs_refcount = 0;
791
792 #define RE_GAMMA_TABLE_SIZE 400
793
794 static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
795 static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
796 static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
797 static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
798 static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1];
799 static float colour_step;
800 static float inv_colour_step;
801 static float valid_gamma;
802 static float valid_inv_gamma;
803
804 static void makeGammaTables(float gamma)
805 {
806         /* we need two tables: one forward, one backward */
807         int i;
808
809         valid_gamma        = gamma;
810         valid_inv_gamma    = 1.0 / gamma;
811         colour_step        = 1.0 / RE_GAMMA_TABLE_SIZE;
812         inv_colour_step    = (float) RE_GAMMA_TABLE_SIZE; 
813
814         /* We could squeeze out the two range tables to gain some memory.        */     
815         for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
816                 colour_domain_table[i]   = i * colour_step;
817                 gamma_range_table[i]     = pow(colour_domain_table[i],
818                                                                                 valid_gamma);
819                 inv_gamma_range_table[i] = pow(colour_domain_table[i],
820                                                                                 valid_inv_gamma);
821         }
822
823         /* The end of the table should match 1.0 carefully. In order to avoid    */
824         /* rounding errors, we just set this explicitly. The last segment may    */
825         /* have a different lenght than the other segments, but our              */
826         /* interpolation is insensitive to that.                                 */
827         colour_domain_table[RE_GAMMA_TABLE_SIZE]   = 1.0;
828         gamma_range_table[RE_GAMMA_TABLE_SIZE]     = 1.0;
829         inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
830
831         /* To speed up calculations, we make these calc factor tables. They are  */
832         /* multiplication factors used in scaling the interpolation.             */
833         for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
834                 gamfactor_table[i] = inv_colour_step
835                         * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
836                 inv_gamfactor_table[i] = inv_colour_step
837                         * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
838         }
839
840 } /* end of void makeGammaTables(float gamma) */
841
842
843 static float gammaCorrect(float c)
844 {
845         int i;
846         float res = 0.0;
847         
848         i = floor(c * inv_colour_step);
849         /* Clip to range [0,1]: outside, just do the complete calculation.       */
850         /* We may have some performance problems here. Stretching up the LUT     */
851         /* may help solve that, by exchanging LUT size for the interpolation.    */
852         /* Negative colours are explicitly handled.                              */
853         if (i < 0) res = -pow(abs(c), valid_gamma);
854         else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
855         else res = gamma_range_table[i] + 
856                          ( (c - colour_domain_table[i]) * gamfactor_table[i]); 
857         
858         return res;
859 } /* end of float gammaCorrect(float col) */
860
861 /* ------------------------------------------------------------------------- */
862
863 static float invGammaCorrect(float col)
864 {
865         int i;
866         float res = 0.0;
867
868         i = floor(col*inv_colour_step);
869         /* Negative colours are explicitly handled.                              */
870         if (i < 0) res = -pow(abs(col), valid_inv_gamma);
871         else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
872         else res = inv_gamma_range_table[i] + 
873                          ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]);
874                            
875         return res;
876 } /* end of float invGammaCorrect(float col) */
877
878
879 static void gamtabs(float gamma)
880 {
881         float val, igamma= 1.0f/gamma;
882         int a;
883         
884         gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2");
885         igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2");
886
887         /* gamtab: in short, out short */
888         for(a=0; a<65536; a++) {
889                 val= a;
890                 val/= 65535.0;
891                 
892                 if(gamma==2.0) val= sqrt(val);
893                 else if(gamma!=1.0) val= pow(val, igamma);
894                 
895                 gamtab[a]= (65535.99*val);
896         }
897         /* inverse gamtab1 : in byte, out short */
898         for(a=1; a<=256; a++) {
899                 if(gamma==2.0) igamtab1[a-1]= a*a-1;
900                 else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
901                 else {
902                         val= a/256.0;
903                         igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
904                 }
905         }
906
907 }
908
909 static void alloc_or_ref_gammatabs()
910 {
911         if (gamma_tabs_refcount == 0) {
912                 gamtabs(2.0f);
913                 makeGammaTables(2.0f);
914         }
915         gamma_tabs_refcount++;
916 }
917
918 static void init_gammacross(Sequence * seq)
919 {
920         alloc_or_ref_gammatabs();
921 }
922
923 static void load_gammacross(Sequence * seq)
924 {
925         alloc_or_ref_gammatabs();
926 }
927
928 static void free_gammacross(Sequence * seq)
929 {
930         if (--gamma_tabs_refcount == 0) {
931                 MEM_freeN(gamtab);
932                 MEM_freeN(igamtab1);
933                 gamtab = 0;
934                 igamtab1 = 0;
935         }
936         if (gamma_tabs_refcount < 0) {
937                 fprintf(stderr, "seqeffects: free_gammacross double free!\n");
938         }
939 }
940
941 static void do_gammacross_effect_byte(float facf0, float facf1, 
942                                       int x, int y, 
943                                       char *rect1, 
944                                       char *rect2, 
945                                       char *out)
946 {
947         int fac1, fac2, col;
948         int xo;
949         char *rt1, *rt2, *rt;
950         
951         xo= x;
952         rt1= (char *)rect1;
953         rt2= (char *)rect2;
954         rt= (char *)out;
955
956         fac2= (int)(256.0*facf0);
957         fac1= 256-fac2;
958
959         while(y--) {
960
961                 x= xo;
962                 while(x--) {
963
964                         col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
965                         if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
966                         col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
967                         if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
968                         col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
969                         if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
970                         col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
971                         if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
972
973                         rt1+= 4; rt2+= 4; rt+= 4;
974                 }
975
976                 if(y==0) break;
977                 y--;
978
979                 x= xo;
980                 while(x--) {
981
982                         col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
983                         if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
984                         col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
985                         if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
986                         col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
987                         if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
988                         col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
989                         if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
990
991                         rt1+= 4; rt2+= 4; rt+= 4;
992                 }
993         }
994
995 }
996
997 static void do_gammacross_effect_float(float facf0, float facf1, 
998                                        int x, int y, 
999                                        float *rect1, float *rect2, 
1000                                        float *out)
1001 {
1002         float fac1, fac2, col;
1003         int xo;
1004         float *rt1, *rt2, *rt;
1005
1006         xo= x;
1007         rt1= rect1;
1008         rt2= rect2;
1009         rt= out;
1010
1011         fac2= facf0;
1012         fac1= 1.0 - fac2;
1013
1014         while(y--) {
1015
1016                 x= xo * 4;
1017                 while(x--) {
1018
1019                         *rt= gammaCorrect(
1020                                 fac1 * invGammaCorrect(*rt1) 
1021                                 + fac2 * invGammaCorrect(*rt2));
1022                         rt1++; rt2++; rt++;
1023                 }
1024
1025                 if(y==0) break;
1026                 y--;
1027
1028                 x= xo * 4;
1029                 while(x--) {
1030
1031                         col= gammaCorrect(
1032                                 fac1*invGammaCorrect(*rt1) 
1033                                 + fac2*invGammaCorrect(*rt2));
1034
1035                         rt1++; rt2++; rt++;
1036                 }
1037         }
1038 }
1039
1040 static void do_gammacross_effect(Sequence * seq,int cfra,
1041                                  float facf0, float facf1, int x, int y, 
1042                                  struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
1043                                  struct ImBuf *ibuf3, struct ImBuf *out)
1044 {
1045         if (out->rect_float) {
1046                 do_gammacross_effect_float(
1047                         facf0, facf1, x, y,
1048                         ibuf1->rect_float, ibuf2->rect_float,
1049                         out->rect_float);
1050         } else {
1051                 do_gammacross_effect_byte(
1052                         facf0, facf1, x, y,
1053                         (char*) ibuf1->rect, (char*) ibuf2->rect,
1054                         (char*) out->rect);
1055         }
1056 }
1057
1058
1059 /* **********************************************************************
1060    ADD
1061    ********************************************************************** */
1062
1063 static void do_add_effect_byte(float facf0, float facf1, int x, int y, 
1064                                unsigned char *rect1, unsigned char *rect2, 
1065                                unsigned char *out)
1066 {
1067         int col, xo, fac1, fac3;
1068         char *rt1, *rt2, *rt;
1069
1070         xo= x;
1071         rt1= (char *)rect1;
1072         rt2= (char *)rect2;
1073         rt= (char *)out;
1074
1075         fac1= (int)(256.0*facf0);
1076         fac3= (int)(256.0*facf1);
1077
1078         while(y--) {
1079
1080                 x= xo;
1081                 while(x--) {
1082
1083                         col= rt1[0]+ ((fac1*rt2[0])>>8);
1084                         if(col>255) rt[0]= 255; else rt[0]= col;
1085                         col= rt1[1]+ ((fac1*rt2[1])>>8);
1086                         if(col>255) rt[1]= 255; else rt[1]= col;
1087                         col= rt1[2]+ ((fac1*rt2[2])>>8);
1088                         if(col>255) rt[2]= 255; else rt[2]= col;
1089                         col= rt1[3]+ ((fac1*rt2[3])>>8);
1090                         if(col>255) rt[3]= 255; else rt[3]= col;
1091
1092                         rt1+= 4; rt2+= 4; rt+= 4;
1093                 }
1094
1095                 if(y==0) break;
1096                 y--;
1097
1098                 x= xo;
1099                 while(x--) {
1100
1101                         col= rt1[0]+ ((fac3*rt2[0])>>8);
1102                         if(col>255) rt[0]= 255; else rt[0]= col;
1103                         col= rt1[1]+ ((fac3*rt2[1])>>8);
1104                         if(col>255) rt[1]= 255; else rt[1]= col;
1105                         col= rt1[2]+ ((fac3*rt2[2])>>8);
1106                         if(col>255) rt[2]= 255; else rt[2]= col;
1107                         col= rt1[3]+ ((fac3*rt2[3])>>8);
1108                         if(col>255) rt[3]= 255; else rt[3]= col;
1109
1110                         rt1+= 4; rt2+= 4; rt+= 4;
1111                 }
1112         }
1113 }
1114
1115 static void do_add_effect_float(float facf0, float facf1, int x, int y, 
1116                                 float *rect1, float *rect2, 
1117                                 float *out)
1118 {
1119         int xo;
1120         float fac1, fac3;
1121         float *rt1, *rt2, *rt;
1122
1123         xo= x;
1124         rt1= rect1;
1125         rt2= rect2;
1126         rt= out;
1127
1128         fac1= facf0;
1129         fac3= facf1;
1130
1131         while(y--) {
1132
1133                 x= xo * 4;
1134                 while(x--) {
1135                         *rt = *rt1 + fac1 * (*rt2);
1136
1137                         rt1++; rt2++; rt++;
1138                 }
1139
1140                 if(y==0) break;
1141                 y--;
1142
1143                 x= xo * 4;
1144                 while(x--) {
1145                         *rt = *rt1 + fac3 * (*rt2);
1146
1147                         rt1++; rt2++; rt++;
1148                 }
1149         }
1150 }
1151
1152 static void do_add_effect(Sequence * seq,int cfra,
1153                           float facf0, float facf1, int x, int y, 
1154                           struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
1155                           struct ImBuf *ibuf3, struct ImBuf *out)
1156 {
1157         if (out->rect_float) {
1158                 do_add_effect_float(
1159                         facf0, facf1, x, y,
1160                         ibuf1->rect_float, ibuf2->rect_float,
1161                         out->rect_float);
1162         } else {
1163                 do_add_effect_byte(
1164                         facf0, facf1, x, y,
1165                         (char*) ibuf1->rect, (char*) ibuf2->rect,
1166                         (char*) out->rect);
1167         }
1168 }
1169
1170
1171 /* **********************************************************************
1172    SUB
1173    ********************************************************************** */
1174
1175 static void do_sub_effect_byte(float facf0, float facf1, 
1176                                int x, int y, 
1177                                char *rect1, char *rect2, char *out)
1178 {
1179         int col, xo, fac1, fac3;
1180         char *rt1, *rt2, *rt;
1181
1182         xo= x;
1183         rt1= (char *)rect1;
1184         rt2= (char *)rect2;
1185         rt= (char *)out;
1186
1187         fac1= (int)(256.0*facf0);
1188         fac3= (int)(256.0*facf1);
1189
1190         while(y--) {
1191
1192                 x= xo;
1193                 while(x--) {
1194
1195                         col= rt1[0]- ((fac1*rt2[0])>>8);
1196                         if(col<0) rt[0]= 0; else rt[0]= col;
1197                         col= rt1[1]- ((fac1*rt2[1])>>8);
1198                         if(col<0) rt[1]= 0; else rt[1]= col;
1199                         col= rt1[2]- ((fac1*rt2[2])>>8);
1200                         if(col<0) rt[2]= 0; else rt[2]= col;
1201                         col= rt1[3]- ((fac1*rt2[3])>>8);
1202                         if(col<0) rt[3]= 0; else rt[3]= col;
1203
1204                         rt1+= 4; rt2+= 4; rt+= 4;
1205                 }
1206
1207                 if(y==0) break;
1208                 y--;
1209
1210                 x= xo;
1211                 while(x--) {
1212
1213                         col= rt1[0]- ((fac3*rt2[0])>>8);
1214                         if(col<0) rt[0]= 0; else rt[0]= col;
1215                         col= rt1[1]- ((fac3*rt2[1])>>8);
1216                         if(col<0) rt[1]= 0; else rt[1]= col;
1217                         col= rt1[2]- ((fac3*rt2[2])>>8);
1218                         if(col<0) rt[2]= 0; else rt[2]= col;
1219                         col= rt1[3]- ((fac3*rt2[3])>>8);
1220                         if(col<0) rt[3]= 0; else rt[3]= col;
1221
1222                         rt1+= 4; rt2+= 4; rt+= 4;
1223                 }
1224         }
1225 }
1226
1227 static void do_sub_effect_float(float facf0, float facf1, int x, int y, 
1228                                 float *rect1, float *rect2, 
1229                                 float *out)
1230 {
1231         int xo;
1232         float fac1, fac3;
1233         float *rt1, *rt2, *rt;
1234
1235         xo= x;
1236         rt1= rect1;
1237         rt2= rect2;
1238         rt= out;
1239
1240         fac1= facf0;
1241         fac3= facf1;
1242
1243         while(y--) {
1244
1245                 x= xo * 4;
1246                 while(x--) {
1247                         *rt = *rt1 - fac1 * (*rt2);
1248
1249                         rt1++; rt2++; rt++;
1250                 }
1251
1252                 if(y==0) break;
1253                 y--;
1254
1255                 x= xo * 4;
1256                 while(x--) {
1257                         *rt = *rt1 - fac3 * (*rt2);
1258
1259                         rt1++; rt2++; rt++;
1260                 }
1261         }
1262 }
1263
1264 static void do_sub_effect(Sequence * seq,int cfra,
1265                           float facf0, float facf1, int x, int y, 
1266                           struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
1267                           struct ImBuf *ibuf3, struct ImBuf *out)
1268 {
1269         if (out->rect_float) {
1270                 do_sub_effect_float(
1271                         facf0, facf1, x, y,
1272                         ibuf1->rect_float, ibuf2->rect_float,
1273                         out->rect_float);
1274         } else {
1275                 do_sub_effect_byte(
1276                         facf0, facf1, x, y,
1277                         (char*) ibuf1->rect, (char*) ibuf2->rect,
1278                         (char*) out->rect);
1279         }
1280 }
1281
1282 /* **********************************************************************
1283    DROP
1284    ********************************************************************** */
1285
1286 /* Must be > 0 or add precopy, etc to the function */
1287 #define XOFF    8
1288 #define YOFF    8
1289
1290 static void do_drop_effect_byte(float facf0, float facf1, int x, int y, 
1291                                 unsigned char *rect2i, unsigned char *rect1i, 
1292                                 unsigned char *outi)
1293 {
1294         int height, width, temp, fac, fac1, fac2;
1295         char *rt1, *rt2, *out;
1296         int field= 1;
1297
1298         width= x;
1299         height= y;
1300
1301         fac1= (int)(70.0*facf0);
1302         fac2= (int)(70.0*facf1);
1303
1304         rt2= (char*) (rect2i + YOFF*width);
1305         rt1= (char*) rect1i;
1306         out= (char*) outi;
1307         for (y=0; y<height-YOFF; y++) {
1308                 if(field) fac= fac1;
1309                 else fac= fac2;
1310                 field= !field;
1311
1312                 memcpy(out, rt1, sizeof(int)*XOFF);
1313                 rt1+= XOFF*4;
1314                 out+= XOFF*4;
1315
1316                 for (x=XOFF; x<width; x++) {
1317                         temp= ((fac*rt2[3])>>8);
1318
1319                         *(out++)= MAX2(0, *rt1 - temp); rt1++;
1320                         *(out++)= MAX2(0, *rt1 - temp); rt1++;
1321                         *(out++)= MAX2(0, *rt1 - temp); rt1++;
1322                         *(out++)= MAX2(0, *rt1 - temp); rt1++;
1323                         rt2+=4;
1324                 }
1325                 rt2+=XOFF*4;
1326         }
1327         memcpy(out, rt1, sizeof(int)*YOFF*width);
1328 }
1329
1330 static void do_drop_effect_float(float facf0, float facf1, int x, int y, 
1331                                  float *rect2i, float *rect1i, 
1332                                  float *outi)
1333 {
1334         int height, width;
1335         float temp, fac, fac1, fac2;
1336         float *rt1, *rt2, *out;
1337         int field= 1;
1338
1339         width= x;
1340         height= y;
1341
1342         fac1= 70.0*facf0;
1343         fac2= 70.0*facf1;
1344
1345         rt2=  (rect2i + YOFF*width);
1346         rt1=  rect1i;
1347         out=  outi;
1348         for (y=0; y<height-YOFF; y++) {
1349                 if(field) fac= fac1;
1350                 else fac= fac2;
1351                 field= !field;
1352
1353                 memcpy(out, rt1, 4 * sizeof(float)*XOFF);
1354                 rt1+= XOFF*4;
1355                 out+= XOFF*4;
1356
1357                 for (x=XOFF; x<width; x++) {
1358                         temp= fac * rt2[3];
1359
1360                         *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
1361                         *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
1362                         *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
1363                         *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
1364                         rt2+=4;
1365                 }
1366                 rt2+=XOFF*4;
1367         }
1368         memcpy(out, rt1, 4 * sizeof(float)*YOFF*width);
1369 }
1370
1371
1372 static void do_drop_effect(Sequence * seq,int cfra,
1373                            float facf0, float facf1, int x, int y, 
1374                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
1375                            struct ImBuf * ibuf3,
1376                            struct ImBuf *out)
1377 {
1378         if (out->rect_float) {
1379                 do_drop_effect_float(
1380                         facf0, facf1, x, y,
1381                         ibuf1->rect_float, ibuf2->rect_float,
1382                         out->rect_float);
1383         } else {
1384                 do_drop_effect_byte(
1385                         facf0, facf1, x, y,
1386                         (char*) ibuf1->rect, (char*) ibuf2->rect,
1387                         (char*) out->rect);
1388         }
1389 }
1390
1391 /* **********************************************************************
1392    MUL
1393    ********************************************************************** */
1394
1395 static void do_mul_effect_byte(float facf0, float facf1, int x, int y, 
1396                                unsigned char *rect1, unsigned char *rect2, 
1397                                unsigned char *out)
1398 {
1399         int  xo, fac1, fac3;
1400         char *rt1, *rt2, *rt;
1401
1402         xo= x;
1403         rt1= (char *)rect1;
1404         rt2= (char *)rect2;
1405         rt= (char *)out;
1406
1407         fac1= (int)(256.0*facf0);
1408         fac3= (int)(256.0*facf1);
1409
1410         /* formula:
1411          *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+axaux= c*px + py*s ;//+centx
1412                         yaux= -s*px + c*py;//+centy
1413          */
1414
1415         while(y--) {
1416
1417                 x= xo;
1418                 while(x--) {
1419
1420                         rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
1421                         rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
1422                         rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
1423                         rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
1424
1425                         rt1+= 4; rt2+= 4; rt+= 4;
1426                 }
1427
1428                 if(y==0) break;
1429                 y--;
1430
1431                 x= xo;
1432                 while(x--) {
1433
1434                         rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
1435                         rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
1436                         rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
1437                         rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
1438
1439                         rt1+= 4; rt2+= 4; rt+= 4;
1440                 }
1441         }
1442 }
1443
1444 static void do_mul_effect_float(float facf0, float facf1, int x, int y, 
1445                                 float *rect1, float *rect2, 
1446                                 float *out)
1447 {
1448         int  xo;
1449         float fac1, fac3;
1450         float *rt1, *rt2, *rt;
1451
1452         xo= x;
1453         rt1= rect1;
1454         rt2= rect2;
1455         rt= out;
1456
1457         fac1= facf0;
1458         fac3= facf1;
1459
1460         /* formula:
1461          *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+a
1462          */
1463
1464         while(y--) {
1465
1466                 x= xo;
1467                 while(x--) {
1468
1469                         rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0);
1470                         rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0);
1471                         rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0);
1472                         rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0);
1473
1474                         rt1+= 4; rt2+= 4; rt+= 4;
1475                 }
1476
1477                 if(y==0) break;
1478                 y--;
1479
1480                 x= xo;
1481                 while(x--) {
1482
1483                         rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0);
1484                         rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0);
1485                         rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0);
1486                         rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0);
1487
1488                         rt1+= 4; rt2+= 4; rt+= 4;
1489                 }
1490         }
1491 }
1492
1493 static void do_mul_effect(Sequence * seq,int cfra,
1494                           float facf0, float facf1, int x, int y, 
1495                           struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
1496                           struct ImBuf *ibuf3, struct ImBuf *out)
1497 {
1498         if (out->rect_float) {
1499                 do_mul_effect_float(
1500                         facf0, facf1, x, y,
1501                         ibuf1->rect_float, ibuf2->rect_float,
1502                         out->rect_float);
1503         } else {
1504                 do_mul_effect_byte(
1505                         facf0, facf1, x, y,
1506                         (char*) ibuf1->rect, (char*) ibuf2->rect,
1507                         (char*) out->rect);
1508         }
1509 }
1510
1511 /* **********************************************************************
1512    WIPE
1513    ********************************************************************** */
1514
1515 // This function calculates the blur band for the wipe effects
1516 static float in_band(float width,float dist, float perc,int side,int dir){
1517         
1518         float t1,t2,alpha,percwidth;
1519         if(width == 0)
1520                 return (float)side;
1521         if(side == 1)
1522                 percwidth = width * perc;
1523         else
1524                 percwidth = width * (1 - perc);
1525         
1526         if(width < dist)
1527                 return side;
1528         
1529         t1 = dist / width;  //percentange of width that is
1530         t2 = 1 / width;  //amount of alpha per % point
1531         
1532         if(side == 1)
1533                 alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe
1534         else
1535                 alpha = (1-perc) - (t1*t2*100);
1536         
1537         if(dir == 0)
1538                 alpha = 1-alpha;
1539         return alpha;
1540 }
1541
1542 static float check_zone(int x, int y, int xo, int yo, 
1543                         Sequence *seq, float facf0) 
1544 {
1545    float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
1546    /*some future stuff
1547    float hyp3,hyp4,b4,b5           
1548    */
1549    float temp1,temp2,temp3,temp4; //some placeholder variables
1550    float halfx = xo/2;
1551    float halfy = yo/2;
1552    float widthf,output=0;
1553    WipeVars *wipe = (WipeVars *)seq->effectdata;
1554    int width;
1555
1556         angle = wipe->angle;
1557         if(angle < 0){
1558                 x = xo-x;
1559                 //y = yo-y
1560                 }
1561         angle = pow(fabs(angle)/45,log(xo)/log(2));
1562
1563         posy = facf0 * yo;
1564         if(wipe->forward){
1565                 posx = facf0 * xo;
1566                 posy = facf0 * yo;
1567         } else{
1568                 posx = xo - facf0 * xo;
1569                 posy = yo - facf0 * yo;
1570         }
1571    switch (wipe->wipetype) {
1572        case DO_SINGLE_WIPE:
1573          width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
1574          hwidth = (float)width/2.0;       
1575                 
1576          if (angle == 0.0)angle = 0.000001;
1577          b1 = posy - (-angle)*posx;
1578          b2 = y - (-angle)*x;
1579          hyp  = fabs(angle*x+y+(-posy-angle*posx))/sqrt(angle*angle+1);
1580          if(angle < 0){
1581                  temp1 = b1;
1582                  b1 = b2;
1583                  b2 = temp1;
1584          }
1585          if(wipe->forward){      
1586                      if(b1 < b2)
1587                                 output = in_band(width,hyp,facf0,1,1);
1588                  else
1589                                 output = in_band(width,hyp,facf0,0,1);
1590                  }
1591                  else{   
1592                  if(b1 < b2)
1593                                 output = in_band(width,hyp,facf0,0,1);
1594                  else
1595                                 output = in_band(width,hyp,facf0,1,1);
1596                  }
1597                  break;
1598          
1599          
1600           case DO_DOUBLE_WIPE:
1601                  if(!wipe->forward)facf0 = 1-facf0;   // Go the other direction
1602
1603              width = (int)(wipe->edgeWidth*((xo+yo)/2.0));  // calculate the blur width
1604              hwidth = (float)width/2.0;       
1605              if (angle == 0)angle = 0.000001;
1606              b1 = posy/2 - (-angle)*posx/2;
1607              b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
1608              b2 = y - (-angle)*x;
1609
1610              hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
1611              hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
1612              
1613              temp1 = xo*(1-facf0/2)-xo*facf0/2;
1614              temp2 = yo*(1-facf0/2)-yo*facf0/2;
1615                  pointdist = sqrt(temp1*temp1 + temp2*temp2);
1616
1617                          if(b2 < b1 && b2 < b3 ){
1618                                 if(hwidth < pointdist)
1619                                         output = in_band(hwidth,hyp,facf0,0,1);
1620                         }
1621                          else if(b2 > b1 && b2 > b3 ){
1622                                 if(hwidth < pointdist)
1623                                         output = in_band(hwidth,hyp2,facf0,0,1);        
1624                         } 
1625                      else{
1626                          if(  hyp < hwidth && hyp2 > hwidth )
1627                                  output = in_band(hwidth,hyp,facf0,1,1);
1628                          else if(  hyp > hwidth && hyp2 < hwidth )
1629                                          output = in_band(hwidth,hyp2,facf0,1,1);
1630                                  else
1631                                          output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
1632                      }
1633                      if(!wipe->forward)output = 1-output;
1634          break;     
1635          case DO_CLOCK_WIPE:
1636                         /*
1637                                 temp1: angle of effect center in rads
1638                                 temp2: angle of line through (halfx,halfy) and (x,y) in rads
1639                                 temp3: angle of low side of blur
1640                                 temp4: angle of high side of blur
1641                         */
1642                         output = 1-facf0;
1643                         widthf = wipe->edgeWidth*2*3.14159;
1644                         temp1 = 2 * 3.14159 * facf0;
1645                         
1646                         if(wipe->forward){
1647                                 temp1 = 2*3.14159-temp1;
1648                         }
1649                         
1650                         x = x - halfx;
1651                         y = y - halfy;
1652
1653                         temp2 = asin(abs(y)/sqrt(x*x + y*y));
1654                         if(x <= 0 && y >= 0)
1655                                 temp2 = 3.14159 - temp2;
1656                         else if(x<=0 && y <= 0)
1657                                 temp2 += 3.14159;
1658                         else if(x >= 0 && y <= 0)
1659                                 temp2 = 2*3.14159 - temp2;
1660                         
1661                         if(wipe->forward){
1662                                 temp3 = temp1-(widthf/2)*facf0;
1663                                 temp4 = temp1+(widthf/2)*(1-facf0);
1664                         }
1665                         else{
1666                                 temp3 = temp1-(widthf/2)*(1-facf0);
1667                                 temp4 = temp1+(widthf/2)*facf0;
1668                         }
1669                         if (temp3 < 0)  temp3 = 0;
1670                         if (temp4 > 2*3.14159) temp4 = 2*3.14159;
1671                         
1672                         
1673                         if(temp2 < temp3)
1674                                 output = 0;
1675                         else if (temp2 > temp4)
1676                                 output = 1;
1677                         else
1678                                 output = (temp2-temp3)/(temp4-temp3);
1679                         if(x == 0 && y == 0){
1680                                 output = 1;
1681                         }
1682                         if(output != output)
1683                                 output = 1;
1684                         if(wipe->forward)
1685                                 output = 1 - output;
1686         break;
1687         /* BOX WIPE IS NOT WORKING YET */
1688      /* case DO_CROSS_WIPE: */
1689         /* BOX WIPE IS NOT WORKING YET */
1690      /* case DO_BOX_WIPE: 
1691                  if(invert)facf0 = 1-facf0;
1692
1693              width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
1694              hwidth = (float)width/2.0;       
1695              if (angle == 0)angle = 0.000001;
1696              b1 = posy/2 - (-angle)*posx/2;
1697              b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
1698              b2 = y - (-angle)*x;
1699
1700              hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
1701              hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
1702              
1703              temp1 = xo*(1-facf0/2)-xo*facf0/2;
1704              temp2 = yo*(1-facf0/2)-yo*facf0/2;
1705                  pointdist = sqrt(temp1*temp1 + temp2*temp2);
1706
1707                          if(b2 < b1 && b2 < b3 ){
1708                                 if(hwidth < pointdist)
1709                                         output = in_band(hwidth,hyp,facf0,0,1);
1710                         }
1711                          else if(b2 > b1 && b2 > b3 ){
1712                                 if(hwidth < pointdist)
1713                                         output = in_band(hwidth,hyp2,facf0,0,1);        
1714                         } 
1715                      else{
1716                          if(  hyp < hwidth && hyp2 > hwidth )
1717                                  output = in_band(hwidth,hyp,facf0,1,1);
1718                          else if(  hyp > hwidth && hyp2 < hwidth )
1719                                          output = in_band(hwidth,hyp2,facf0,1,1);
1720                                  else
1721                                          output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
1722                      }
1723                  if(invert)facf0 = 1-facf0;
1724              angle = -1/angle;
1725              b1 = posy/2 - (-angle)*posx/2;
1726              b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
1727              b2 = y - (-angle)*x;
1728
1729              hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
1730              hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
1731            
1732                  if(b2 < b1 && b2 < b3 ){
1733                                 if(hwidth < pointdist)
1734                                         output *= in_band(hwidth,hyp,facf0,0,1);
1735                         }
1736                          else if(b2 > b1 && b2 > b3 ){
1737                                 if(hwidth < pointdist)
1738                                         output *= in_band(hwidth,hyp2,facf0,0,1);       
1739                         } 
1740                      else{
1741                          if(  hyp < hwidth && hyp2 > hwidth )
1742                                  output *= in_band(hwidth,hyp,facf0,1,1);
1743                          else if(  hyp > hwidth && hyp2 < hwidth )
1744                                          output *= in_band(hwidth,hyp2,facf0,1,1);
1745                                  else
1746                                          output *= in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
1747                      }
1748                      
1749          break;*/
1750       case DO_IRIS_WIPE:
1751          if(xo > yo) yo = xo;
1752          else xo = yo;
1753          
1754                 if(!wipe->forward)
1755                         facf0 = 1-facf0;
1756
1757              width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
1758              hwidth = (float)width/2.0; 
1759              
1760          temp1 = (halfx-(halfx)*facf0);     
1761                  pointdist = sqrt(temp1*temp1 + temp1*temp1);
1762                  
1763                  temp2 = sqrt((halfx-x)*(halfx-x)  +  (halfy-y)*(halfy-y));
1764                  if(temp2 > pointdist)
1765                          output = in_band(hwidth,fabs(temp2-pointdist),facf0,0,1);
1766                  else
1767                          output = in_band(hwidth,fabs(temp2-pointdist),facf0,1,1);
1768                  
1769                 if(!wipe->forward)
1770                         output = 1-output;
1771                         
1772          break;
1773    }
1774    if     (output < 0) output = 0;
1775    else if(output > 1) output = 1;
1776    return output;
1777 }
1778
1779 static void init_wipe_effect(Sequence *seq)
1780 {
1781         if(seq->effectdata)MEM_freeN(seq->effectdata);
1782         seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
1783 }
1784
1785 static int num_inputs_wipe()
1786 {
1787         return 1;
1788 }
1789
1790 static void free_wipe_effect(Sequence *seq)
1791 {
1792         if(seq->effectdata)MEM_freeN(seq->effectdata);
1793         seq->effectdata = 0;
1794 }
1795
1796 static void copy_wipe_effect(Sequence *dst, Sequence *src)
1797 {
1798         dst->effectdata = MEM_dupallocN(src->effectdata);
1799 }
1800
1801 static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, 
1802                                 int x, int y, 
1803                                 unsigned char *rect1, 
1804                                 unsigned char *rect2, unsigned char *out)
1805 {
1806         int xo, yo;
1807         char *rt1, *rt2, *rt;
1808         rt1 = (char *)rect1;
1809         rt2 = (char *)rect2;
1810         rt = (char *)out;
1811
1812         xo = x;
1813         yo = y;
1814         for(y=0;y<yo;y++) {
1815                 for(x=0;x<xo;x++) {
1816                         float check = check_zone(x,y,xo,yo,seq,facf0);
1817                         if (check) {
1818                                 if (rt1) {
1819                                         rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
1820                                         rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
1821                                         rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
1822                                         rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
1823                                 } else {
1824                                         rt[0] = 0;
1825                                         rt[1] = 0;
1826                                         rt[2] = 0;
1827                                         rt[3] = 255;
1828                                 }
1829                         } else {
1830                                 if (rt2) {
1831                                         rt[0] = rt2[0];
1832                                         rt[1] = rt2[1];
1833                                         rt[2] = rt2[2];
1834                                         rt[3] = rt2[3];
1835                                 } else {
1836                                         rt[0] = 0;
1837                                         rt[1] = 0;
1838                                         rt[2] = 0;
1839                                         rt[3] = 255;
1840                                 }
1841                         }
1842
1843                         rt+=4;
1844                         if(rt1 !=NULL){
1845                                 rt1+=4;
1846                         }
1847                         if(rt2 !=NULL){
1848                                 rt2+=4;
1849                         }
1850                 }
1851         }
1852 }
1853
1854 static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, 
1855                                  int x, int y, 
1856                                  float *rect1, 
1857                                  float *rect2, float *out)
1858 {
1859         int xo, yo;
1860         float *rt1, *rt2, *rt;
1861         rt1 = rect1;
1862         rt2 = rect2;
1863         rt = out;
1864
1865         xo = x;
1866         yo = y;
1867         for(y=0;y<yo;y++) {
1868                 for(x=0;x<xo;x++) {
1869                         float check = check_zone(x,y,xo,yo,seq,facf0);
1870                         if (check) {
1871                                 if (rt1) {
1872                                         rt[0] = rt1[0]*check+ rt2[0]*(1-check);
1873                                         rt[1] = rt1[1]*check+ rt2[1]*(1-check);
1874                                         rt[2] = rt1[2]*check+ rt2[2]*(1-check);
1875                                         rt[3] = rt1[3]*check+ rt2[3]*(1-check);
1876                                 } else {
1877                                         rt[0] = 0;
1878                                         rt[1] = 0;
1879                                         rt[2] = 0;
1880                                         rt[3] = 1.0;
1881                                 }
1882                         } else {
1883                                 if (rt2) {
1884                                         rt[0] = rt2[0];
1885                                         rt[1] = rt2[1];
1886                                         rt[2] = rt2[2];
1887                                         rt[3] = rt2[3];
1888                                 } else {
1889                                         rt[0] = 0;
1890                                         rt[1] = 0;
1891                                         rt[2] = 0;
1892                                         rt[3] = 1.0;
1893                                 }
1894                         }
1895
1896                         rt+=4;
1897                         if(rt1 !=NULL){
1898                                 rt1+=4;
1899                         }
1900                         if(rt2 !=NULL){
1901                                 rt2+=4;
1902                         }
1903                 }
1904         }
1905 }
1906
1907 static void do_wipe_effect(Sequence * seq,int cfra,
1908                            float facf0, float facf1, int x, int y, 
1909                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
1910                            struct ImBuf *ibuf3, struct ImBuf *out)
1911 {
1912         if (out->rect_float) {
1913                 do_wipe_effect_float(seq,
1914                                      facf0, facf1, x, y,
1915                                      ibuf1->rect_float, ibuf2->rect_float,
1916                                      out->rect_float);
1917         } else {
1918                 do_wipe_effect_byte(seq,
1919                                     facf0, facf1, x, y,
1920                                     (char*) ibuf1->rect, (char*) ibuf2->rect,
1921                                     (char*) out->rect);
1922         }
1923 }
1924 /* **********************************************************************
1925    TRANSFORM
1926    ********************************************************************** */
1927 static void init_transform_effect(Sequence *seq)
1928 {
1929         TransformVars *scale;
1930
1931         if(seq->effectdata)MEM_freeN(seq->effectdata);
1932         seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars");
1933
1934         scale = (TransformVars *)seq->effectdata;
1935         scale->ScalexIni = 1;
1936         scale->ScaleyIni = 1;
1937         scale->ScalexFin = 1;
1938         scale->ScaleyFin = 1;
1939         
1940         scale->xIni=0;
1941         scale->xFin=0;
1942         scale->yIni=0;
1943         scale->yFin=0;
1944         
1945         scale->rotIni=0;
1946         scale->rotFin=0;
1947         
1948 }
1949
1950 static int num_inputs_transform()
1951 {
1952         return 1;
1953 }
1954
1955 static void free_transform_effect(Sequence *seq)
1956 {
1957         if(seq->effectdata)MEM_freeN(seq->effectdata);
1958         seq->effectdata = 0;
1959 }
1960
1961 static void copy_transform_effect(Sequence *dst, Sequence *src)
1962 {
1963         dst->effectdata = MEM_dupallocN(src->effectdata);
1964 }
1965
1966 /* function assumes out to be zero'ed, only does RGBA */
1967 static void bilinear_interpolation_transform_float(ImBuf *in, float *out, float u, float v)
1968 {
1969         float *row1, *row2, *row3, *row4, a, b;
1970         float a_b, ma_b, a_mb, ma_mb;
1971         float empty[4]= {0.0f, 0.0f, 0.0f, 0.0f};
1972         int y1, y2, x1, x2;
1973
1974         x1= (int)floor(u);
1975         x2= (int)ceil(u);
1976         y1= (int)floor(v);
1977         y2= (int)ceil(v);
1978
1979         /* sample area entirely outside image? */
1980         if(x2<0 || x1>in->x-1 || y2<0 || y1>in->y-1)
1981                 return;
1982         
1983         /* sample including outside of edges of image */
1984         if(x1<0 || y1<0) row1= empty;
1985         else row1= in->rect_float + in->x * y1 * 4 + 4*x1;
1986         
1987         if(x1<0 || y2>in->y-1) row2= empty;
1988         else row2= in->rect_float + in->x * y2 * 4 + 4*x1;
1989         
1990         if(x2>in->x-1 || y1<0) row3= empty;
1991         else row3= in->rect_float + in->x * y1 * 4 + 4*x2;
1992         
1993         if(x2>in->x-1 || y2>in->y-1) row4= empty;
1994         else row4= in->rect_float + in->x * y2 * 4 + 4*x2;
1995         
1996         a= u-floor(u);
1997         b= v-floor(v);
1998         a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
1999         
2000         out[0]= ma_mb*row1[0] + a_mb*row3[0] + ma_b*row2[0]+ a_b*row4[0];
2001         out[1]= ma_mb*row1[1] + a_mb*row3[1] + ma_b*row2[1]+ a_b*row4[1];
2002         out[2]= ma_mb*row1[2] + a_mb*row3[2] + ma_b*row2[2]+ a_b*row4[2];
2003         out[3]= ma_mb*row1[3] + a_mb*row3[3] + ma_b*row2[3]+ a_b*row4[3];
2004 }
2005
2006
2007 static void do_transform_effect_float(Sequence * seq,float facf0, int x, int y, 
2008                            struct ImBuf *ibuf1,float *out)
2009 {
2010         int xo, yo, xi, yi;
2011         float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py;
2012         TransformVars *scale;
2013         
2014         scale = (TransformVars *)seq->effectdata;
2015         xo = x;
2016         yo = y;
2017
2018         /*factor scale*/
2019         factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0;
2020         factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0;
2021
2022         /*Factor translate*/
2023         tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0;
2024         ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0;
2025
2026         /*factor Rotate*/
2027         factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0;
2028         rad = (M_PI * factRot) / 180.0f;
2029         s= sin(rad);
2030         c= cos(rad);
2031
2032         for (yi = 0; yi < yo; yi++) {
2033                 for (xi = 0; xi < xo; xi++) {
2034                         /*tranlate point*/
2035                         px = xi-tx;
2036                         py = yi-ty;
2037
2038                         /*rotate point with center ref*/
2039                         xaux = c*px + py*s ;
2040                         yaux = -s*px + c*py;
2041
2042                         /*scale point with center ref*/
2043                         xs = xaux / factxScale;
2044                         ys = yaux / factyScale;
2045
2046                         /*undo reference center point */
2047                         xs += (xo / 2.0f);
2048                         ys += (yo / 2.0f);
2049
2050                         /*interpolate*/
2051                         bilinear_interpolation_transform_float(ibuf1,out, xs,ys);
2052                         
2053                         out+=4;
2054                 }
2055         }       
2056         
2057 }
2058
2059 /* function assumes out to be zero'ed, only does RGBA */
2060 static void bilinear_interpolation_transform_byte(unsigned char *in, unsigned char *out, float u, float v,int x,int y)
2061 {
2062         float a, b;
2063         float a_b, ma_b, a_mb, ma_mb;
2064         int y1, y2, x1, x2;
2065
2066         int row1R,row1G,row1B,row1A;
2067         int row2R,row2G,row2B,row2A;
2068         int row3R,row3G,row3B,row3A;
2069         int row4R,row4G,row4B,row4A;
2070
2071         x1= (int)floor(u);
2072         x2= (int)ceil(u);
2073         y1= (int)floor(v);
2074         y2= (int)ceil(v);
2075
2076         /* sample area entirely outside image? */
2077         if(x2<0 || x1>x-1 || y2<0 || y1>y-1)
2078                 return;
2079         
2080         /* sample including outside of edges of image */
2081         if(x1<0 || y1<0){
2082                 row1R = 0;
2083                 row1G = 0;
2084                 row1B = 0;
2085                 row1A = 0;
2086         }
2087         else{ 
2088                 row1R= in[x * y1 * 4 + 4 * x1];
2089                 row1G= in[x * y1 * 4 + 4 * x1 + 1];
2090                 row1B= in[x * y1 * 4 + 4 * x1 + 2];
2091                 row1A= in[x * y1 * 4 + 4 * x1 + 3];
2092         }
2093         
2094         if(x1<0 || y2>y-1){
2095                 row2R = 0;
2096                 row2G = 0;
2097                 row2B = 0;
2098                 row2A = 0;
2099         }
2100         else{ 
2101                 row2R= in[x * y2 * 4 + 4 * x1];
2102                 row2G= in[x * y2 * 4 + 4 * x1 + 1];
2103                 row2B= in[x * y2 * 4 + 4 * x1 + 2];
2104                 row2A= in[x * y2 * 4 + 4 * x1 + 3];
2105         }
2106         
2107         if(x2>x-1 || y1<0){
2108                 row3R = 0;
2109                 row3G = 0;
2110                 row3B = 0;
2111                 row3A = 0;
2112         }
2113         else{ 
2114                 row3R= in[x * y1 * 4 + 4 * x2];
2115                 row3G= in[x * y1 * 4 + 4 * x2 + 1];
2116                 row3B= in[x * y1 * 4 + 4 * x2 + 2];
2117                 row3A= in[x * y1 * 4 + 4 * x2 + 3];
2118         }
2119         
2120         if(x2>x-1 || y2>y-1){
2121                 row4R = 0;
2122                 row4G = 0;
2123                 row4B = 0;
2124                 row4A = 0;
2125         }
2126         else{ 
2127                 row4R= in[x * y2 * 4 + 4 * x2];
2128                 row4G= in[x * y2 * 4 + 4 * x2 + 1];
2129                 row4B= in[x * y2 * 4 + 4 * x2 + 2];
2130                 row4A= in[x * y2 * 4 + 4 * x2 + 3];
2131         }
2132         
2133         a= u-floor(u);
2134         b= v-floor(v);
2135         a_b= a*b; ma_b= (1-a)*b; a_mb= a*(1-b); ma_mb= (1-a)*(1-b);
2136         
2137         out[0]= (int)(ma_mb*row1R + a_mb*row3R + ma_b*row2R + a_b*row4R);
2138         out[1]= (int)(ma_mb*row1G + a_mb*row3G + ma_b*row2G + a_b*row4G);
2139         out[2]= (int)(ma_mb*row1B + a_mb*row3B + ma_b*row2B + a_b*row4B);
2140         out[3]= (int)(ma_mb*row1A + a_mb*row3A + ma_b*row2A + a_b*row4A);
2141 }
2142
2143 static void do_transform_effect_byte(Sequence * seq,float facf0, int x, int y, 
2144                           unsigned char *ibuf1,unsigned char *out)
2145 {
2146         int xo, yo, xi, yi;
2147         float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py;
2148         TransformVars *scale;
2149         
2150         scale = (TransformVars *)seq->effectdata;
2151         xo = x;
2152         yo = y;
2153
2154         /*factor scale*/
2155         factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0;
2156         factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0;
2157
2158         /*Factor translate*/
2159         tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0;
2160         ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0;
2161
2162         /*factor Rotate*/
2163         factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0;
2164         rad = (M_PI * factRot) / 180.0f;
2165         s= sin(rad);
2166         c= cos(rad);
2167
2168         for (yi = 0; yi < yo; yi++) {
2169                 for (xi = 0; xi < xo; xi++) {
2170                         /*tranlate point*/
2171                         px = xi-tx;
2172                         py = yi-ty;
2173
2174                         /*rotate point with center ref*/
2175                         xaux = c*px + py*s ;
2176                         yaux = -s*px + c*py;
2177
2178                         /*scale point with center ref*/
2179                         xs = xaux / factxScale;
2180                         ys = yaux / factyScale;
2181
2182                         /*undo reference center point */
2183                         xs += (xo / 2.0f);
2184                         ys += (yo / 2.0f);
2185
2186                         /*interpolate*/
2187                         bilinear_interpolation_transform_byte(ibuf1,out, xs,ys,x,y);
2188                         
2189                         out+=4;
2190                 }
2191         }       
2192
2193 }
2194 static void do_transform_effect(Sequence * seq,int cfra,
2195                            float facf0, float facf1, int x, int y, 
2196                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
2197                            struct ImBuf *ibuf3, struct ImBuf *out)
2198 {
2199         if (out->rect_float) {
2200                 do_transform_effect_float(seq,
2201                         facf0,x, y,
2202                         ibuf1,
2203                         out->rect_float);
2204         } else {
2205                 do_transform_effect_byte(seq,
2206                         facf0,x, y,
2207                         (unsigned char*) ibuf1->rect,
2208                         (unsigned char*) out->rect);
2209         }
2210 }
2211
2212
2213 /* **********************************************************************
2214    GLOW
2215    ********************************************************************** */
2216
2217 static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height,
2218                                  float blur,
2219                                  int quality)
2220 /*      MUUUCCH better than the previous blur. */
2221 /*      We do the blurring in two passes which is a whole lot faster. */
2222 /*      I changed the math arount to implement an actual Gaussian */
2223 /*      distribution. */
2224 /* */
2225 /*      Watch out though, it tends to misbehaven with large blur values on */
2226 /*      a small bitmap.  Avoid avoid avoid. */
2227 /*=============================== */
2228 {
2229         unsigned char*  temp=NULL,*swap;
2230         float   *filter=NULL;
2231         int     x,y,i,fx,fy;
2232         int     index, ix, halfWidth;
2233         float   fval, k, curColor[3], curColor2[3], weight=0;
2234
2235         /*      If we're not really blurring, bail out */
2236         if (blur<=0)
2237                 return;
2238
2239         /*      Allocate memory for the tempmap and the blur filter matrix */
2240         temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
2241         if (!temp)
2242                 return;
2243
2244         /*      Allocate memory for the filter elements */
2245         halfWidth = ((quality+1)*blur);
2246         filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
2247         if (!filter){
2248                 MEM_freeN (temp);
2249                 return;
2250         }
2251
2252         /*      Apparently we're calculating a bell curve */
2253         /*      based on the standard deviation (or radius) */
2254         /*      This code is based on an example */
2255         /*      posted to comp.graphics.algorithms by */
2256         /*      Blancmange (bmange@airdmhor.gen.nz) */
2257
2258         k = -1.0/(2.0*3.14159*blur*blur);
2259         fval=0;
2260         for (ix = 0;ix< halfWidth;ix++){
2261                 weight = (float)exp(k*(ix*ix));
2262                 filter[halfWidth - ix] = weight;
2263                 filter[halfWidth + ix] = weight;
2264         }
2265         filter[0] = weight;
2266
2267         /*      Normalize the array */
2268         fval=0;
2269         for (ix = 0;ix< halfWidth*2;ix++)
2270                 fval+=filter[ix];
2271
2272         for (ix = 0;ix< halfWidth*2;ix++)
2273                 filter[ix]/=fval;
2274
2275         /*      Blur the rows */
2276         for (y=0;y<height;y++){
2277                 /*      Do the left & right strips */
2278                 for (x=0;x<halfWidth;x++){
2279                         index=(x+y*width)*4;
2280                         fx=0;
2281                         curColor[0]=curColor[1]=curColor[2]=0;
2282                         curColor2[0]=curColor2[1]=curColor2[2]=0;
2283
2284                         for (i=x-halfWidth;i<x+halfWidth;i++){
2285                            if ((i>=0)&&(i<width)){
2286                                 curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
2287                                 curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
2288                                 curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
2289
2290                                 curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
2291                                    filter[fx];
2292                                 curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
2293                                    filter[fx];
2294                                 curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
2295                                    filter[fx];
2296                                 }
2297                                 fx++;
2298                         }
2299                         temp[index+GlowR]=curColor[0];
2300                         temp[index+GlowG]=curColor[1];
2301                         temp[index+GlowB]=curColor[2];
2302
2303                         temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
2304                         temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
2305                         temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
2306
2307                 }
2308                 /*      Do the main body */
2309                 for (x=halfWidth;x<width-halfWidth;x++){
2310                         index=(x+y*width)*4;
2311                         fx=0;
2312                         curColor[0]=curColor[1]=curColor[2]=0;
2313                         for (i=x-halfWidth;i<x+halfWidth;i++){
2314                                 curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
2315                                 curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
2316                                 curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
2317                                 fx++;
2318                         }
2319                         temp[index+GlowR]=curColor[0];
2320                         temp[index+GlowG]=curColor[1];
2321                         temp[index+GlowB]=curColor[2];
2322                 }
2323         }
2324
2325         /*      Swap buffers */
2326         swap=temp;temp=map;map=swap;
2327
2328
2329         /*      Blur the columns */
2330         for (x=0;x<width;x++){
2331                 /*      Do the top & bottom strips */
2332                 for (y=0;y<halfWidth;y++){
2333                         index=(x+y*width)*4;
2334                         fy=0;
2335                         curColor[0]=curColor[1]=curColor[2]=0;
2336                         curColor2[0]=curColor2[1]=curColor2[2]=0;
2337                         for (i=y-halfWidth;i<y+halfWidth;i++){
2338                                 if ((i>=0)&&(i<height)){
2339                                    /*   Bottom */
2340                                    curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
2341                                    curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
2342                                    curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
2343
2344                                    /*   Top */
2345                                    curColor2[0]+=map[(x+(height-1-i)*width) *
2346                                       4+GlowR]*filter[fy];
2347                                    curColor2[1]+=map[(x+(height-1-i)*width) *
2348                                       4+GlowG]*filter[fy];
2349                                    curColor2[2]+=map[(x+(height-1-i)*width) *
2350                                       4+GlowB]*filter[fy];
2351                                 }
2352                                 fy++;
2353                         }
2354                         temp[index+GlowR]=curColor[0];
2355                         temp[index+GlowG]=curColor[1];
2356                         temp[index+GlowB]=curColor[2];
2357                         temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
2358                         temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
2359                         temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
2360                 }
2361                 /*      Do the main body */
2362                 for (y=halfWidth;y<height-halfWidth;y++){
2363                         index=(x+y*width)*4;
2364                         fy=0;
2365                         curColor[0]=curColor[1]=curColor[2]=0;
2366                         for (i=y-halfWidth;i<y+halfWidth;i++){
2367                                 curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
2368                                 curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
2369                                 curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
2370                                 fy++;
2371                         }
2372                         temp[index+GlowR]=curColor[0];
2373                         temp[index+GlowG]=curColor[1];
2374                         temp[index+GlowB]=curColor[2];
2375                 }
2376         }
2377
2378
2379         /*      Swap buffers */
2380         swap=temp;temp=map;map=swap;
2381
2382         /*      Tidy up  */
2383         MEM_freeN (filter);
2384         MEM_freeN (temp);
2385 }
2386
2387 static void RVBlurBitmap2_float ( float* map, int width,int height,
2388                                   float blur,
2389                                   int quality)
2390 /*      MUUUCCH better than the previous blur. */
2391 /*      We do the blurring in two passes which is a whole lot faster. */
2392 /*      I changed the math arount to implement an actual Gaussian */
2393 /*      distribution. */
2394 /* */
2395 /*      Watch out though, it tends to misbehaven with large blur values on */
2396 /*      a small bitmap.  Avoid avoid avoid. */
2397 /*=============================== */
2398 {
2399         float*  temp=NULL,*swap;
2400         float   *filter=NULL;
2401         int     x,y,i,fx,fy;
2402         int     index, ix, halfWidth;
2403         float   fval, k, curColor[3], curColor2[3], weight=0;
2404
2405         /*      If we're not really blurring, bail out */
2406         if (blur<=0)
2407                 return;
2408
2409         /*      Allocate memory for the tempmap and the blur filter matrix */
2410         temp= MEM_mallocN( (width*height*4*sizeof(float)), "blurbitmaptemp");
2411         if (!temp)
2412                 return;
2413
2414         /*      Allocate memory for the filter elements */
2415         halfWidth = ((quality+1)*blur);
2416         filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
2417         if (!filter){
2418                 MEM_freeN (temp);
2419                 return;
2420         }
2421
2422         /*      Apparently we're calculating a bell curve */
2423         /*      based on the standard deviation (or radius) */
2424         /*      This code is based on an example */
2425         /*      posted to comp.graphics.algorithms by */
2426         /*      Blancmange (bmange@airdmhor.gen.nz) */
2427
2428         k = -1.0/(2.0*3.14159*blur*blur);
2429         fval=0;
2430         for (ix = 0;ix< halfWidth;ix++){
2431                 weight = (float)exp(k*(ix*ix));
2432                 filter[halfWidth - ix] = weight;
2433                 filter[halfWidth + ix] = weight;
2434         }
2435         filter[0] = weight;
2436
2437         /*      Normalize the array */
2438         fval=0;
2439         for (ix = 0;ix< halfWidth*2;ix++)
2440                 fval+=filter[ix];
2441
2442         for (ix = 0;ix< halfWidth*2;ix++)
2443                 filter[ix]/=fval;
2444
2445         /*      Blur the rows */
2446         for (y=0;y<height;y++){
2447                 /*      Do the left & right strips */
2448                 for (x=0;x<halfWidth;x++){
2449                         index=(x+y*width)*4;
2450                         fx=0;
2451                         curColor[0]=curColor[1]=curColor[2]=0.0f;
2452                         curColor2[0]=curColor2[1]=curColor2[2]=0.0f;
2453
2454                         for (i=x-halfWidth;i<x+halfWidth;i++){
2455                            if ((i>=0)&&(i<width)){
2456                                 curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
2457                                 curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
2458                                 curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
2459
2460                                 curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
2461                                    filter[fx];
2462                                 curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
2463                                    filter[fx];
2464                                 curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
2465                                    filter[fx];
2466                                 }
2467                                 fx++;
2468                         }
2469                         temp[index+GlowR]=curColor[0];
2470                         temp[index+GlowG]=curColor[1];
2471                         temp[index+GlowB]=curColor[2];
2472
2473                         temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
2474                         temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
2475                         temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
2476
2477                 }
2478                 /*      Do the main body */
2479                 for (x=halfWidth;x<width-halfWidth;x++){
2480                         index=(x+y*width)*4;
2481                         fx=0;
2482                         curColor[0]=curColor[1]=curColor[2]=0;
2483                         for (i=x-halfWidth;i<x+halfWidth;i++){
2484                                 curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
2485                                 curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
2486                                 curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
2487                                 fx++;
2488                         }
2489                         temp[index+GlowR]=curColor[0];
2490                         temp[index+GlowG]=curColor[1];
2491                         temp[index+GlowB]=curColor[2];
2492                 }
2493         }
2494
2495         /*      Swap buffers */
2496         swap=temp;temp=map;map=swap;
2497
2498
2499         /*      Blur the columns */
2500         for (x=0;x<width;x++){
2501                 /*      Do the top & bottom strips */
2502                 for (y=0;y<halfWidth;y++){
2503                         index=(x+y*width)*4;
2504                         fy=0;
2505                         curColor[0]=curColor[1]=curColor[2]=0;
2506                         curColor2[0]=curColor2[1]=curColor2[2]=0;
2507                         for (i=y-halfWidth;i<y+halfWidth;i++){
2508                                 if ((i>=0)&&(i<height)){
2509                                    /*   Bottom */
2510                                    curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
2511                                    curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
2512                                    curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
2513
2514                                    /*   Top */
2515                                    curColor2[0]+=map[(x+(height-1-i)*width) *
2516                                       4+GlowR]*filter[fy];
2517                                    curColor2[1]+=map[(x+(height-1-i)*width) *
2518                                       4+GlowG]*filter[fy];
2519                                    curColor2[2]+=map[(x+(height-1-i)*width) *
2520                                       4+GlowB]*filter[fy];
2521                                 }
2522                                 fy++;
2523                         }
2524                         temp[index+GlowR]=curColor[0];
2525                         temp[index+GlowG]=curColor[1];
2526                         temp[index+GlowB]=curColor[2];
2527                         temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
2528                         temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
2529                         temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
2530                 }
2531                 /*      Do the main body */
2532                 for (y=halfWidth;y<height-halfWidth;y++){
2533                         index=(x+y*width)*4;
2534                         fy=0;
2535                         curColor[0]=curColor[1]=curColor[2]=0;
2536                         for (i=y-halfWidth;i<y+halfWidth;i++){
2537                                 curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
2538                                 curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
2539                                 curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
2540                                 fy++;
2541                         }
2542                         temp[index+GlowR]=curColor[0];
2543                         temp[index+GlowG]=curColor[1];
2544                         temp[index+GlowB]=curColor[2];
2545                 }
2546         }
2547
2548
2549         /*      Swap buffers */
2550         swap=temp;temp=map;map=swap;
2551
2552         /*      Tidy up  */
2553         MEM_freeN (filter);
2554         MEM_freeN (temp);
2555 }
2556
2557
2558 /*      Adds two bitmaps and puts the results into a third map. */
2559 /*      C must have been previously allocated but it may be A or B. */
2560 /*      We clamp values to 255 to prevent weirdness */
2561 /*=============================== */
2562 static void RVAddBitmaps_byte (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
2563 {
2564         int     x,y,index;
2565
2566         for (y=0;y<height;y++){
2567                 for (x=0;x<width;x++){
2568                         index=(x+y*width)*4;
2569                         c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
2570                         c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
2571                         c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
2572                         c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
2573                 }
2574         }
2575 }
2576
2577 static void RVAddBitmaps_float (float* a, float* b, float* c, 
2578                                 int width, int height)
2579 {
2580         int     x,y,index;
2581
2582         for (y=0;y<height;y++){
2583                 for (x=0;x<width;x++){
2584                         index=(x+y*width)*4;
2585                         c[index+GlowR]=MIN2(1.0,a[index+GlowR]+b[index+GlowR]);
2586                         c[index+GlowG]=MIN2(1.0,a[index+GlowG]+b[index+GlowG]);
2587                         c[index+GlowB]=MIN2(1.0,a[index+GlowB]+b[index+GlowB]);
2588                         c[index+GlowA]=MIN2(1.0,a[index+GlowA]+b[index+GlowA]);
2589                 }
2590         }
2591 }
2592
2593 /*      For each pixel whose total luminance exceeds the threshold, */
2594 /*      Multiply it's value by BOOST and add it to the output map */
2595 static void RVIsolateHighlights_byte (unsigned char* in, unsigned char* out, 
2596                                       int width, int height, int threshold, 
2597                                       float boost, float clamp)
2598 {
2599         int x,y,index;
2600         int     intensity;
2601
2602
2603         for(y=0;y< height;y++) {
2604                 for (x=0;x< width;x++) {
2605                    index= (x+y*width)*4;
2606
2607                    /*   Isolate the intensity */
2608                    intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
2609                    if (intensity>0){
2610                         out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
2611                         out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
2612                         out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
2613                         out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255);
2614                         }
2615                         else{
2616                                 out[index+GlowR]=0;
2617                                 out[index+GlowG]=0;
2618                                 out[index+GlowB]=0;
2619                                 out[index+GlowA]=0;
2620                         }
2621                 }
2622         }
2623 }
2624
2625 static void RVIsolateHighlights_float (float* in, float* out, 
2626                                       int width, int height, float threshold, 
2627                                       float boost, float clamp)
2628 {
2629         int x,y,index;
2630         float   intensity;
2631
2632
2633         for(y=0;y< height;y++) {
2634                 for (x=0;x< width;x++) {
2635                    index= (x+y*width)*4;
2636
2637                    /*   Isolate the intensity */
2638                    intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
2639                    if (intensity>0){
2640                         out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity));
2641                         out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity));
2642                         out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity));
2643                         out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity));
2644                         }
2645                         else{
2646                                 out[index+GlowR]=0;
2647                                 out[index+GlowG]=0;
2648                                 out[index+GlowB]=0;
2649                                 out[index+GlowA]=0;
2650                         }
2651                 }
2652         }
2653 }
2654
2655 static void init_glow_effect(Sequence *seq)
2656 {
2657         GlowVars *glow;
2658
2659         if(seq->effectdata)MEM_freeN(seq->effectdata);
2660         seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
2661
2662         glow = (GlowVars *)seq->effectdata;
2663         glow->fMini = 0.25;
2664         glow->fClamp = 1.0;
2665         glow->fBoost = 0.5;
2666         glow->dDist = 3.0;
2667         glow->dQuality = 3;
2668         glow->bNoComp = 0;
2669 }
2670
2671 static int num_inputs_glow()
2672 {
2673         return 1;
2674 }
2675
2676 static void free_glow_effect(Sequence *seq)
2677 {
2678         if(seq->effectdata)MEM_freeN(seq->effectdata);
2679         seq->effectdata = 0;
2680 }
2681
2682 static void copy_glow_effect(Sequence *dst, Sequence *src)
2683 {
2684         dst->effectdata = MEM_dupallocN(src->effectdata);
2685 }
2686
2687 //void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
2688 static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, 
2689                                 int x, int y, char *rect1, 
2690                                 char *rect2, char *out)
2691 {
2692         unsigned char *outbuf=(unsigned char *)out;
2693         unsigned char *inbuf=(unsigned char *)rect1;
2694         GlowVars *glow = (GlowVars *)seq->effectdata;
2695
2696         RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp);
2697         RVBlurBitmap2_byte (outbuf, x, y, glow->dDist,glow->dQuality);
2698         if (!glow->bNoComp)
2699                 RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y);
2700 }
2701
2702 static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, 
2703                                  int x, int y, 
2704                                  float *rect1, float *rect2, float *out)
2705 {
2706         float *outbuf = out;
2707         float *inbuf = rect1;
2708         GlowVars *glow = (GlowVars *)seq->effectdata;
2709
2710         RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost, glow->fClamp);
2711         RVBlurBitmap2_float (outbuf, x, y, glow->dDist,glow->dQuality);
2712         if (!glow->bNoComp)
2713                 RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y);
2714 }
2715
2716 static void do_glow_effect(Sequence * seq,int cfra,
2717                            float facf0, float facf1, int x, int y, 
2718                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
2719                            struct ImBuf *ibuf3, struct ImBuf *out)
2720 {
2721         if (out->rect_float) {
2722                 do_glow_effect_float(seq,
2723                                      facf0, facf1, x, y,
2724                                      ibuf1->rect_float, ibuf2->rect_float,
2725                                      out->rect_float);
2726         } else {
2727                 do_glow_effect_byte(seq,
2728                                     facf0, facf1, x, y,
2729                                     (char*) ibuf1->rect, (char*) ibuf2->rect,
2730                                     (char*) out->rect);
2731         }
2732 }
2733
2734 /* **********************************************************************
2735    SOLID COLOR
2736    ********************************************************************** */
2737
2738 static void init_solid_color(Sequence *seq)
2739 {
2740         SolidColorVars *cv;
2741         
2742         if(seq->effectdata)MEM_freeN(seq->effectdata);
2743         seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor");
2744         
2745         cv = (SolidColorVars *)seq->effectdata;
2746         cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
2747 }
2748
2749 static int num_inputs_color()
2750 {
2751         return 0;
2752 }
2753
2754 static void free_solid_color(Sequence *seq)
2755 {
2756         if(seq->effectdata)MEM_freeN(seq->effectdata);
2757         seq->effectdata = 0;
2758 }
2759
2760 static void copy_solid_color(Sequence *dst, Sequence *src)
2761 {
2762         dst->effectdata = MEM_dupallocN(src->effectdata);
2763 }
2764
2765 static int early_out_color(struct Sequence *seq,
2766                            float facf0, float facf1)
2767 {
2768         return -1;
2769 }
2770
2771 static void do_solid_color(Sequence * seq,int cfra,
2772                            float facf0, float facf1, int x, int y, 
2773                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
2774                            struct ImBuf *ibuf3, struct ImBuf *out)
2775 {
2776         SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
2777
2778         unsigned char *rect;
2779         float *rect_float;
2780
2781         if (out->rect) {
2782                 rect = (unsigned char *)out->rect;
2783                 
2784                 for(y=0; y<out->y; y++) {       
2785                         for(x=0; x<out->x; x++, rect+=4) {
2786                                 rect[0]= (char)(cv->col[0]*255);
2787                                 rect[1]= (char)(cv->col[1]*255);
2788                                 rect[2]= (char)(cv->col[2]*255);
2789                                 rect[3]= 255;
2790                         }       
2791                 }
2792         } else if (out->rect_float) {
2793                 rect_float = out->rect_float;
2794                 
2795                 for(y=0; y<out->y; y++) {       
2796                         for(x=0; x<out->x; x++, rect_float+=4) {
2797                                 rect_float[0]= cv->col[0];
2798                                 rect_float[1]= cv->col[1];
2799                                 rect_float[2]= cv->col[2];
2800                                 rect_float[3]= 1.0;
2801                         }
2802                 }
2803         }
2804 }
2805
2806 /* **********************************************************************
2807    SPEED
2808    ********************************************************************** */
2809 static void init_speed_effect(Sequence *seq)
2810 {
2811         SpeedControlVars * v;
2812
2813         if(seq->effectdata) MEM_freeN(seq->effectdata);
2814         seq->effectdata = MEM_callocN(sizeof(struct SpeedControlVars), 
2815                                       "speedcontrolvars");
2816
2817         v = (SpeedControlVars *)seq->effectdata;
2818         v->globalSpeed = 1.0;
2819         v->frameMap = 0;
2820         v->flags = SEQ_SPEED_COMPRESS_IPO_Y;
2821         v->length = 0;
2822 }
2823
2824 static void load_speed_effect(Sequence * seq)
2825 {
2826         SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
2827
2828         v->frameMap = 0;
2829         v->length = 0;
2830 }
2831
2832 static int num_inputs_speed()
2833 {
2834         return 1;
2835 }
2836
2837 static void free_speed_effect(Sequence *seq)
2838 {
2839         SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
2840         if(v->frameMap) MEM_freeN(v->frameMap);
2841         if(seq->effectdata) MEM_freeN(seq->effectdata);
2842         seq->effectdata = 0;
2843 }
2844
2845 static void copy_speed_effect(Sequence *dst, Sequence *src)
2846 {
2847         dst->effectdata = MEM_dupallocN(src->effectdata);
2848 }
2849
2850 static int early_out_speed(struct Sequence *seq,
2851                           float facf0, float facf1)
2852 {
2853         return 1;
2854 }
2855
2856 static void store_icu_yrange_speed(struct Sequence * seq,
2857                                    short adrcode, float * ymin, float * ymax)
2858 {
2859         SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
2860
2861         /* if not already done, load / initialize data */
2862         get_sequence_effect(seq);
2863
2864         if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
2865                 *ymin = -100.0;
2866                 *ymax = 100.0;
2867         } else {
2868                 if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
2869                         *ymin = 0.0;
2870                         *ymax = 1.0;
2871                 } else {
2872                         *ymin = 0.0;
2873                         *ymax = seq->len;
2874                 }
2875         }       
2876 }
2877
2878 void sequence_effect_speed_rebuild_map(struct Sequence * seq, int force)
2879 {
2880         float facf0 = seq->facf0;
2881         float ctime, div;
2882         int cfra;
2883         float fallback_fac;
2884         SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
2885
2886         /* if not already done, load / initialize data */
2887         get_sequence_effect(seq);
2888
2889         if (!(force || seq->len != v->length || !v->frameMap)) {
2890                 return;
2891         }
2892
2893         if (!v->frameMap || v->length != seq->len) {
2894                 if (v->frameMap) MEM_freeN(v->frameMap);
2895
2896                 v->length = seq->len;
2897
2898                 v->frameMap = MEM_callocN(sizeof(float) * v->length, 
2899                                           "speedcontrol frameMap");
2900         }
2901
2902         fallback_fac = 1.0;
2903         
2904         /* if there is no IPO, try to make retiming easy by stretching the
2905            strip */
2906
2907         if (!seq->ipo && seq->seq1 && seq->seq1->enddisp != seq->seq1->start
2908             && seq->seq1->len != 0) {
2909                 fallback_fac = (float) seq->seq1->len / 
2910                         (float) (seq->seq1->enddisp - seq->seq1->start);
2911                 /* FIXME: this strip stretching gets screwed by stripdata
2912                    handling one layer up.
2913                    
2914                    So it currently works by enlarging, never by shrinking!
2915
2916                    (IPOs still work, if used correctly)
2917                 */
2918                 if (fallback_fac > 1.0) {
2919                         fallback_fac = 1.0;
2920                 }
2921         }
2922
2923         if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
2924                 float cursor = 0;
2925
2926                 v->frameMap[0] = 0;
2927
2928                 for (cfra = 1; cfra < v->length; cfra++) {
2929                         if(seq->ipo) {
2930                                 if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
2931                                         ctime = frame_to_float(seq->startdisp
2932                                                                + cfra);
2933                                         div = 1.0;
2934                                 } else {
2935                                         ctime= frame_to_float(cfra);
2936                                         div= v->length / 100.0f;
2937                                         if(div==0.0) return;
2938                                 }
2939                 
2940                                 calc_ipo(seq->ipo, ctime/div);
2941                                 execute_ipo((ID *)seq, seq->ipo);
2942                         } else {
2943                                 seq->facf0 = fallback_fac;
2944                         }
2945                         seq->facf0 *= v->globalSpeed;
2946
2947                         cursor += seq->facf0;
2948
2949                         if (cursor >= v->length) {
2950                                 v->frameMap[cfra] = v->length - 1;
2951                         } else {
2952                                 v->frameMap[cfra] = cursor;
2953                         }
2954                 }
2955         } else {
2956                 for (cfra = 0; cfra < v->length; cfra++) {
2957                         if(seq->ipo) {
2958                                 if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
2959                                         ctime = frame_to_float(seq->startdisp
2960                                                                + cfra);
2961                                         div = 1.0;
2962                                 } else {
2963                                         ctime= frame_to_float(cfra);
2964                                         div= v->length / 100.0f;
2965                                         if(div==0.0) return;
2966                                 }
2967                 
2968                                 calc_ipo(seq->ipo, ctime/div);
2969                                 execute_ipo((ID *)seq, seq->ipo);
2970                         }
2971                         
2972                         if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
2973                                 seq->facf0 *= v->length;
2974                         }
2975                         if (!seq->ipo) {
2976                                 seq->facf0 = (float) cfra * fallback_fac;
2977                         }
2978                         seq->facf0 *= v->globalSpeed;
2979                         if (seq->facf0 >= v->length) {
2980                                 seq->facf0 = v->length - 1;
2981                         }
2982                         v->frameMap[cfra] = seq->facf0;
2983                 }
2984         }
2985         seq->facf0 = facf0;
2986 }
2987
2988 /*
2989   simply reuse do_cross_effect for blending...
2990
2991 static void do_speed_effect(Sequence * seq,int cfra,
2992                            float facf0, float facf1, int x, int y, 
2993                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
2994                            struct ImBuf *ibuf3, struct ImBuf *out)
2995 {
2996
2997 }
2998 */
2999
3000
3001 /* **********************************************************************
3002    sequence effect factory
3003    ********************************************************************** */
3004
3005
3006 static void init_noop(struct Sequence *seq)
3007 {
3008
3009 }
3010
3011 static void load_noop(struct Sequence *seq)
3012 {
3013
3014 }
3015
3016 static void init_plugin_noop(struct Sequence *seq, const char * fname)
3017 {
3018
3019 }
3020
3021 static void free_noop(struct Sequence *seq)
3022 {
3023
3024 }
3025
3026 static int num_inputs_default()
3027 {
3028         return 2;
3029 }
3030
3031 static int early_out_noop(struct Sequence *seq,
3032                           float facf0, float facf1)
3033 {
3034         return 0;
3035 }
3036
3037 static int early_out_fade(struct Sequence *seq,
3038                           float facf0, float facf1)
3039 {
3040         if (facf0 == 0.0 && facf1 == 0.0) {
3041                 return 1;
3042         } else if (facf0 == 1.0 && facf1 == 1.0) {
3043                 return 2;
3044         }
3045         return 0;
3046 }
3047
3048 static int early_out_mul_input2(struct Sequence *seq,
3049                                 float facf0, float facf1)
3050 {
3051         if (facf0 == 0.0 && facf1 == 0.0) {
3052                 return 1;
3053         }
3054         return 0;
3055 }
3056
3057 static void store_icu_yrange_noop(struct Sequence * seq,
3058                                   short adrcode, float * ymin, float * ymax)
3059 {
3060         /* defaults are fine */
3061 }
3062
3063 static void get_default_fac_noop(struct Sequence *seq, int cfra,
3064                                  float * facf0, float * facf1)
3065 {
3066         *facf0 = *facf1 = 1.0;
3067 }
3068
3069 static void get_default_fac_fade(struct Sequence *seq, int cfra,
3070                                  float * facf0, float * facf1)
3071 {
3072         *facf0  = (float)(cfra - seq->startdisp);
3073         *facf1 = (float)(*facf0 + 0.5);
3074         *facf0 /= seq->len;
3075         *facf1 /= seq->len;
3076 }
3077
3078 static void do_overdrop_effect(struct Sequence * seq, int cfra,
3079                                float fac, float facf, 
3080                                int x, int y, struct ImBuf * ibuf1, 
3081                                struct ImBuf * ibuf2, 
3082                                struct ImBuf * ibuf3, 
3083                                struct ImBuf * out)
3084 {
3085         do_drop_effect(seq, cfra, fac, facf, x, y, 
3086                        ibuf1, ibuf2, ibuf3, out);
3087         do_alphaover_effect(seq, cfra, fac, facf, x, y, 
3088                             ibuf1, ibuf2, ibuf3, out);
3089 }
3090
3091 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
3092 {
3093         struct SeqEffectHandle rval;
3094         int sequence_type = seq_type;
3095
3096         rval.init = init_noop;
3097         rval.init_plugin = init_plugin_noop;
3098         rval.num_inputs = num_inputs_default;
3099         rval.load = load_noop;
3100         rval.free = free_noop;
3101         rval.early_out = early_out_noop;
3102         rval.get_default_fac = get_default_fac_noop;
3103         rval.store_icu_yrange = store_icu_yrange_noop;
3104         rval.execute = NULL;
3105         rval.copy = NULL;
3106
3107         switch (sequence_type) {
3108         case SEQ_CROSS:
3109                 rval.execute = do_cross_effect;
3110                 rval.early_out = early_out_fade;
3111                 rval.get_default_fac = get_default_fac_fade;
3112                 break;
3113         case SEQ_GAMCROSS:
3114                 rval.init = init_gammacross;
3115                 rval.load = load_gammacross;
3116                 rval.free = free_gammacross;
3117                 rval.early_out = early_out_fade;
3118                 rval.get_default_fac = get_default_fac_fade;
3119                 rval.execute = do_gammacross_effect;
3120                 break;
3121         case SEQ_ADD:
3122                 rval.execute = do_add_effect;
3123                 rval.early_out = early_out_mul_input2;
3124                 break;
3125         case SEQ_SUB:
3126                 rval.execute = do_sub_effect;
3127                 rval.early_out = early_out_mul_input2;
3128                 break;
3129         case SEQ_MUL:
3130                 rval.execute = do_mul_effect;
3131                 rval.early_out = early_out_mul_input2;
3132                 break;
3133         case SEQ_ALPHAOVER:
3134                 rval.init = init_alpha_over_or_under;
3135                 rval.execute = do_alphaover_effect;
3136                 break;
3137         case SEQ_OVERDROP:
3138                 rval.execute = do_overdrop_effect;
3139                 break;
3140         case SEQ_ALPHAUNDER:
3141                 rval.init = init_alpha_over_or_under;
3142                 rval.execute = do_alphaunder_effect;
3143                 break;
3144         case SEQ_WIPE:
3145                 rval.init = init_wipe_effect;
3146                 rval.num_inputs = num_inputs_wipe;
3147                 rval.free = free_wipe_effect;
3148                 rval.copy = copy_wipe_effect;
3149                 rval.early_out = early_out_fade;
3150                 rval.get_default_fac = get_default_fac_fade;
3151                 rval.execute = do_wipe_effect;
3152                 break;
3153         case SEQ_GLOW:
3154                 rval.init = init_glow_effect;
3155                 rval.num_inputs = num_inputs_glow;
3156                 rval.free = free_glow_effect;
3157                 rval.copy = copy_glow_effect;
3158                 rval.execute = do_glow_effect;
3159                 break;
3160         case SEQ_TRANSFORM:
3161                 rval.init = init_transform_effect;
3162                 rval.num_inputs = num_inputs_transform;
3163                 rval.free = free_transform_effect;
3164                 rval.copy = copy_transform_effect;
3165                 rval.execute = do_transform_effect;
3166                 break;
3167         case SEQ_SPEED:
3168                 rval.init = init_speed_effect;
3169                 rval.num_inputs = num_inputs_speed;
3170                 rval.load = load_speed_effect;
3171                 rval.free = free_speed_effect;
3172                 rval.copy = copy_speed_effect;
3173                 rval.execute = do_cross_effect;
3174                 rval.early_out = early_out_speed;
3175                 rval.store_icu_yrange = store_icu_yrange_speed;
3176                 break;
3177         case SEQ_COLOR:
3178                 rval.init = init_solid_color;
3179                 rval.num_inputs = num_inputs_color;
3180                 rval.early_out = early_out_color;
3181                 rval.free = free_solid_color;
3182                 rval.copy = copy_solid_color;
3183                 rval.execute = do_solid_color;
3184                 break;
3185         case SEQ_PLUGIN:
3186                 rval.init_plugin = init_plugin;
3187                 rval.num_inputs = num_inputs_plugin;
3188                 rval.load = load_plugin;
3189                 rval.free = free_plugin;
3190                 rval.copy = copy_plugin;
3191                 rval.execute = do_plugin_effect;
3192                 rval.early_out = do_plugin_early_out;
3193                 rval.get_default_fac = get_default_fac_fade;
3194                 break;
3195         }
3196
3197         return rval;
3198 }
3199
3200
3201 struct SeqEffectHandle get_sequence_effect(Sequence * seq)
3202 {
3203         struct SeqEffectHandle rval = get_sequence_effect_impl(seq->type);
3204
3205         if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
3206                 rval.load(seq);
3207                 seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
3208         }
3209
3210         return rval;
3211 }
3212
3213 int get_sequence_effect_num_inputs(int seq_type)
3214 {
3215         struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
3216
3217         return rval.num_inputs();
3218 }