Blender V2.61 - r43446

seqeffects.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): 
00022  * - Blender Foundation, 2003-2009
00023  * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 #include <math.h>
00035 #include <stdlib.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 #include "BLI_dynlib.h"
00039 
00040 #include "BLI_math.h" /* windows needs for M_PI */
00041 #include "BLI_utildefines.h"
00042 #include "BLI_string.h"
00043 
00044 #include "DNA_scene_types.h"
00045 #include "DNA_sequence_types.h"
00046 #include "DNA_anim_types.h"
00047 
00048 #include "BKE_fcurve.h"
00049 #include "BKE_main.h"
00050 #include "BKE_plugin_types.h"
00051 #include "BKE_sequencer.h"
00052 #include "BKE_texture.h"
00053 #include "BKE_utildefines.h"
00054 
00055 #include "IMB_imbuf_types.h"
00056 #include "IMB_imbuf.h"
00057 
00058 #include "RNA_access.h"
00059 
00060 /* **** XXX **** */
00061 static void error(const char *UNUSED(error), ...) {}
00062 
00063 #define INT 96
00064 #define FLO 128
00065 
00066 /* **** XXX **** */
00067 
00068 /* Glow effect */
00069 enum {
00070     GlowR=0,
00071     GlowG=1,
00072     GlowB=2,
00073     GlowA=3
00074 };
00075 
00076 static struct ImBuf * prepare_effect_imbufs(
00077     SeqRenderData context,
00078     struct ImBuf *ibuf1, struct ImBuf *ibuf2,
00079     struct ImBuf *ibuf3)
00080 {
00081     struct ImBuf * out;
00082     int x = context.rectx;
00083     int y = context.recty;
00084 
00085     if (!ibuf1 && !ibuf2 && !ibuf3) {
00086         /* hmmm, global float option ? */
00087         out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect);
00088     } else if ((ibuf1 && ibuf1->rect_float) || 
00089            (ibuf2 && ibuf2->rect_float) || 
00090            (ibuf3 && ibuf3->rect_float)) {
00091         /* if any inputs are rectfloat, output is float too */
00092 
00093         out = IMB_allocImBuf((short)x, (short)y, 32, IB_rectfloat);
00094     } else {
00095         out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect);
00096     }
00097     
00098     if (ibuf1 && !ibuf1->rect_float && out->rect_float) {
00099         IMB_float_from_rect_simple(ibuf1);
00100     }
00101     if (ibuf2 && !ibuf2->rect_float && out->rect_float) {
00102         IMB_float_from_rect_simple(ibuf2);
00103     }
00104     if (ibuf3 && !ibuf3->rect_float && out->rect_float) {
00105         IMB_float_from_rect_simple(ibuf3);
00106     }
00107     
00108     if (ibuf1 && !ibuf1->rect && !out->rect_float) {
00109         IMB_rect_from_float(ibuf1);
00110     }
00111     if (ibuf2 && !ibuf2->rect && !out->rect_float) {
00112         IMB_rect_from_float(ibuf2);
00113     }
00114     if (ibuf3 && !ibuf3->rect && !out->rect_float) {
00115         IMB_rect_from_float(ibuf3);
00116     }
00117             
00118     return out;
00119 }
00120 
00121 /* **********************************************************************
00122    PLUGINS
00123    ********************************************************************** */
00124 
00125 static void open_plugin_seq(PluginSeq *pis, const char *seqname)
00126 {
00127     int (*version)(void);
00128     void* (*alloc_private)(void);
00129     char *cp;
00130 
00131     /* to be sure: (is tested for) */
00132     pis->doit= NULL;
00133     pis->pname= NULL;
00134     pis->varstr= NULL;
00135     pis->cfra= NULL;
00136     pis->version= 0;
00137     pis->instance_private_data = NULL;
00138 
00139     /* clear the error list */
00140     BLI_dynlib_get_error_as_string(NULL);
00141 
00142     /* if(pis->handle) BLI_dynlib_close(pis->handle); */
00143     /* pis->handle= 0; */
00144 
00145     /* open the needed object */
00146     pis->handle= BLI_dynlib_open(pis->name);
00147     if(test_dlerr(pis->name, pis->name)) return;
00148 
00149     if (pis->handle != NULL) {
00150         /* find the address of the version function */
00151         version= (int (*)(void))BLI_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
00152         if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
00153 
00154         if (version != NULL) {
00155             pis->version= version();
00156             if (pis->version >= 2 && pis->version <= 6) {
00157                 int (*info_func)(PluginInfo *);
00158                 PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");
00159 
00160                 info_func= (int (*)(PluginInfo *))BLI_dynlib_find_symbol(pis->handle, "plugin_getinfo");
00161 
00162                 if(info_func == NULL) error("No info func");
00163                 else {
00164                     info_func(info);
00165 
00166                     pis->pname= info->name;
00167                     pis->vars= info->nvars;
00168                     pis->cfra= info->cfra;
00169 
00170                     pis->varstr= info->varstr;
00171 
00172                     pis->doit= (void(*)(void))info->seq_doit;
00173                     if (info->init)
00174                         info->init();
00175                 }
00176                 MEM_freeN(info);
00177 
00178                 cp= BLI_dynlib_find_symbol(pis->handle, "seqname");
00179                 if(cp) BLI_strncpy(cp, seqname, SEQ_NAME_MAXSTR);
00180             } else {
00181                 printf ("Plugin returned unrecognized version number\n");
00182                 return;
00183             }
00184         }
00185         alloc_private = (void* (*)(void))BLI_dynlib_find_symbol(
00186             pis->handle, "plugin_seq_alloc_private_data");
00187         if (alloc_private) {
00188             pis->instance_private_data = alloc_private();
00189         }
00190         
00191         pis->current_private_data = (void**) 
00192             BLI_dynlib_find_symbol(
00193                 pis->handle, "plugin_private_data");
00194     }
00195 }
00196 
00197 static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
00198 {
00199     PluginSeq *pis;
00200     VarStruct *varstr;
00201     int a;
00202 
00203     pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
00204 
00205     BLI_strncpy(pis->name, str, FILE_MAX);
00206     open_plugin_seq(pis, seqname);
00207 
00208     if(pis->doit==NULL) {
00209         if(pis->handle==NULL) error("no plugin: %s", str);
00210         else error("in plugin: %s", str);
00211         MEM_freeN(pis);
00212         return NULL;
00213     }
00214 
00215     /* default values */
00216     varstr= pis->varstr;
00217     for(a=0; a<pis->vars; a++, varstr++) {
00218         if( (varstr->type & FLO)==FLO)
00219             pis->data[a]= varstr->def;
00220         else if( (varstr->type & INT)==INT)
00221             *((int *)(pis->data+a))= (int) varstr->def;
00222     }
00223 
00224     return pis;
00225 }
00226 
00227 static void free_plugin_seq(PluginSeq *pis)
00228 {
00229     if(pis==NULL) return;
00230 
00231     /* no BLI_dynlib_close: same plugin can be opened multiple times with 1 handle */
00232 
00233     if (pis->instance_private_data) {
00234         void (*free_private)(void *);
00235 
00236         free_private = (void (*)(void *))BLI_dynlib_find_symbol(
00237             pis->handle, "plugin_seq_free_private_data");
00238         if (free_private) {
00239             free_private(pis->instance_private_data);
00240         }
00241     }
00242 
00243     MEM_freeN(pis);
00244 }
00245 
00246 static void init_plugin(Sequence * seq, const char * fname)
00247 {
00248     seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2);
00249 }
00250 
00251 /* 
00252  * FIXME: should query plugin! Could be generator, that needs zero inputs...
00253  */
00254 static int num_inputs_plugin(void)
00255 {
00256     return 1;
00257 }
00258 
00259 static void load_plugin(Sequence * seq)
00260 {
00261     if (seq) {
00262         open_plugin_seq(seq->plugin, seq->name+2);
00263     }
00264 }
00265 
00266 static void copy_plugin(Sequence * dst, Sequence * src)
00267 {
00268     if(src->plugin) {
00269         dst->plugin= MEM_dupallocN(src->plugin);
00270         open_plugin_seq(dst->plugin, dst->name+2);
00271     }
00272 }
00273 
00274 static ImBuf * IMB_cast_away_list(ImBuf * i)
00275 {
00276     if (!i) {
00277         return NULL;
00278     }
00279     return (ImBuf*) (((void**) i) + 2);
00280 }
00281 
00282 static struct ImBuf * do_plugin_effect(
00283     SeqRenderData context, Sequence *seq, float cfra,
00284     float facf0, float facf1,
00285     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
00286     struct ImBuf *ibuf3)
00287 {
00288     char *cp;
00289     int float_rendering;
00290     int use_temp_bufs = 0; /* Are needed since blur.c (and maybe some other
00291                   old plugins) do very bad stuff
00292                   with imbuf-internals */
00293 
00294     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
00295     int x = context.rectx;
00296     int y = context.recty;
00297 
00298     if(seq->plugin && seq->plugin->doit) {
00299         
00300         if(seq->plugin->cfra) 
00301             *(seq->plugin->cfra)= cfra;
00302         
00303         cp = BLI_dynlib_find_symbol(
00304             seq->plugin->handle, "seqname");
00305 
00306         /* XXX: it's crappy to limit copying buffer by it's lemgth,
00307          *      but assuming plugin stuff is using correct buffer size
00308          *      it should be fine */
00309         if(cp) strncpy(cp, seq->name+2, sizeof(seq->name)-2);
00310 
00311         if (seq->plugin->current_private_data) {
00312             *seq->plugin->current_private_data 
00313                 = seq->plugin->instance_private_data;
00314         }
00315 
00316         float_rendering = (out->rect_float != NULL);
00317 
00318         if (seq->plugin->version<=3 && float_rendering) {
00319             use_temp_bufs = 1;
00320 
00321             if (ibuf1) {
00322                 ibuf1 = IMB_dupImBuf(ibuf1);
00323                 IMB_rect_from_float(ibuf1);
00324                 imb_freerectfloatImBuf(ibuf1);
00325                 ibuf1->flags &= ~IB_rectfloat;
00326             }
00327             if (ibuf2) {
00328                 ibuf2 = IMB_dupImBuf(ibuf2);
00329                 IMB_rect_from_float(ibuf2);
00330                 imb_freerectfloatImBuf(ibuf2);
00331                 ibuf2->flags &= ~IB_rectfloat;
00332             } 
00333             if (ibuf3) {
00334                 ibuf3 = IMB_dupImBuf(ibuf3);
00335                 IMB_rect_from_float(ibuf3);
00336                 imb_freerectfloatImBuf(ibuf3);
00337                 ibuf3->flags &= ~IB_rectfloat;
00338             } 
00339             if (!out->rect) imb_addrectImBuf(out);
00340             imb_freerectfloatImBuf(out);
00341             out->flags &= ~IB_rectfloat;
00342         }
00343 
00344         if (seq->plugin->version<=2) {
00345             if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
00346             if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
00347             if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
00348         }
00349 
00350         if (seq->plugin->version<=4) {
00351             ((SeqDoit)seq->plugin->doit)(
00352                 seq->plugin->data, facf0, facf1, x, y,
00353                 IMB_cast_away_list(ibuf1), 
00354                 IMB_cast_away_list(ibuf2), 
00355                 IMB_cast_away_list(out), 
00356                 IMB_cast_away_list(ibuf3));
00357         } else {
00358             ((SeqDoit)seq->plugin->doit)(
00359                 seq->plugin->data, facf0, facf1, x, y,
00360                 ibuf1, ibuf2, out, ibuf3);
00361         }
00362 
00363         if (seq->plugin->version<=2) {
00364             if (!use_temp_bufs) {
00365                 if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
00366                 if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
00367                 if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
00368             }
00369             IMB_convert_rgba_to_abgr(out);
00370         }
00371         if (seq->plugin->version<=3 && float_rendering) {
00372             IMB_float_from_rect_simple(out);
00373         }
00374 
00375         if (use_temp_bufs) {
00376             if (ibuf1) IMB_freeImBuf(ibuf1);
00377             if (ibuf2) IMB_freeImBuf(ibuf2);
00378             if (ibuf3) IMB_freeImBuf(ibuf3);
00379         }
00380     }
00381     return out;
00382 }
00383 
00384 static int do_plugin_early_out(struct Sequence *UNUSED(seq),
00385                    float UNUSED(facf0), float UNUSED(facf1))
00386 {
00387     return 0;
00388 }
00389 
00390 static void free_plugin(struct Sequence * seq)
00391 {
00392     free_plugin_seq(seq->plugin);
00393     seq->plugin = NULL;
00394 }
00395 
00396 /* **********************************************************************
00397    ALPHA OVER
00398    ********************************************************************** */
00399 
00400 static void init_alpha_over_or_under(Sequence * seq)
00401 {
00402     Sequence * seq1 = seq->seq1;
00403     Sequence * seq2 = seq->seq2;
00404 
00405     seq->seq2= seq1;
00406     seq->seq1= seq2;
00407 }
00408 
00409 static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, 
00410                      char * rect1, char *rect2, char *out)
00411 {
00412     int fac2, mfac, fac, fac4;
00413     int xo, tempc;
00414     char *rt1, *rt2, *rt;
00415 
00416     xo= x;
00417     rt1= (char *)rect1;
00418     rt2= (char *)rect2;
00419     rt= (char *)out;
00420 
00421     fac2= (int)(256.0f*facf0);
00422     fac4= (int)(256.0f*facf1);
00423 
00424     while(y--) {
00425 
00426         x= xo;
00427         while(x--) {
00428 
00429             /* rt = rt1 over rt2  (alpha from rt1) */
00430 
00431             fac= fac2;
00432             mfac= 256 - ( (fac2*rt1[3])>>8 );
00433 
00434             if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
00435             else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
00436             else {
00437                 tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
00438                 if(tempc>255) rt[0]= 255; else rt[0]= tempc;
00439                 tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
00440                 if(tempc>255) rt[1]= 255; else rt[1]= tempc;
00441                 tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
00442                 if(tempc>255) rt[2]= 255; else rt[2]= tempc;
00443                 tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
00444                 if(tempc>255) rt[3]= 255; else rt[3]= tempc;
00445             }
00446             rt1+= 4; rt2+= 4; rt+= 4;
00447         }
00448 
00449         if(y==0) break;
00450         y--;
00451 
00452         x= xo;
00453         while(x--) {
00454 
00455             fac= fac4;
00456             mfac= 256 - ( (fac4*rt1[3])>>8 );
00457 
00458             if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
00459             else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
00460             else {
00461                 tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
00462                 if(tempc>255) rt[0]= 255; else rt[0]= tempc;
00463                 tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
00464                 if(tempc>255) rt[1]= 255; else rt[1]= tempc;
00465                 tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
00466                 if(tempc>255) rt[2]= 255; else rt[2]= tempc;
00467                 tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
00468                 if(tempc>255) rt[3]= 255; else rt[3]= tempc;
00469             }
00470             rt1+= 4; rt2+= 4; rt+= 4;
00471         }
00472     }
00473 }
00474 
00475 static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, 
00476                       float * rect1, float *rect2, float *out)
00477 {
00478     float fac2, mfac, fac, fac4;
00479     int xo;
00480     float *rt1, *rt2, *rt;
00481 
00482     xo= x;
00483     rt1= rect1;
00484     rt2= rect2;
00485     rt= out;
00486 
00487     fac2= facf0;
00488     fac4= facf1;
00489 
00490     while(y--) {
00491 
00492         x= xo;
00493         while(x--) {
00494 
00495             /* rt = rt1 over rt2  (alpha from rt1) */
00496 
00497             fac= fac2;
00498             mfac= 1.0f - (fac2*rt1[3]) ;
00499 
00500             if(fac <= 0.0f) {
00501                 memcpy(rt, rt2, 4 * sizeof(float));
00502             } else if(mfac <=0) {
00503                 memcpy(rt, rt1, 4 * sizeof(float));
00504             } else {
00505                 rt[0] = fac*rt1[0] + mfac*rt2[0];
00506                 rt[1] = fac*rt1[1] + mfac*rt2[1];
00507                 rt[2] = fac*rt1[2] + mfac*rt2[2];
00508                 rt[3] = fac*rt1[3] + mfac*rt2[3];
00509             }
00510             rt1+= 4; rt2+= 4; rt+= 4;
00511         }
00512 
00513         if(y==0) break;
00514         y--;
00515 
00516         x= xo;
00517         while(x--) {
00518 
00519             fac= fac4;
00520             mfac= 1.0f - (fac4*rt1[3]);
00521 
00522             if(fac <= 0.0f) {
00523                 memcpy(rt, rt2, 4 * sizeof(float));
00524             } else if(mfac <= 0.0f) {
00525                 memcpy(rt, rt1, 4 * sizeof(float));
00526             } else {
00527                 rt[0] = fac*rt1[0] + mfac*rt2[0];
00528                 rt[1] = fac*rt1[1] + mfac*rt2[1];
00529                 rt[2] = fac*rt1[2] + mfac*rt2[2];
00530                 rt[3] = fac*rt1[3] + mfac*rt2[3];
00531             }
00532             rt1+= 4; rt2+= 4; rt+= 4;
00533         }
00534     }
00535 }
00536 
00537 static struct ImBuf * do_alphaover_effect(
00538     SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
00539     float facf0, float facf1, 
00540     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
00541     struct ImBuf *ibuf3)
00542 {
00543     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
00544 
00545     if (out->rect_float) {
00546         do_alphaover_effect_float(
00547             facf0, facf1, context.rectx, context.recty,
00548             ibuf1->rect_float, ibuf2->rect_float,
00549             out->rect_float);
00550     } else {
00551         do_alphaover_effect_byte(
00552             facf0, facf1, context.rectx, context.recty,
00553             (char*) ibuf1->rect, (char*) ibuf2->rect,
00554             (char*) out->rect);
00555     }
00556     return out;
00557 }
00558 
00559 
00560 /* **********************************************************************
00561    ALPHA UNDER
00562    ********************************************************************** */
00563 
00564 static void do_alphaunder_effect_byte(
00565     float facf0, float facf1, int x, int y, char *rect1, 
00566     char *rect2, char *out)
00567 {
00568     int fac2, mfac, fac, fac4;
00569     int xo;
00570     char *rt1, *rt2, *rt;
00571 
00572     xo= x;
00573     rt1= rect1;
00574     rt2= rect2;
00575     rt= out;
00576 
00577     fac2= (int)(256.0f*facf0);
00578     fac4= (int)(256.0f*facf1);
00579 
00580     while(y--) {
00581 
00582         x= xo;
00583         while(x--) {
00584 
00585             /* rt = rt1 under rt2  (alpha from rt2) */
00586 
00587             /* this complex optimalisation is because the
00588              * 'skybuf' can be crossed in
00589              */
00590             if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
00591             else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
00592             else {
00593                 mfac= rt2[3];
00594                 fac= (fac2*(256-mfac))>>8;
00595 
00596                 if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
00597                 else {
00598                     rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
00599                     rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
00600                     rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
00601                     rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
00602                 }
00603             }
00604             rt1+= 4; rt2+= 4; rt+= 4;
00605         }
00606 
00607         if(y==0) break;
00608         y--;
00609 
00610         x= xo;
00611         while(x--) {
00612 
00613             if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
00614             else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
00615             else {
00616                 mfac= rt2[3];
00617                 fac= (fac4*(256-mfac))>>8;
00618 
00619                 if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
00620                 else {
00621                     rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
00622                     rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
00623                     rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
00624                     rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
00625                 }
00626             }
00627             rt1+= 4; rt2+= 4; rt+= 4;
00628         }
00629     }
00630 }
00631 
00632 
00633 static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, 
00634                        float *rect1, float *rect2, 
00635                        float *out)
00636 {
00637     float fac2, mfac, fac, fac4;
00638     int xo;
00639     float *rt1, *rt2, *rt;
00640 
00641     xo= x;
00642     rt1= rect1;
00643     rt2= rect2;
00644     rt= out;
00645 
00646     fac2= facf0;
00647     fac4= facf1;
00648 
00649     while(y--) {
00650 
00651         x= xo;
00652         while(x--) {
00653 
00654             /* rt = rt1 under rt2  (alpha from rt2) */
00655 
00656             /* this complex optimalisation is because the
00657              * 'skybuf' can be crossed in
00658              */
00659             if( rt2[3]<=0 && fac2 >= 1.0f) {
00660                 memcpy(rt, rt1, 4 * sizeof(float));
00661             } else if(rt2[3] >= 1.0f) {
00662                 memcpy(rt, rt2, 4 * sizeof(float));
00663             } else {
00664                 mfac = rt2[3];
00665                 fac = fac2 * (1.0f - mfac);
00666 
00667                 if(fac == 0) {
00668                     memcpy(rt, rt2, 4 * sizeof(float));
00669                 } else {
00670                     rt[0]= fac*rt1[0] + mfac*rt2[0];
00671                     rt[1]= fac*rt1[1] + mfac*rt2[1];
00672                     rt[2]= fac*rt1[2] + mfac*rt2[2];
00673                     rt[3]= fac*rt1[3] + mfac*rt2[3];
00674                 }
00675             }
00676             rt1+= 4; rt2+= 4; rt+= 4;
00677         }
00678 
00679         if(y==0) break;
00680         y--;
00681 
00682         x= xo;
00683         while(x--) {
00684 
00685             if(rt2[3]<=0 && fac4 >= 1.0f) {
00686                 memcpy(rt, rt1, 4 * sizeof(float));
00687  
00688             } else if(rt2[3]>=1.0f) {
00689                 memcpy(rt, rt2, 4 * sizeof(float));
00690             } else {
00691                 mfac= rt2[3];
00692                 fac= fac4*(1.0f-mfac);
00693 
00694                 if(fac == 0) {
00695                     memcpy(rt, rt2, 4 * sizeof(float));
00696                 } else {
00697                     rt[0]= fac * rt1[0] + mfac * rt2[0];
00698                     rt[1]= fac * rt1[1] + mfac * rt2[1];
00699                     rt[2]= fac * rt1[2] + mfac * rt2[2];
00700                     rt[3]= fac * rt1[3] + mfac * rt2[3];
00701                 }
00702             }
00703             rt1+= 4; rt2+= 4; rt+= 4;
00704         }
00705     }
00706 }
00707 
00708 static struct ImBuf* do_alphaunder_effect(
00709     SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
00710     float facf0, float facf1, 
00711     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
00712     struct ImBuf *ibuf3)
00713 {
00714     struct ImBuf * out = prepare_effect_imbufs(
00715         context, ibuf1, ibuf2, ibuf3);
00716 
00717     if (out->rect_float) {
00718         do_alphaunder_effect_float(
00719             facf0, facf1, context.rectx, context.recty,
00720             ibuf1->rect_float, ibuf2->rect_float,
00721             out->rect_float);
00722     } else {
00723         do_alphaunder_effect_byte(
00724             facf0, facf1, context.rectx, context.recty,
00725             (char*) ibuf1->rect, (char*) ibuf2->rect,
00726             (char*) out->rect);
00727     }
00728     return out;
00729 }
00730 
00731 
00732 /* **********************************************************************
00733    CROSS
00734    ********************************************************************** */
00735 
00736 static void do_cross_effect_byte(float facf0, float facf1, int x, int y, 
00737               char *rect1, char *rect2, 
00738               char *out)
00739 {
00740     int fac1, fac2, fac3, fac4;
00741     int xo;
00742     char *rt1, *rt2, *rt;
00743 
00744     xo= x;
00745     rt1= rect1;
00746     rt2= rect2;
00747     rt= out;
00748 
00749     fac2= (int)(256.0f*facf0);
00750     fac1= 256-fac2;
00751     fac4= (int)(256.0f*facf1);
00752     fac3= 256-fac4;
00753 
00754     while(y--) {
00755 
00756         x= xo;
00757         while(x--) {
00758 
00759             rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
00760             rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
00761             rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
00762             rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
00763 
00764             rt1+= 4; rt2+= 4; rt+= 4;
00765         }
00766 
00767         if(y==0) break;
00768         y--;
00769 
00770         x= xo;
00771         while(x--) {
00772 
00773             rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
00774             rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
00775             rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
00776             rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
00777 
00778             rt1+= 4; rt2+= 4; rt+= 4;
00779         }
00780 
00781     }
00782 }
00783 
00784 static void do_cross_effect_float(float facf0, float facf1, int x, int y, 
00785                float *rect1, float *rect2, float *out)
00786 {
00787     float fac1, fac2, fac3, fac4;
00788     int xo;
00789     float *rt1, *rt2, *rt;
00790 
00791     xo= x;
00792     rt1= rect1;
00793     rt2= rect2;
00794     rt= out;
00795 
00796     fac2= facf0;
00797     fac1= 1.0f - fac2;
00798     fac4= facf1;
00799     fac3= 1.0f - fac4;
00800 
00801     while(y--) {
00802 
00803         x= xo;
00804         while(x--) {
00805 
00806             rt[0]= fac1*rt1[0] + fac2*rt2[0];
00807             rt[1]= fac1*rt1[1] + fac2*rt2[1];
00808             rt[2]= fac1*rt1[2] + fac2*rt2[2];
00809             rt[3]= fac1*rt1[3] + fac2*rt2[3];
00810 
00811             rt1+= 4; rt2+= 4; rt+= 4;
00812         }
00813 
00814         if(y==0) break;
00815         y--;
00816 
00817         x= xo;
00818         while(x--) {
00819 
00820             rt[0]= fac3*rt1[0] + fac4*rt2[0];
00821             rt[1]= fac3*rt1[1] + fac4*rt2[1];
00822             rt[2]= fac3*rt1[2] + fac4*rt2[2];
00823             rt[3]= fac3*rt1[3] + fac4*rt2[3];
00824 
00825             rt1+= 4; rt2+= 4; rt+= 4;
00826         }
00827 
00828     }
00829 }
00830 
00831 /* careful: also used by speed effect! */
00832 
00833 static struct ImBuf* do_cross_effect(
00834     SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
00835     float facf0, float facf1, 
00836     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
00837     struct ImBuf *ibuf3)
00838 {
00839     struct ImBuf * out = prepare_effect_imbufs(
00840         context, ibuf1, ibuf2, ibuf3);
00841 
00842     if (out->rect_float) {
00843         do_cross_effect_float(
00844             facf0, facf1, context.rectx, context.recty,
00845             ibuf1->rect_float, ibuf2->rect_float,
00846             out->rect_float);
00847     } else {
00848         do_cross_effect_byte(
00849             facf0, facf1, context.rectx, context.recty,
00850             (char*) ibuf1->rect, (char*) ibuf2->rect,
00851             (char*) out->rect);
00852     }
00853     return out;
00854 }
00855 
00856 
00857 /* **********************************************************************
00858    GAMMA CROSS
00859    ********************************************************************** */
00860 
00861 /* copied code from initrender.c */
00862 static unsigned short gamtab[65536];
00863 static unsigned short igamtab1[256];
00864 static int gamma_tabs_init = FALSE;
00865 
00866 #define RE_GAMMA_TABLE_SIZE 400
00867 
00868 static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
00869 static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
00870 static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
00871 static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
00872 static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1]; 
00873 static float color_step;
00874 static float inv_color_step;
00875 static float valid_gamma;
00876 static float valid_inv_gamma;
00877 
00878 static void makeGammaTables(float gamma)
00879 {
00880     /* we need two tables: one forward, one backward */
00881     int i;
00882 
00883     valid_gamma        = gamma;
00884     valid_inv_gamma    = 1.0f / gamma;
00885     color_step        = 1.0f / RE_GAMMA_TABLE_SIZE;
00886     inv_color_step    = (float) RE_GAMMA_TABLE_SIZE; 
00887 
00888     /* We could squeeze out the two range tables to gain some memory.        */ 
00889     for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
00890         color_domain_table[i]   = i * color_step;
00891         gamma_range_table[i]     = pow(color_domain_table[i],
00892                                         valid_gamma);
00893         inv_gamma_range_table[i] = pow(color_domain_table[i],
00894                                         valid_inv_gamma);
00895     }
00896 
00897     /* The end of the table should match 1.0 carefully. In order to avoid    */
00898     /* rounding errors, we just set this explicitly. The last segment may    */
00899     /* have a different length than the other segments, but our              */
00900     /* interpolation is insensitive to that.                                 */
00901     color_domain_table[RE_GAMMA_TABLE_SIZE]   = 1.0;
00902     gamma_range_table[RE_GAMMA_TABLE_SIZE]     = 1.0;
00903     inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
00904 
00905     /* To speed up calculations, we make these calc factor tables. They are  */
00906     /* multiplication factors used in scaling the interpolation.             */
00907     for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
00908         gamfactor_table[i] = inv_color_step
00909             * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
00910         inv_gamfactor_table[i] = inv_color_step
00911             * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
00912     }
00913 
00914 } /* end of void makeGammaTables(float gamma) */
00915 
00916 
00917 static float gammaCorrect(float c)
00918 {
00919     int i;
00920     float res = 0.0;
00921     
00922     i = floor(c * inv_color_step);
00923     /* Clip to range [0,1]: outside, just do the complete calculation.       */
00924     /* We may have some performance problems here. Stretching up the LUT     */
00925     /* may help solve that, by exchanging LUT size for the interpolation.    */
00926     /* Negative colors are explicitly handled.                              */
00927     if (i < 0) res = -pow(abs(c), valid_gamma);
00928     else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
00929     else res = gamma_range_table[i] + 
00930                ( (c - color_domain_table[i]) * gamfactor_table[i]); 
00931     
00932     return res;
00933 } /* end of float gammaCorrect(float col) */
00934 
00935 /* ------------------------------------------------------------------------- */
00936 
00937 static float invGammaCorrect(float col)
00938 {
00939     int i;
00940     float res = 0.0;
00941 
00942     i = floor(col*inv_color_step);
00943     /* Negative colors are explicitly handled.                              */
00944     if (i < 0) res = -pow(abs(col), valid_inv_gamma);
00945     else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
00946     else res = inv_gamma_range_table[i] + 
00947                ( (col - color_domain_table[i]) * inv_gamfactor_table[i]);
00948  
00949     return res;
00950 } /* end of float invGammaCorrect(float col) */
00951 
00952 
00953 static void gamtabs(float gamma)
00954 {
00955     float val, igamma= 1.0f/gamma;
00956     int a;
00957     
00958     /* gamtab: in short, out short */
00959     for(a=0; a<65536; a++) {
00960         val= a;
00961         val/= 65535.0f;
00962         
00963         if(gamma==2.0f) val= sqrt(val);
00964         else if(gamma!=1.0f) val= pow(val, igamma);
00965         
00966         gamtab[a]= (65535.99f*val);
00967     }
00968     /* inverse gamtab1 : in byte, out short */
00969     for(a=1; a<=256; a++) {
00970         if(gamma==2.0f) igamtab1[a-1]= a*a-1;
00971         else if(gamma==1.0f) igamtab1[a-1]= 256*a-1;
00972         else {
00973             val= a/256.0f;
00974             igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
00975         }
00976     }
00977 
00978 }
00979 
00980 static void build_gammatabs(void)
00981 {
00982     if (gamma_tabs_init == FALSE) {
00983         gamtabs(2.0f);
00984         makeGammaTables(2.0f);
00985         gamma_tabs_init = TRUE;
00986     }
00987 }
00988 
00989 static void init_gammacross(Sequence * UNUSED(seq))
00990 {
00991 }
00992 
00993 static void load_gammacross(Sequence * UNUSED(seq))
00994 {
00995 }
00996 
00997 static void free_gammacross(Sequence * UNUSED(seq))
00998 {
00999 }
01000 
01001 static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), 
01002                       int x, int y, 
01003                       unsigned char *rect1, 
01004                       unsigned char *rect2, 
01005                       unsigned char *out)
01006 {
01007     int fac1, fac2, col;
01008     int xo;
01009     unsigned char *rt1, *rt2, *rt;
01010     
01011     xo= x;
01012     rt1= (unsigned char *)rect1;
01013     rt2= (unsigned char *)rect2;
01014     rt= (unsigned char *)out;
01015 
01016     fac2= (int)(256.0f*facf0);
01017     fac1= 256-fac2;
01018 
01019     while(y--) {
01020 
01021         x= xo;
01022         while(x--) {
01023 
01024             col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
01025             if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01026             col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
01027             if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01028             col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
01029             if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01030             col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
01031             if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01032 
01033             rt1+= 4; rt2+= 4; rt+= 4;
01034         }
01035 
01036         if(y==0) break;
01037         y--;
01038 
01039         x= xo;
01040         while(x--) {
01041 
01042             col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
01043             if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01044             col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
01045             if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01046             col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
01047             if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01048             col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
01049             if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
01050 
01051             rt1+= 4; rt2+= 4; rt+= 4;
01052         }
01053     }
01054 
01055 }
01056 
01057 static void do_gammacross_effect_float(float facf0, float UNUSED(facf1), 
01058                        int x, int y, 
01059                        float *rect1, float *rect2, 
01060                        float *out)
01061 {
01062     float fac1, fac2;
01063     int xo;
01064     float *rt1, *rt2, *rt;
01065 
01066     xo= x;
01067     rt1= rect1;
01068     rt2= rect2;
01069     rt= out;
01070 
01071     fac2= facf0;
01072     fac1= 1.0f - fac2;
01073 
01074     while(y--) {
01075 
01076         x= xo * 4;
01077         while(x--) {
01078 
01079             *rt= gammaCorrect(
01080                 fac1 * invGammaCorrect(*rt1) 
01081                 + fac2 * invGammaCorrect(*rt2));
01082             rt1++; rt2++; rt++;
01083         }
01084 
01085         if(y==0) break;
01086         y--;
01087 
01088         x= xo * 4;
01089         while(x--) {
01090 
01091             *rt= gammaCorrect(
01092                 fac1*invGammaCorrect(*rt1) 
01093                 + fac2*invGammaCorrect(*rt2));
01094 
01095             rt1++; rt2++; rt++;
01096         }
01097     }
01098 }
01099 
01100 static struct ImBuf * do_gammacross_effect(
01101     SeqRenderData context,
01102     Sequence *UNUSED(seq), float UNUSED(cfra),
01103     float facf0, float facf1, 
01104     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
01105     struct ImBuf *ibuf3)
01106 {
01107     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
01108 
01109     build_gammatabs();
01110 
01111     if (out->rect_float) {
01112         do_gammacross_effect_float(
01113             facf0, facf1, context.rectx, context.recty,
01114             ibuf1->rect_float, ibuf2->rect_float,
01115             out->rect_float);
01116     } else {
01117         do_gammacross_effect_byte(
01118             facf0, facf1, context.rectx, context.recty,
01119             (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
01120             (unsigned char*) out->rect);
01121     }
01122     return out;
01123 }
01124 
01125 
01126 /* **********************************************************************
01127    ADD
01128    ********************************************************************** */
01129 
01130 static void do_add_effect_byte(float facf0, float facf1, int x, int y, 
01131                    unsigned char *rect1, unsigned char *rect2, 
01132                    unsigned char *out)
01133 {
01134     int col, xo, fac1, fac3;
01135     char *rt1, *rt2, *rt;
01136 
01137     xo= x;
01138     rt1= (char *)rect1;
01139     rt2= (char *)rect2;
01140     rt= (char *)out;
01141 
01142     fac1= (int)(256.0f*facf0);
01143     fac3= (int)(256.0f*facf1);
01144 
01145     while(y--) {
01146 
01147         x= xo;
01148         while(x--) {
01149 
01150             col= rt1[0]+ ((fac1*rt2[0])>>8);
01151             if(col>255) rt[0]= 255; else rt[0]= col;
01152             col= rt1[1]+ ((fac1*rt2[1])>>8);
01153             if(col>255) rt[1]= 255; else rt[1]= col;
01154             col= rt1[2]+ ((fac1*rt2[2])>>8);
01155             if(col>255) rt[2]= 255; else rt[2]= col;
01156             col= rt1[3]+ ((fac1*rt2[3])>>8);
01157             if(col>255) rt[3]= 255; else rt[3]= col;
01158 
01159             rt1+= 4; rt2+= 4; rt+= 4;
01160         }
01161 
01162         if(y==0) break;
01163         y--;
01164 
01165         x= xo;
01166         while(x--) {
01167 
01168             col= rt1[0]+ ((fac3*rt2[0])>>8);
01169             if(col>255) rt[0]= 255; else rt[0]= col;
01170             col= rt1[1]+ ((fac3*rt2[1])>>8);
01171             if(col>255) rt[1]= 255; else rt[1]= col;
01172             col= rt1[2]+ ((fac3*rt2[2])>>8);
01173             if(col>255) rt[2]= 255; else rt[2]= col;
01174             col= rt1[3]+ ((fac3*rt2[3])>>8);
01175             if(col>255) rt[3]= 255; else rt[3]= col;
01176 
01177             rt1+= 4; rt2+= 4; rt+= 4;
01178         }
01179     }
01180 }
01181 
01182 static void do_add_effect_float(float facf0, float facf1, int x, int y, 
01183                 float *rect1, float *rect2, 
01184                 float *out)
01185 {
01186     int xo;
01187     float fac1, fac3;
01188     float *rt1, *rt2, *rt;
01189 
01190     xo= x;
01191     rt1= rect1;
01192     rt2= rect2;
01193     rt= out;
01194 
01195     fac1= facf0;
01196     fac3= facf1;
01197 
01198     while(y--) {
01199 
01200         x= xo * 4;
01201         while(x--) {
01202             *rt = *rt1 + fac1 * (*rt2);
01203 
01204             rt1++; rt2++; rt++;
01205         }
01206 
01207         if(y==0) break;
01208         y--;
01209 
01210         x= xo * 4;
01211         while(x--) {
01212             *rt = *rt1 + fac3 * (*rt2);
01213 
01214             rt1++; rt2++; rt++;
01215         }
01216     }
01217 }
01218 
01219 static struct ImBuf * do_add_effect(SeqRenderData context, 
01220                     Sequence *UNUSED(seq), float UNUSED(cfra),
01221                     float facf0, float facf1,
01222                     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
01223                     struct ImBuf *ibuf3)
01224 {
01225     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
01226 
01227     if (out->rect_float) {
01228         do_add_effect_float(
01229             facf0, facf1, context.rectx, context.recty,
01230             ibuf1->rect_float, ibuf2->rect_float,
01231             out->rect_float);
01232     } else {
01233         do_add_effect_byte(
01234             facf0, facf1, context.rectx, context.recty,
01235             (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
01236             (unsigned char*) out->rect);
01237     }
01238     return out;
01239 }
01240 
01241 
01242 /* **********************************************************************
01243    SUB
01244    ********************************************************************** */
01245 
01246 static void do_sub_effect_byte(float facf0, float facf1, 
01247                    int x, int y, 
01248                    char *rect1, char *rect2, char *out)
01249 {
01250     int col, xo, fac1, fac3;
01251     char *rt1, *rt2, *rt;
01252 
01253     xo= x;
01254     rt1= (char *)rect1;
01255     rt2= (char *)rect2;
01256     rt= (char *)out;
01257 
01258     fac1= (int)(256.0f*facf0);
01259     fac3= (int)(256.0f*facf1);
01260 
01261     while(y--) {
01262 
01263         x= xo;
01264         while(x--) {
01265 
01266             col= rt1[0]- ((fac1*rt2[0])>>8);
01267             if(col<0) rt[0]= 0; else rt[0]= col;
01268             col= rt1[1]- ((fac1*rt2[1])>>8);
01269             if(col<0) rt[1]= 0; else rt[1]= col;
01270             col= rt1[2]- ((fac1*rt2[2])>>8);
01271             if(col<0) rt[2]= 0; else rt[2]= col;
01272             col= rt1[3]- ((fac1*rt2[3])>>8);
01273             if(col<0) rt[3]= 0; else rt[3]= col;
01274 
01275             rt1+= 4; rt2+= 4; rt+= 4;
01276         }
01277 
01278         if(y==0) break;
01279         y--;
01280 
01281         x= xo;
01282         while(x--) {
01283 
01284             col= rt1[0]- ((fac3*rt2[0])>>8);
01285             if(col<0) rt[0]= 0; else rt[0]= col;
01286             col= rt1[1]- ((fac3*rt2[1])>>8);
01287             if(col<0) rt[1]= 0; else rt[1]= col;
01288             col= rt1[2]- ((fac3*rt2[2])>>8);
01289             if(col<0) rt[2]= 0; else rt[2]= col;
01290             col= rt1[3]- ((fac3*rt2[3])>>8);
01291             if(col<0) rt[3]= 0; else rt[3]= col;
01292 
01293             rt1+= 4; rt2+= 4; rt+= 4;
01294         }
01295     }
01296 }
01297 
01298 static void do_sub_effect_float(float facf0, float facf1, int x, int y, 
01299                 float *rect1, float *rect2, 
01300                 float *out)
01301 {
01302     int xo;
01303     float fac1, fac3;
01304     float *rt1, *rt2, *rt;
01305 
01306     xo= x;
01307     rt1= rect1;
01308     rt2= rect2;
01309     rt= out;
01310 
01311     fac1= facf0;
01312     fac3= facf1;
01313 
01314     while(y--) {
01315 
01316         x= xo * 4;
01317         while(x--) {
01318             *rt = *rt1 - fac1 * (*rt2);
01319 
01320             rt1++; rt2++; rt++;
01321         }
01322 
01323         if(y==0) break;
01324         y--;
01325 
01326         x= xo * 4;
01327         while(x--) {
01328             *rt = *rt1 - fac3 * (*rt2);
01329 
01330             rt1++; rt2++; rt++;
01331         }
01332     }
01333 }
01334 
01335 static struct ImBuf * do_sub_effect(
01336     SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
01337     float facf0, float facf1, 
01338     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
01339     struct ImBuf *ibuf3)
01340 {
01341     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
01342 
01343     if (out->rect_float) {
01344         do_sub_effect_float(
01345             facf0, facf1, context.rectx, context.recty,
01346             ibuf1->rect_float, ibuf2->rect_float,
01347             out->rect_float);
01348     } else {
01349         do_sub_effect_byte(
01350             facf0, facf1, context.rectx, context.recty,
01351             (char*) ibuf1->rect, (char*) ibuf2->rect,
01352             (char*) out->rect);
01353     }
01354     return out;
01355 }
01356 
01357 /* **********************************************************************
01358    DROP
01359    ********************************************************************** */
01360 
01361 /* Must be > 0 or add precopy, etc to the function */
01362 #define XOFF    8
01363 #define YOFF    8
01364 
01365 static void do_drop_effect_byte(float facf0, float facf1, int x, int y, 
01366                 char *rect2i, char *rect1i, 
01367                 char *outi)
01368 {
01369     int height, width, temp, fac, fac1, fac2;
01370     char *rt1, *rt2, *out;
01371     int field= 1;
01372 
01373     width= x;
01374     height= y;
01375 
01376     fac1= (int)(70.0f*facf0);
01377     fac2= (int)(70.0f*facf1);
01378 
01379     rt2= (char*) (rect2i + YOFF*width);
01380     rt1= (char*) rect1i;
01381     out= (char*) outi;
01382     for (y=0; y<height-YOFF; y++) {
01383         if(field) fac= fac1;
01384         else fac= fac2;
01385         field= !field;
01386 
01387         memcpy(out, rt1, sizeof(int)*XOFF);
01388         rt1+= XOFF*4;
01389         out+= XOFF*4;
01390 
01391         for (x=XOFF; x<width; x++) {
01392             temp= ((fac*rt2[3])>>8);
01393 
01394             *(out++)= MAX2(0, *rt1 - temp); rt1++;
01395             *(out++)= MAX2(0, *rt1 - temp); rt1++;
01396             *(out++)= MAX2(0, *rt1 - temp); rt1++;
01397             *(out++)= MAX2(0, *rt1 - temp); rt1++;
01398             rt2+=4;
01399         }
01400         rt2+=XOFF*4;
01401     }
01402     memcpy(out, rt1, sizeof(int)*YOFF*width);
01403 }
01404 
01405 static void do_drop_effect_float(float facf0, float facf1, int x, int y, 
01406                  float *rect2i, float *rect1i, 
01407                  float *outi)
01408 {
01409     int height, width;
01410     float temp, fac, fac1, fac2;
01411     float *rt1, *rt2, *out;
01412     int field= 1;
01413 
01414     width= x;
01415     height= y;
01416 
01417     fac1= 70.0f*facf0;
01418     fac2= 70.0f*facf1;
01419 
01420     rt2=  (rect2i + YOFF*width);
01421     rt1=  rect1i;
01422     out=  outi;
01423     for (y=0; y<height-YOFF; y++) {
01424         if(field) fac= fac1;
01425         else fac= fac2;
01426         field= !field;
01427 
01428         memcpy(out, rt1, 4 * sizeof(float)*XOFF);
01429         rt1+= XOFF*4;
01430         out+= XOFF*4;
01431 
01432         for (x=XOFF; x<width; x++) {
01433             temp= fac * rt2[3];
01434 
01435             *(out++)= MAX2(0.0f, *rt1 - temp); rt1++;
01436             *(out++)= MAX2(0.0f, *rt1 - temp); rt1++;
01437             *(out++)= MAX2(0.0f, *rt1 - temp); rt1++;
01438             *(out++)= MAX2(0.0f, *rt1 - temp); rt1++;
01439             rt2+=4;
01440         }
01441         rt2+=XOFF*4;
01442     }
01443     memcpy(out, rt1, 4 * sizeof(float)*YOFF*width);
01444 }
01445 
01446 /* **********************************************************************
01447    MUL
01448    ********************************************************************** */
01449 
01450 static void do_mul_effect_byte(float facf0, float facf1, int x, int y, 
01451                    unsigned char *rect1, unsigned char *rect2, 
01452                    unsigned char *out)
01453 {
01454     int xo, fac1, fac3;
01455     char *rt1, *rt2, *rt;
01456 
01457     xo= x;
01458     rt1= (char *)rect1;
01459     rt2= (char *)rect2;
01460     rt= (char *)out;
01461 
01462     fac1= (int)(256.0f*facf0);
01463     fac3= (int)(256.0f*facf1);
01464 
01465     /* formula:
01466      *      fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+axaux= c*px + py*s ;//+centx
01467             yaux= -s*px + c*py;//+centy
01468      */
01469 
01470     while(y--) {
01471 
01472         x= xo;
01473         while(x--) {
01474 
01475             rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
01476             rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
01477             rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
01478             rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
01479 
01480             rt1+= 4; rt2+= 4; rt+= 4;
01481         }
01482 
01483         if(y==0) break;
01484         y--;
01485 
01486         x= xo;
01487         while(x--) {
01488 
01489             rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
01490             rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
01491             rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
01492             rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
01493 
01494             rt1+= 4; rt2+= 4; rt+= 4;
01495         }
01496     }
01497 }
01498 
01499 static void do_mul_effect_float(float facf0, float facf1, int x, int y, 
01500                     float *rect1, float *rect2, 
01501                     float *out)
01502 {
01503     int xo;
01504     float fac1, fac3;
01505     float *rt1, *rt2, *rt;
01506 
01507     xo= x;
01508     rt1= rect1;
01509     rt2= rect2;
01510     rt= out;
01511 
01512     fac1= facf0;
01513     fac3= facf1;
01514 
01515     /* formula:
01516      *      fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+a
01517      */
01518 
01519     while(y--) {
01520 
01521         x= xo;
01522         while(x--) {
01523 
01524             rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0f);
01525             rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0f);
01526             rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0f);
01527             rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0f);
01528 
01529             rt1+= 4; rt2+= 4; rt+= 4;
01530         }
01531 
01532         if(y==0) break;
01533         y--;
01534 
01535         x= xo;
01536         while(x--) {
01537 
01538             rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0f);
01539             rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0f);
01540             rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0f);
01541             rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0f);
01542 
01543             rt1+= 4; rt2+= 4; rt+= 4;
01544         }
01545     }
01546 }
01547 
01548 static struct ImBuf * do_mul_effect(
01549     SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
01550     float facf0, float facf1, 
01551     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
01552     struct ImBuf *ibuf3)
01553 {
01554     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
01555 
01556     if (out->rect_float) {
01557         do_mul_effect_float(
01558             facf0, facf1, context.rectx, context.recty,
01559             ibuf1->rect_float, ibuf2->rect_float,
01560             out->rect_float);
01561     } else {
01562         do_mul_effect_byte(
01563             facf0, facf1, context.rectx, context.recty,
01564             (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
01565             (unsigned char*) out->rect);
01566     }
01567 
01568     return out;
01569 }
01570 
01571 /* **********************************************************************
01572    WIPE
01573    ********************************************************************** */
01574 
01575 typedef struct WipeZone {
01576     float angle;
01577     int flip;
01578     int xo, yo;
01579     int width;
01580     float pythangle;
01581 } WipeZone;
01582 
01583 static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
01584 {
01585     wipezone->flip = (wipe->angle < 0);
01586     wipezone->angle = tan(DEG2RAD(fabsf(wipe->angle)));
01587     wipezone->xo = xo;
01588     wipezone->yo = yo;
01589     wipezone->width = (int)(wipe->edgeWidth*((xo+yo)/2.0f));
01590     wipezone->pythangle = 1.0f/sqrtf(wipezone->angle*wipezone->angle + 1.0f);
01591 }
01592 
01593 // This function calculates the blur band for the wipe effects
01594 static float in_band(float width,float dist,int side,int dir)
01595 {
01596     float alpha;
01597 
01598     if(width == 0)
01599         return (float)side;
01600 
01601     if(width < dist)
01602         return (float)side;
01603 
01604     if(side == 1)
01605         alpha = (dist+0.5*width) / (width);
01606     else
01607         alpha = (0.5*width-dist) / (width);
01608 
01609     if(dir == 0)
01610         alpha = 1-alpha;
01611 
01612     return alpha;
01613 }
01614 
01615 static float check_zone(WipeZone *wipezone, int x, int y,
01616     Sequence *seq, float facf0) 
01617 {
01618     float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
01619 /*some future stuff
01620 float hyp3,hyp4,b4,b5      
01621 */
01622     float temp1,temp2,temp3,temp4; //some placeholder variables
01623     int xo = wipezone->xo;
01624     int yo = wipezone->yo;
01625     float halfx = xo*0.5f;
01626     float halfy = yo*0.5f;
01627     float widthf,output=0;
01628     WipeVars *wipe = (WipeVars *)seq->effectdata;
01629     int width;
01630 
01631     if(wipezone->flip) x = xo - x;
01632     angle = wipezone->angle;
01633 
01634     if(wipe->forward){
01635         posx = facf0 * xo;
01636         posy = facf0 * yo;
01637     } else{
01638         posx = xo - facf0 * xo;
01639         posy = yo - facf0 * yo;
01640     }
01641 
01642     switch (wipe->wipetype) {
01643         case DO_SINGLE_WIPE:
01644             width = wipezone->width;
01645 
01646             if(angle == 0.0f) {
01647                 b1 = posy;
01648                 b2 = y;
01649                 hyp = fabs(y - posy);
01650             }
01651             else {
01652                 b1 = posy - (-angle)*posx;
01653                 b2 = y - (-angle)*x;
01654                 hyp = fabsf(angle*x+y+(-posy-angle*posx))*wipezone->pythangle;
01655             }
01656 
01657             if(angle < 0) {
01658                 temp1 = b1;
01659                 b1 = b2;
01660                 b2 = temp1;
01661             }
01662 
01663             if(wipe->forward) {
01664                 if(b1 < b2)
01665                     output = in_band(width,hyp,1,1);
01666                 else
01667                     output = in_band(width,hyp,0,1);
01668             }
01669             else {
01670                 if(b1 < b2)
01671                     output = in_band(width,hyp,0,1);
01672                 else
01673                     output = in_band(width,hyp,1,1);
01674             }
01675         break;
01676 
01677         case DO_DOUBLE_WIPE:
01678             if(!wipe->forward)
01679                 facf0 = 1.0f-facf0;   // Go the other direction
01680 
01681             width = wipezone->width;  // calculate the blur width
01682             hwidth = width*0.5f;
01683             if (angle == 0) {
01684                 b1 = posy*0.5f;
01685                 b3 = yo-posy*0.5f;
01686                 b2 = y;
01687 
01688                 hyp = abs(y - posy*0.5f);
01689                 hyp2 = abs(y - (yo-posy*0.5f));
01690             }
01691             else {
01692                 b1 = posy*0.5f - (-angle)*posx*0.5f;
01693                 b3 = (yo-posy*0.5f) - (-angle)*(xo-posx*0.5f);
01694                 b2 = y - (-angle)*x;
01695 
01696                 hyp = fabsf(angle*x+y+(-posy*0.5f-angle*posx*0.5f))*wipezone->pythangle;
01697                 hyp2 = fabsf(angle*x+y+(-(yo-posy*0.5f)-angle*(xo-posx*0.5f)))*wipezone->pythangle;
01698             }
01699 
01700             hwidth= MIN2(hwidth, fabsf(b3-b1)/2.0f);
01701 
01702             if(b2 < b1 && b2 < b3 ){
01703                 output = in_band(hwidth,hyp,0,1);
01704             } else if(b2 > b1 && b2 > b3 ){
01705                 output = in_band(hwidth,hyp2,0,1);
01706             } else {
01707                 if(  hyp < hwidth && hyp2 > hwidth )
01708                     output = in_band(hwidth,hyp,1,1);
01709                 else if( hyp > hwidth && hyp2 < hwidth )
01710                       output = in_band(hwidth,hyp2,1,1);
01711                 else
01712                       output = in_band(hwidth,hyp2,1,1) * in_band(hwidth,hyp,1,1);
01713             }
01714             if(!wipe->forward)output = 1-output;
01715         break;
01716         case DO_CLOCK_WIPE:
01717               /*
01718                   temp1: angle of effect center in rads
01719                   temp2: angle of line through (halfx,halfy) and (x,y) in rads
01720                   temp3: angle of low side of blur
01721                   temp4: angle of high side of blur
01722               */
01723             output = 1.0f - facf0;
01724             widthf = wipe->edgeWidth*2.0f*(float)M_PI;
01725             temp1 = 2.0f * (float)M_PI * facf0;
01726 
01727             if(wipe->forward){
01728                 temp1 = 2.0f*(float)M_PI - temp1;
01729             }
01730 
01731             x = x - halfx;
01732             y = y - halfy;
01733 
01734             temp2 = asin(abs(y)/sqrt(x*x + y*y));
01735             if(x <= 0 && y >= 0) temp2 = (float)M_PI - temp2;
01736             else if(x<=0 && y <= 0) temp2 += (float)M_PI;
01737             else if(x >= 0 && y <= 0) temp2 = 2.0f*(float)M_PI - temp2;
01738 
01739             if(wipe->forward){
01740                 temp3 = temp1-(widthf*0.5f)*facf0;
01741                 temp4 = temp1+(widthf*0.5f)*(1-facf0);
01742             } else{
01743                 temp3 = temp1-(widthf*0.5f)*(1-facf0);
01744                 temp4 = temp1+(widthf*0.5f)*facf0;
01745             }
01746             if (temp3 < 0) temp3 = 0;
01747             if (temp4 > 2.0f*(float)M_PI) temp4 = 2.0f*(float)M_PI;
01748 
01749 
01750             if(temp2 < temp3) output = 0;
01751             else if (temp2 > temp4) output = 1;
01752             else output = (temp2-temp3)/(temp4-temp3);
01753             if(x == 0 && y == 0) output = 1;
01754             if(output != output) output = 1;
01755             if(wipe->forward) output = 1 - output;
01756         break;
01757     /* BOX WIPE IS NOT WORKING YET */
01758     /* case DO_CROSS_WIPE: */
01759     /* BOX WIPE IS NOT WORKING YET */
01760     /* 
01761         case DO_BOX_WIPE: 
01762             if(invert)facf0 = 1-facf0;
01763 
01764             width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
01765             hwidth = (float)width/2.0;
01766             if (angle == 0)angle = 0.000001;
01767             b1 = posy/2 - (-angle)*posx/2;
01768             b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
01769             b2 = y - (-angle)*x;
01770 
01771             hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle;
01772             hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle;
01773 
01774             temp1 = xo*(1-facf0/2)-xo*facf0/2;
01775             temp2 = yo*(1-facf0/2)-yo*facf0/2;
01776             pointdist = sqrt(temp1*temp1 + temp2*temp2);
01777 
01778             if(b2 < b1 && b2 < b3 ){
01779                 if(hwidth < pointdist)
01780                     output = in_band(wipezone,hwidth,hyp,facf0,0,1);
01781             } else if(b2 > b1 && b2 > b3 ){
01782                 if(hwidth < pointdist)
01783                     output = in_band(wipezone,hwidth,hyp2,facf0,0,1);   
01784             } else {
01785                 if( hyp < hwidth && hyp2 > hwidth )
01786                     output = in_band(wipezone,hwidth,hyp,facf0,1,1);
01787                 else if( hyp > hwidth && hyp2 < hwidth )
01788                      output = in_band(wipezone,hwidth,hyp2,facf0,1,1);
01789                 else
01790                      output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
01791             }
01792 
01793             if(invert)facf0 = 1-facf0;
01794             angle = -1/angle;
01795             b1 = posy/2 - (-angle)*posx/2;
01796             b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
01797             b2 = y - (-angle)*x;
01798 
01799             hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle;
01800             hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle;
01801 
01802             if(b2 < b1 && b2 < b3 ){
01803                 if(hwidth < pointdist)
01804                     output *= in_band(wipezone,hwidth,hyp,facf0,0,1);
01805             } else if(b2 > b1 && b2 > b3 ){
01806                 if(hwidth < pointdist)
01807                     output *= in_band(wipezone,hwidth,hyp2,facf0,0,1);  
01808             } else {
01809                 if( hyp < hwidth && hyp2 > hwidth )
01810                     output *= in_band(wipezone,hwidth,hyp,facf0,1,1);
01811                 else if( hyp > hwidth && hyp2 < hwidth )
01812                     output *= in_band(wipezone,hwidth,hyp2,facf0,1,1);
01813                 else
01814                     output *= in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
01815             }
01816 
01817         break;
01818 */
01819         case DO_IRIS_WIPE:
01820             if(xo > yo) yo = xo;
01821             else xo = yo;
01822 
01823             if(!wipe->forward) facf0 = 1-facf0;
01824 
01825             width = wipezone->width;
01826             hwidth = width*0.5f;
01827 
01828             temp1 = (halfx-(halfx)*facf0);
01829             pointdist = sqrt(temp1*temp1 + temp1*temp1);
01830 
01831             temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y));
01832             if(temp2 > pointdist) output = in_band(hwidth,fabs(temp2-pointdist),0,1);
01833             else output = in_band(hwidth,fabs(temp2-pointdist),1,1);
01834 
01835             if(!wipe->forward) output = 1-output;
01836             
01837         break;
01838     }
01839     if (output < 0) output = 0;
01840     else if(output > 1) output = 1;
01841     return output;
01842 }
01843 
01844 static void init_wipe_effect(Sequence *seq)
01845 {
01846     if(seq->effectdata)MEM_freeN(seq->effectdata);
01847     seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
01848 }
01849 
01850 static int num_inputs_wipe(void)
01851 {
01852     return 1;
01853 }
01854 
01855 static void free_wipe_effect(Sequence *seq)
01856 {
01857     if(seq->effectdata)MEM_freeN(seq->effectdata);
01858     seq->effectdata = NULL;
01859 }
01860 
01861 static void copy_wipe_effect(Sequence *dst, Sequence *src)
01862 {
01863     dst->effectdata = MEM_dupallocN(src->effectdata);
01864 }
01865 
01866 static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), 
01867                 int x, int y, 
01868                 unsigned char *rect1, 
01869                 unsigned char *rect2, unsigned char *out)
01870 {
01871     WipeZone wipezone;
01872     WipeVars *wipe = (WipeVars *)seq->effectdata;
01873     int xo, yo;
01874     char *rt1, *rt2, *rt;
01875 
01876     precalc_wipe_zone(&wipezone, wipe, x, y);
01877 
01878     rt1 = (char *)rect1;
01879     rt2 = (char *)rect2;
01880     rt = (char *)out;
01881 
01882     xo = x;
01883     yo = y;
01884     for(y=0;y<yo;y++) {
01885         for(x=0;x<xo;x++) {
01886             float check = check_zone(&wipezone,x,y,seq,facf0);
01887             if (check) {
01888                 if (rt1) {
01889                     rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
01890                     rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
01891                     rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
01892                     rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
01893                 } else {
01894                     rt[0] = 0;
01895                     rt[1] = 0;
01896                     rt[2] = 0;
01897                     rt[3] = 255;
01898                 }
01899             } else {
01900                 if (rt2) {
01901                     rt[0] = rt2[0];
01902                     rt[1] = rt2[1];
01903                     rt[2] = rt2[2];
01904                     rt[3] = rt2[3];
01905                 } else {
01906                     rt[0] = 0;
01907                     rt[1] = 0;
01908                     rt[2] = 0;
01909                     rt[3] = 255;
01910                 }
01911             }
01912 
01913             rt+=4;
01914             if(rt1 !=NULL){
01915                 rt1+=4;
01916             }
01917             if(rt2 !=NULL){
01918                 rt2+=4;
01919             }
01920         }
01921     }
01922 }
01923 
01924 static void do_wipe_effect_float(Sequence *seq, float facf0, float UNUSED(facf1), 
01925                  int x, int y, 
01926                  float *rect1, 
01927                  float *rect2, float *out)
01928 {
01929     WipeZone wipezone;
01930     WipeVars *wipe = (WipeVars *)seq->effectdata;
01931     int xo, yo;
01932     float *rt1, *rt2, *rt;
01933 
01934     precalc_wipe_zone(&wipezone, wipe, x, y);
01935 
01936     rt1 = rect1;
01937     rt2 = rect2;
01938     rt = out;
01939 
01940     xo = x;
01941     yo = y;
01942     for(y=0;y<yo;y++) {
01943         for(x=0;x<xo;x++) {
01944             float check = check_zone(&wipezone,x,y,seq,facf0);
01945             if (check) {
01946                 if (rt1) {
01947                     rt[0] = rt1[0]*check+ rt2[0]*(1-check);
01948                     rt[1] = rt1[1]*check+ rt2[1]*(1-check);
01949                     rt[2] = rt1[2]*check+ rt2[2]*(1-check);
01950                     rt[3] = rt1[3]*check+ rt2[3]*(1-check);
01951                 } else {
01952                     rt[0] = 0;
01953                     rt[1] = 0;
01954                     rt[2] = 0;
01955                     rt[3] = 1.0;
01956                 }
01957             } else {
01958                 if (rt2) {
01959                     rt[0] = rt2[0];
01960                     rt[1] = rt2[1];
01961                     rt[2] = rt2[2];
01962                     rt[3] = rt2[3];
01963                 } else {
01964                     rt[0] = 0;
01965                     rt[1] = 0;
01966                     rt[2] = 0;
01967                     rt[3] = 1.0;
01968                 }
01969             }
01970 
01971             rt+=4;
01972             if(rt1 !=NULL){
01973                 rt1+=4;
01974             }
01975             if(rt2 !=NULL){
01976                 rt2+=4;
01977             }
01978         }
01979     }
01980 }
01981 
01982 static struct ImBuf * do_wipe_effect(
01983     SeqRenderData context, Sequence *seq, float UNUSED(cfra),
01984     float facf0, float facf1, 
01985     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
01986     struct ImBuf *ibuf3)
01987 {
01988     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
01989 
01990     if (out->rect_float) {
01991         do_wipe_effect_float(seq,
01992                      facf0, facf1, context.rectx, context.recty,
01993                      ibuf1->rect_float, ibuf2->rect_float,
01994                      out->rect_float);
01995     } else {
01996         do_wipe_effect_byte(seq,
01997                     facf0, facf1, context.rectx, context.recty,
01998                     (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
01999                     (unsigned char*) out->rect);
02000     }
02001 
02002     return out;
02003 }
02004 /* **********************************************************************
02005    TRANSFORM
02006    ********************************************************************** */
02007 static void init_transform_effect(Sequence *seq)
02008 {
02009     TransformVars *transform;
02010 
02011     if(seq->effectdata)MEM_freeN(seq->effectdata);
02012     seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars");
02013 
02014     transform = (TransformVars *)seq->effectdata;
02015 
02016     transform->ScalexIni = 1.0f;
02017     transform->ScaleyIni = 1.0f;
02018 
02019     transform->xIni=0.0f;
02020     transform->yIni=0.0f;
02021 
02022     transform->rotIni=0.0f;
02023     
02024     transform->interpolation=1;
02025     transform->percent=1;
02026     transform->uniform_scale=0;
02027 }
02028 
02029 static int num_inputs_transform(void)
02030 {
02031     return 1;
02032 }
02033 
02034 static void free_transform_effect(Sequence *seq)
02035 {
02036     if(seq->effectdata)MEM_freeN(seq->effectdata);
02037     seq->effectdata = NULL;
02038 }
02039 
02040 static void copy_transform_effect(Sequence *dst, Sequence *src)
02041 {
02042     dst->effectdata = MEM_dupallocN(src->effectdata);
02043 }
02044 
02045 static void transform_image(int x, int y, struct ImBuf *ibuf1, struct ImBuf *out, 
02046                 float scale_x, float scale_y, float translate_x, float translate_y, 
02047                 float rotate, int interpolation)
02048 {
02049     int xo, yo, xi, yi;
02050     float xt, yt, xr, yr;
02051     float s,c;
02052 
02053     xo = x;
02054     yo = y;
02055     
02056     // Rotate
02057     s= sin(rotate);
02058     c= cos(rotate);
02059 
02060     for (yi = 0; yi < yo; yi++) {
02061         for (xi = 0; xi < xo; xi++) {
02062 
02063             //translate point
02064             xt = xi-translate_x;
02065             yt = yi-translate_y;
02066 
02067             //rotate point with center ref
02068             xr =  c*xt + s*yt;
02069             yr = -s*xt + c*yt;
02070 
02071             //scale point with center ref
02072             xt = xr / scale_x;
02073             yt = yr / scale_y;
02074 
02075             //undo reference center point 
02076             xt += (xo / 2.0f);
02077             yt += (yo / 2.0f);
02078 
02079             //interpolate
02080             switch(interpolation) {
02081             case 0:
02082                 neareast_interpolation(ibuf1,out, xt,yt,xi,yi);
02083                 break;
02084             case 1:
02085                 bilinear_interpolation(ibuf1,out, xt,yt,xi,yi);
02086                 break;
02087             case 2:
02088                 bicubic_interpolation(ibuf1,out, xt,yt,xi,yi);
02089                 break;
02090             }
02091         }
02092     }
02093 }
02094 
02095 static void do_transform(Scene *scene, Sequence *seq, float UNUSED(facf0), int x, int y, 
02096               struct ImBuf *ibuf1,struct ImBuf *out)
02097 {
02098     TransformVars *transform = (TransformVars *)seq->effectdata;
02099     float scale_x, scale_y, translate_x, translate_y, rotate_radians;
02100     
02101     // Scale
02102     if (transform->uniform_scale) {
02103         scale_x = scale_y = transform->ScalexIni;
02104     } else {
02105         scale_x = transform->ScalexIni;
02106         scale_y = transform->ScaleyIni;
02107     }
02108 
02109     // Translate
02110     if(!transform->percent){
02111         float rd_s = (scene->r.size/100.0f);
02112 
02113         translate_x = transform->xIni*rd_s+(x/2.0f);
02114         translate_y = transform->yIni*rd_s+(y/2.0f);
02115     }else{
02116         translate_x = x*(transform->xIni/100.0f)+(x/2.0f);
02117         translate_y = y*(transform->yIni/100.0f)+(y/2.0f);
02118     }
02119     
02120     // Rotate
02121     rotate_radians = DEG2RADF(transform->rotIni);
02122 
02123     transform_image(x,y, ibuf1, out, scale_x, scale_y, translate_x, translate_y, rotate_radians, transform->interpolation);
02124 }
02125 
02126 
02127 static struct ImBuf * do_transform_effect(
02128     SeqRenderData context, Sequence *seq,float UNUSED(cfra),
02129     float facf0, float UNUSED(facf1), 
02130     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
02131     struct ImBuf *ibuf3)
02132 {
02133     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
02134 
02135     do_transform(context.scene, seq, facf0, 
02136                  context.rectx, context.recty, ibuf1, out);
02137 
02138     return out;
02139 }
02140 
02141 
02142 /* **********************************************************************
02143    GLOW
02144    ********************************************************************** */
02145 
02146 static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height,
02147                  float blur,
02148                  int quality)
02149 /*  MUUUCCH better than the previous blur. */
02150 /*  We do the blurring in two passes which is a whole lot faster. */
02151 /*  I changed the math arount to implement an actual Gaussian */
02152 /*  distribution. */
02153 /* */
02154 /*  Watch out though, it tends to misbehaven with large blur values on */
02155 /*  a small bitmap.  Avoid avoid avoid. */
02156 /*=============================== */
02157 {
02158     unsigned char*  temp=NULL,*swap;
02159     float   *filter=NULL;
02160     int x,y,i,fx,fy;
02161     int index, ix, halfWidth;
02162     float   fval, k, curColor[3], curColor2[3], weight=0;
02163 
02164     /*  If we're not really blurring, bail out */
02165     if (blur<=0)
02166         return;
02167 
02168     /*  Allocate memory for the tempmap and the blur filter matrix */
02169     temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
02170     if (!temp)
02171         return;
02172 
02173     /*  Allocate memory for the filter elements */
02174     halfWidth = ((quality+1)*blur);
02175     filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
02176     if (!filter){
02177         MEM_freeN (temp);
02178         return;
02179     }
02180 
02181     /*  Apparently we're calculating a bell curve */
02182     /*  based on the standard deviation (or radius) */
02183     /*  This code is based on an example */
02184     /*  posted to comp.graphics.algorithms by */
02185     /*  Blancmange (bmange@airdmhor.gen.nz) */
02186 
02187     k = -1.0f/(2.0f*(float)M_PI*blur*blur);
02188     for (ix = 0;ix< halfWidth;ix++){
02189         weight = (float)exp(k*(ix*ix));
02190         filter[halfWidth - ix] = weight;
02191         filter[halfWidth + ix] = weight;
02192     }
02193     filter[0] = weight;
02194 
02195     /*  Normalize the array */
02196     fval=0;
02197     for (ix = 0;ix< halfWidth*2;ix++)
02198         fval+=filter[ix];
02199 
02200     for (ix = 0;ix< halfWidth*2;ix++)
02201         filter[ix]/=fval;
02202 
02203     /*  Blur the rows */
02204     for (y=0;y<height;y++){
02205         /*  Do the left & right strips */
02206         for (x=0;x<halfWidth;x++){
02207             index=(x+y*width)*4;
02208             fx=0;
02209             curColor[0]=curColor[1]=curColor[2]=0;
02210             curColor2[0]=curColor2[1]=curColor2[2]=0;
02211 
02212             for (i=x-halfWidth;i<x+halfWidth;i++){
02213                 if ((i>=0)&&(i<width)){
02214                     curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
02215                     curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
02216                     curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
02217 
02218                     curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
02219                         filter[fx];
02220                     curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
02221                         filter[fx];
02222                     curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
02223                         filter[fx];
02224                 }
02225                 fx++;
02226             }
02227             temp[index+GlowR]=curColor[0];
02228             temp[index+GlowG]=curColor[1];
02229             temp[index+GlowB]=curColor[2];
02230 
02231             temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
02232             temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
02233             temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
02234 
02235         }
02236         /*  Do the main body */
02237         for (x=halfWidth;x<width-halfWidth;x++){
02238             index=(x+y*width)*4;
02239             fx=0;
02240             curColor[0]=curColor[1]=curColor[2]=0;
02241             for (i=x-halfWidth;i<x+halfWidth;i++){
02242                 curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
02243                 curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
02244                 curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
02245                 fx++;
02246             }
02247             temp[index+GlowR]=curColor[0];
02248             temp[index+GlowG]=curColor[1];
02249             temp[index+GlowB]=curColor[2];
02250         }
02251     }
02252 
02253     /*  Swap buffers */
02254     swap=temp;temp=map;map=swap;
02255 
02256 
02257     /*  Blur the columns */
02258     for (x=0;x<width;x++){
02259         /*  Do the top & bottom strips */
02260         for (y=0;y<halfWidth;y++){
02261             index=(x+y*width)*4;
02262             fy=0;
02263             curColor[0]=curColor[1]=curColor[2]=0;
02264             curColor2[0]=curColor2[1]=curColor2[2]=0;
02265             for (i=y-halfWidth;i<y+halfWidth;i++){
02266                 if ((i>=0)&&(i<height)){
02267                     /*  Bottom */
02268                     curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
02269                     curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
02270                     curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
02271 
02272                     /*  Top */
02273                     curColor2[0]+=map[(x+(height-1-i)*width) *
02274                         4+GlowR]*filter[fy];
02275                     curColor2[1]+=map[(x+(height-1-i)*width) *
02276                         4+GlowG]*filter[fy];
02277                     curColor2[2]+=map[(x+(height-1-i)*width) *
02278                         4+GlowB]*filter[fy];
02279                 }
02280                 fy++;
02281             }
02282             temp[index+GlowR]=curColor[0];
02283             temp[index+GlowG]=curColor[1];
02284             temp[index+GlowB]=curColor[2];
02285             temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
02286             temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
02287             temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
02288         }
02289         /*  Do the main body */
02290         for (y=halfWidth;y<height-halfWidth;y++){
02291             index=(x+y*width)*4;
02292             fy=0;
02293             curColor[0]=curColor[1]=curColor[2]=0;
02294             for (i=y-halfWidth;i<y+halfWidth;i++){
02295                 curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
02296                 curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
02297                 curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
02298                 fy++;
02299             }
02300             temp[index+GlowR]=curColor[0];
02301             temp[index+GlowG]=curColor[1];
02302             temp[index+GlowB]=curColor[2];
02303         }
02304     }
02305 
02306 
02307     /*  Swap buffers */
02308     swap=temp;temp=map; /* map=swap; */ /* UNUSED */
02309 
02310     /*  Tidy up  */
02311     MEM_freeN (filter);
02312     MEM_freeN (temp);
02313 }
02314 
02315 static void RVBlurBitmap2_float ( float* map, int width,int height,
02316                   float blur,
02317                   int quality)
02318 /*  MUUUCCH better than the previous blur. */
02319 /*  We do the blurring in two passes which is a whole lot faster. */
02320 /*  I changed the math arount to implement an actual Gaussian */
02321 /*  distribution. */
02322 /* */
02323 /*  Watch out though, it tends to misbehaven with large blur values on */
02324 /*  a small bitmap.  Avoid avoid avoid. */
02325 /*=============================== */
02326 {
02327     float*  temp=NULL,*swap;
02328     float   *filter=NULL;
02329     int x,y,i,fx,fy;
02330     int index, ix, halfWidth;
02331     float   fval, k, curColor[3], curColor2[3], weight=0;
02332 
02333     /*  If we're not really blurring, bail out */
02334     if (blur<=0)
02335         return;
02336 
02337     /*  Allocate memory for the tempmap and the blur filter matrix */
02338     temp= MEM_mallocN( (width*height*4*sizeof(float)), "blurbitmaptemp");
02339     if (!temp)
02340         return;
02341 
02342     /*  Allocate memory for the filter elements */
02343     halfWidth = ((quality+1)*blur);
02344     filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
02345     if (!filter){
02346         MEM_freeN (temp);
02347         return;
02348     }
02349 
02350     /*  Apparently we're calculating a bell curve */
02351     /*  based on the standard deviation (or radius) */
02352     /*  This code is based on an example */
02353     /*  posted to comp.graphics.algorithms by */
02354     /*  Blancmange (bmange@airdmhor.gen.nz) */
02355 
02356     k = -1.0f/(2.0f*(float)M_PI*blur*blur);
02357 
02358     for (ix = 0;ix< halfWidth;ix++){
02359         weight = (float)exp(k*(ix*ix));
02360         filter[halfWidth - ix] = weight;
02361         filter[halfWidth + ix] = weight;
02362     }
02363     filter[0] = weight;
02364 
02365     /*  Normalize the array */
02366     fval=0;
02367     for (ix = 0;ix< halfWidth*2;ix++)
02368         fval+=filter[ix];
02369 
02370     for (ix = 0;ix< halfWidth*2;ix++)
02371         filter[ix]/=fval;
02372 
02373     /*  Blur the rows */
02374     for (y=0;y<height;y++){
02375         /*  Do the left & right strips */
02376         for (x=0;x<halfWidth;x++){
02377             index=(x+y*width)*4;
02378             fx=0;
02379             curColor[0]=curColor[1]=curColor[2]=0.0f;
02380             curColor2[0]=curColor2[1]=curColor2[2]=0.0f;
02381 
02382             for (i=x-halfWidth;i<x+halfWidth;i++){
02383                 if ((i>=0)&&(i<width)){
02384                     curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
02385                     curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
02386                     curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
02387 
02388                     curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
02389                         filter[fx];
02390                     curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
02391                         filter[fx];
02392                     curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
02393                         filter[fx];
02394                 }
02395                 fx++;
02396             }
02397             temp[index+GlowR]=curColor[0];
02398             temp[index+GlowG]=curColor[1];
02399             temp[index+GlowB]=curColor[2];
02400 
02401             temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
02402             temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
02403             temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
02404 
02405         }
02406         /*  Do the main body */
02407         for (x=halfWidth;x<width-halfWidth;x++){
02408             index=(x+y*width)*4;
02409             fx=0;
02410             curColor[0]=curColor[1]=curColor[2]=0;
02411             for (i=x-halfWidth;i<x+halfWidth;i++){
02412                 curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
02413                 curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
02414                 curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
02415                 fx++;
02416             }
02417             temp[index+GlowR]=curColor[0];
02418             temp[index+GlowG]=curColor[1];
02419             temp[index+GlowB]=curColor[2];
02420         }
02421     }
02422 
02423     /*  Swap buffers */
02424     swap=temp;temp=map;map=swap;
02425 
02426 
02427     /*  Blur the columns */
02428     for (x=0;x<width;x++){
02429         /*  Do the top & bottom strips */
02430         for (y=0;y<halfWidth;y++){
02431             index=(x+y*width)*4;
02432             fy=0;
02433             curColor[0]=curColor[1]=curColor[2]=0;
02434             curColor2[0]=curColor2[1]=curColor2[2]=0;
02435             for (i=y-halfWidth;i<y+halfWidth;i++){
02436                 if ((i>=0)&&(i<height)){
02437                     /*  Bottom */
02438                     curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
02439                     curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
02440                     curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
02441 
02442                     /*  Top */
02443                     curColor2[0]+=map[(x+(height-1-i)*width) *
02444                         4+GlowR]*filter[fy];
02445                     curColor2[1]+=map[(x+(height-1-i)*width) *
02446                         4+GlowG]*filter[fy];
02447                     curColor2[2]+=map[(x+(height-1-i)*width) *
02448                         4+GlowB]*filter[fy];
02449                 }
02450                 fy++;
02451             }
02452             temp[index+GlowR]=curColor[0];
02453             temp[index+GlowG]=curColor[1];
02454             temp[index+GlowB]=curColor[2];
02455             temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
02456             temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
02457             temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
02458         }
02459         /*  Do the main body */
02460         for (y=halfWidth;y<height-halfWidth;y++){
02461             index=(x+y*width)*4;
02462             fy=0;
02463             curColor[0]=curColor[1]=curColor[2]=0;
02464             for (i=y-halfWidth;i<y+halfWidth;i++){
02465                 curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
02466                 curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
02467                 curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
02468                 fy++;
02469             }
02470             temp[index+GlowR]=curColor[0];
02471             temp[index+GlowG]=curColor[1];
02472             temp[index+GlowB]=curColor[2];
02473         }
02474     }
02475 
02476 
02477     /*  Swap buffers */
02478     swap=temp;temp=map; /* map=swap; */ /* UNUSED */
02479 
02480     /*  Tidy up  */
02481     MEM_freeN (filter);
02482     MEM_freeN (temp);
02483 }
02484 
02485 
02486 /*  Adds two bitmaps and puts the results into a third map. */
02487 /*  C must have been previously allocated but it may be A or B. */
02488 /*  We clamp values to 255 to prevent weirdness */
02489 /*=============================== */
02490 static void RVAddBitmaps_byte (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
02491 {
02492     int x,y,index;
02493 
02494     for (y=0;y<height;y++){
02495         for (x=0;x<width;x++){
02496             index=(x+y*width)*4;
02497             c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
02498             c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
02499             c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
02500             c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
02501         }
02502     }
02503 }
02504 
02505 static void RVAddBitmaps_float (float* a, float* b, float* c, 
02506                 int width, int height)
02507 {
02508     int x,y,index;
02509 
02510     for (y=0;y<height;y++){
02511         for (x=0;x<width;x++){
02512             index=(x+y*width)*4;
02513             c[index+GlowR]= MIN2(1.0f, a[index+GlowR]+b[index+GlowR]);
02514             c[index+GlowG]= MIN2(1.0f, a[index+GlowG]+b[index+GlowG]);
02515             c[index+GlowB]= MIN2(1.0f, a[index+GlowB]+b[index+GlowB]);
02516             c[index+GlowA]= MIN2(1.0f, a[index+GlowA]+b[index+GlowA]);
02517         }
02518     }
02519 }
02520 
02521 /*  For each pixel whose total luminance exceeds the threshold, */
02522 /*  Multiply it's value by BOOST and add it to the output map */
02523 static void RVIsolateHighlights_byte (unsigned char* in, unsigned char* out, 
02524                       int width, int height, int threshold, 
02525                       float boost, float clamp)
02526 {
02527     int x,y,index;
02528     int intensity;
02529 
02530 
02531     for(y=0;y< height;y++) {
02532         for (x=0;x< width;x++) {
02533             index= (x+y*width)*4;
02534 
02535             /*  Isolate the intensity */
02536             intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
02537             if (intensity>0){
02538                 out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
02539                 out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
02540                 out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
02541                 out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255);
02542             } else{
02543                 out[index+GlowR]=0;
02544                 out[index+GlowG]=0;
02545                 out[index+GlowB]=0;
02546                 out[index+GlowA]=0;
02547             }
02548         }
02549     }
02550 }
02551 
02552 static void RVIsolateHighlights_float (float* in, float* out, 
02553                       int width, int height, float threshold, 
02554                       float boost, float clamp)
02555 {
02556     int x,y,index;
02557     float   intensity;
02558 
02559 
02560     for(y=0;y< height;y++) {
02561         for (x=0;x< width;x++) {
02562             index= (x+y*width)*4;
02563 
02564             /*  Isolate the intensity */
02565             intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
02566             if (intensity>0){
02567                 out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity));
02568                 out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity));
02569                 out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity));
02570                 out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity));
02571             } else{
02572                 out[index+GlowR]=0;
02573                 out[index+GlowG]=0;
02574                 out[index+GlowB]=0;
02575                 out[index+GlowA]=0;
02576             }
02577         }
02578     }
02579 }
02580 
02581 static void init_glow_effect(Sequence *seq)
02582 {
02583     GlowVars *glow;
02584 
02585     if(seq->effectdata)MEM_freeN(seq->effectdata);
02586     seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
02587 
02588     glow = (GlowVars *)seq->effectdata;
02589     glow->fMini = 0.25;
02590     glow->fClamp = 1.0;
02591     glow->fBoost = 0.5;
02592     glow->dDist = 3.0;
02593     glow->dQuality = 3;
02594     glow->bNoComp = 0;
02595 }
02596 
02597 static int num_inputs_glow(void)
02598 {
02599     return 1;
02600 }
02601 
02602 static void free_glow_effect(Sequence *seq)
02603 {
02604     if(seq->effectdata)MEM_freeN(seq->effectdata);
02605     seq->effectdata = NULL;
02606 }
02607 
02608 static void copy_glow_effect(Sequence *dst, Sequence *src)
02609 {
02610     dst->effectdata = MEM_dupallocN(src->effectdata);
02611 }
02612 
02613 //void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
02614 static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), 
02615                 int x, int y, char *rect1, 
02616                 char *UNUSED(rect2), char *out)
02617 {
02618     unsigned char *outbuf=(unsigned char *)out;
02619     unsigned char *inbuf=(unsigned char *)rect1;
02620     GlowVars *glow = (GlowVars *)seq->effectdata;
02621     
02622     RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost * facf0, glow->fClamp);
02623     RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (render_size / 100.0f),glow->dQuality);
02624     if (!glow->bNoComp)
02625         RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y);
02626 }
02627 
02628 static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), 
02629                  int x, int y, 
02630                  float *rect1, float *UNUSED(rect2), float *out)
02631 {
02632     float *outbuf = out;
02633     float *inbuf = rect1;
02634     GlowVars *glow = (GlowVars *)seq->effectdata;
02635 
02636     RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost * facf0, glow->fClamp);
02637     RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (render_size / 100.0f),glow->dQuality);
02638     if (!glow->bNoComp)
02639         RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y);
02640 }
02641 
02642 static struct ImBuf * do_glow_effect(
02643     SeqRenderData context, Sequence *seq, float UNUSED(cfra),
02644     float facf0, float facf1, 
02645     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
02646     struct ImBuf *ibuf3)
02647 {
02648     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
02649 
02650     int render_size = 100*context.rectx/context.scene->r.xsch;
02651 
02652     if (out->rect_float) {
02653         do_glow_effect_float(seq, render_size,
02654                      facf0, facf1, 
02655                      context.rectx, context.recty,
02656                      ibuf1->rect_float, ibuf2->rect_float,
02657                      out->rect_float);
02658     } else {
02659         do_glow_effect_byte(seq, render_size,
02660                     facf0, facf1, 
02661                     context.rectx, context.recty,
02662                     (char*) ibuf1->rect, (char*) ibuf2->rect,
02663                     (char*) out->rect);
02664     }
02665 
02666     return out;
02667 }
02668 
02669 /* **********************************************************************
02670    SOLID COLOR
02671    ********************************************************************** */
02672 
02673 static void init_solid_color(Sequence *seq)
02674 {
02675     SolidColorVars *cv;
02676     
02677     if(seq->effectdata)MEM_freeN(seq->effectdata);
02678     seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor");
02679     
02680     cv = (SolidColorVars *)seq->effectdata;
02681     cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
02682 }
02683 
02684 static int num_inputs_color(void)
02685 {
02686     return 0;
02687 }
02688 
02689 static void free_solid_color(Sequence *seq)
02690 {
02691     if(seq->effectdata)MEM_freeN(seq->effectdata);
02692     seq->effectdata = NULL;
02693 }
02694 
02695 static void copy_solid_color(Sequence *dst, Sequence *src)
02696 {
02697     dst->effectdata = MEM_dupallocN(src->effectdata);
02698 }
02699 
02700 static int early_out_color(struct Sequence *UNUSED(seq),
02701                float UNUSED(facf0), float UNUSED(facf1))
02702 {
02703     return -1;
02704 }
02705 
02706 static struct ImBuf * do_solid_color(
02707     SeqRenderData context, Sequence *seq, float UNUSED(cfra),
02708     float facf0, float facf1, 
02709     struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
02710     struct ImBuf *ibuf3)
02711 {
02712     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
02713 
02714     SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
02715 
02716     unsigned char *rect;
02717     float *rect_float;
02718     int x; /*= context.rectx;*/ /*UNUSED*/
02719     int y; /*= context.recty;*/ /*UNUSED*/
02720 
02721     if (out->rect) {
02722         unsigned char col0[3];
02723         unsigned char col1[3];
02724 
02725         col0[0] = facf0 * cv->col[0] * 255;
02726         col0[1] = facf0 * cv->col[1] * 255;
02727         col0[2] = facf0 * cv->col[2] * 255;
02728 
02729         col1[0] = facf1 * cv->col[0] * 255;
02730         col1[1] = facf1 * cv->col[1] * 255;
02731         col1[2] = facf1 * cv->col[2] * 255;
02732 
02733         rect = (unsigned char *)out->rect;
02734         
02735         for(y=0; y<out->y; y++) {   
02736             for(x=0; x<out->x; x++, rect+=4) {
02737                 rect[0]= col0[0];
02738                 rect[1]= col0[1];
02739                 rect[2]= col0[2];
02740                 rect[3]= 255;
02741             }
02742             y++;
02743             if (y<out->y) {
02744                 for(x=0; x<out->x; x++, rect+=4) {
02745                     rect[0]= col1[0];
02746                     rect[1]= col1[1];
02747                     rect[2]= col1[2];
02748                     rect[3]= 255;
02749                 }   
02750             }
02751         }
02752 
02753     } else if (out->rect_float) {
02754         float col0[3];
02755         float col1[3];
02756 
02757         col0[0] = facf0 * cv->col[0];
02758         col0[1] = facf0 * cv->col[1];
02759         col0[2] = facf0 * cv->col[2];
02760 
02761         col1[0] = facf1 * cv->col[0];
02762         col1[1] = facf1 * cv->col[1];
02763         col1[2] = facf1 * cv->col[2];
02764 
02765         rect_float = out->rect_float;
02766         
02767         for(y=0; y<out->y; y++) {   
02768             for(x=0; x<out->x; x++, rect_float+=4) {
02769                 rect_float[0]= col0[0];
02770                 rect_float[1]= col0[1];
02771                 rect_float[2]= col0[2];
02772                 rect_float[3]= 1.0;
02773             }
02774             y++;
02775             if (y<out->y) {
02776                 for(x=0; x<out->x; x++, rect_float+=4) {
02777                     rect_float[0]= col1[0];
02778                     rect_float[1]= col1[1];
02779                     rect_float[2]= col1[2];
02780                     rect_float[3]= 1.0;
02781                 }
02782             }
02783         }
02784     }
02785     return out;
02786 }
02787 
02788 /* **********************************************************************
02789    MULTICAM
02790    ********************************************************************** */
02791 
02792 /* no effect inputs for multicam, we use give_ibuf_seq */
02793 static int num_inputs_multicam(void)
02794 {
02795     return 0;
02796 }
02797 
02798 static int early_out_multicam(struct Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
02799 {
02800     return -1;
02801 }
02802 
02803 static struct ImBuf * do_multicam(
02804     SeqRenderData context, Sequence *seq, float cfra,
02805     float UNUSED(facf0), float UNUSED(facf1),
02806     struct ImBuf *UNUSED(ibuf1), struct ImBuf *UNUSED(ibuf2), 
02807     struct ImBuf *UNUSED(ibuf3))
02808 {
02809     struct ImBuf * i;
02810     struct ImBuf * out;
02811     Editing * ed;
02812     ListBase * seqbasep;
02813 
02814     if (seq->multicam_source == 0 || seq->multicam_source >= seq->machine) {
02815         return NULL;
02816     }
02817 
02818     ed = context.scene->ed;
02819     if (!ed) {
02820         return NULL;
02821     }
02822     seqbasep = seq_seqbase(&ed->seqbase, seq);
02823     if (!seqbasep) {
02824         return NULL;
02825     }
02826 
02827     i = give_ibuf_seqbase(context, cfra, seq->multicam_source, seqbasep);
02828     if (!i) {
02829         return NULL;
02830     }
02831 
02832     if (input_have_to_preprocess(context, seq, cfra)) {
02833         out = IMB_dupImBuf(i);
02834         IMB_freeImBuf(i);
02835     } else {
02836         out = i;
02837     }
02838     
02839     return out;
02840 }
02841 
02842 /* **********************************************************************
02843    ADJUSTMENT
02844    ********************************************************************** */
02845 
02846 /* no effect inputs for adjustment, we use give_ibuf_seq */
02847 static int num_inputs_adjustment(void)
02848 {
02849     return 0;
02850 }
02851 
02852 static int early_out_adjustment(struct Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
02853 {
02854     return -1;
02855 }
02856 
02857 static struct ImBuf * do_adjustment_impl(SeqRenderData context, Sequence * seq,
02858                      float cfra)
02859 {
02860     Editing * ed;
02861     ListBase * seqbasep;
02862     struct ImBuf * i= NULL;
02863 
02864     ed = context.scene->ed;
02865 
02866     seqbasep = seq_seqbase(&ed->seqbase, seq);
02867 
02868     if (seq->machine > 0) {
02869         i = give_ibuf_seqbase(context, cfra,
02870                       seq->machine - 1, seqbasep);
02871     }
02872 
02873     /* found nothing? so let's work the way up the metastrip stack, so
02874        that it is possible to group a bunch of adjustment strips into
02875        a metastrip and have that work on everything below the metastrip
02876     */
02877        
02878     if (!i) {
02879         Sequence * meta;
02880 
02881         meta = seq_metastrip(&ed->seqbase, NULL, seq);
02882 
02883         if (meta) {
02884             i = do_adjustment_impl(context, meta, cfra);
02885         }
02886     }
02887 
02888     return i;
02889 }
02890 
02891 static struct ImBuf * do_adjustment(
02892     SeqRenderData context, Sequence *seq, float cfra,
02893     float UNUSED(facf0), float UNUSED(facf1),
02894     struct ImBuf *UNUSED(ibuf1), struct ImBuf *UNUSED(ibuf2), 
02895     struct ImBuf *UNUSED(ibuf3))
02896 {
02897     struct ImBuf * i = NULL;
02898     struct ImBuf * out;
02899     Editing * ed;
02900 
02901     ed = context.scene->ed;
02902 
02903     if (!ed) {
02904         return NULL;
02905     }
02906 
02907     i = do_adjustment_impl(context, seq, cfra);
02908 
02909     if (input_have_to_preprocess(context, seq, cfra)) {
02910         out = IMB_dupImBuf(i);
02911         IMB_freeImBuf(i);
02912     } else {
02913         out = i;
02914     }
02915     
02916     return out;
02917 }
02918 
02919 /* **********************************************************************
02920    SPEED
02921    ********************************************************************** */
02922 static void init_speed_effect(Sequence *seq)
02923 {
02924     SpeedControlVars * v;
02925 
02926     if(seq->effectdata) MEM_freeN(seq->effectdata);
02927     seq->effectdata = MEM_callocN(sizeof(struct SpeedControlVars), 
02928                       "speedcontrolvars");
02929 
02930     v = (SpeedControlVars *)seq->effectdata;
02931     v->globalSpeed = 1.0;
02932     v->frameMap = NULL;
02933     v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */
02934     v->length = 0;
02935 }
02936 
02937 static void load_speed_effect(Sequence * seq)
02938 {
02939     SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
02940 
02941     v->frameMap = NULL;
02942     v->length = 0;
02943 }
02944 
02945 static int num_inputs_speed(void)
02946 {
02947     return 1;
02948 }
02949 
02950 static void free_speed_effect(Sequence *seq)
02951 {
02952     SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
02953     if(v->frameMap) MEM_freeN(v->frameMap);
02954     if(seq->effectdata) MEM_freeN(seq->effectdata);
02955     seq->effectdata = NULL;
02956 }
02957 
02958 static void copy_speed_effect(Sequence *dst, Sequence *src)
02959 {
02960     SpeedControlVars * v;
02961     dst->effectdata = MEM_dupallocN(src->effectdata);
02962     v = (SpeedControlVars *)dst->effectdata;
02963     v->frameMap = NULL;
02964     v->length = 0;
02965 }
02966 
02967 static int early_out_speed(struct Sequence *UNUSED(seq),
02968               float UNUSED(facf0), float UNUSED(facf1))
02969 {
02970     return 1;
02971 }
02972 
02973 static void store_icu_yrange_speed(struct Sequence * seq,
02974                    short UNUSED(adrcode), float * ymin, float * ymax)
02975 {
02976     SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
02977 
02978     /* if not already done, load / initialize data */
02979     get_sequence_effect(seq);
02980 
02981     if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
02982         *ymin = -100.0;
02983         *ymax = 100.0;
02984     } else {
02985         if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
02986             *ymin = 0.0;
02987             *ymax = 1.0;
02988         } else {
02989             *ymin = 0.0;
02990             *ymax = seq->len;
02991         }
02992     }   
02993 }
02994 void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
02995 {
02996     int cfra;
02997     float fallback_fac = 1.0f;
02998     SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
02999     FCurve *fcu= NULL;
03000     int flags = v->flags;
03001 
03002     /* if not already done, load / initialize data */
03003     get_sequence_effect(seq);
03004 
03005     if (    (force == FALSE) &&
03006             (seq->len == v->length) &&
03007             (v->frameMap != NULL)
03008     ) {
03009         return;
03010     }
03011     if (    (seq->seq1 == NULL) ||
03012             (seq->len < 1)
03013     ) { /* make coverity happy and check for (CID 598)
03014                          input strip ... */
03015         return;
03016     }
03017 
03018     /* XXX - new in 2.5x. should we use the animation system this way?
03019      * The fcurve is needed because many frames need evaluating at once - campbell */
03020     fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
03021 
03022 
03023     if (!v->frameMap || v->length != seq->len) {
03024         if (v->frameMap) MEM_freeN(v->frameMap);
03025 
03026         v->length = seq->len;
03027 
03028         v->frameMap = MEM_callocN(sizeof(float) * v->length, 
03029                       "speedcontrol frameMap");
03030     }
03031 
03032     fallback_fac = 1.0;
03033 
03034     if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
03035         if (seq->seq1->enddisp != seq->seq1->start
03036             && seq->seq1->len != 0) {
03037             fallback_fac = (float) seq->seq1->len / 
03038                 (float) (seq->seq1->enddisp - seq->seq1->start);
03039             flags = SEQ_SPEED_INTEGRATE;
03040             fcu = NULL;
03041         }
03042     } else {
03043         /* if there is no fcurve, use value as simple multiplier */
03044         if (!fcu) {
03045             fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/
03046         }
03047     }
03048 
03049     if (flags & SEQ_SPEED_INTEGRATE) {
03050         float cursor = 0;
03051         float facf;
03052 
03053         v->frameMap[0] = 0;
03054         v->lastValidFrame = 0;
03055 
03056         for (cfra = 1; cfra < v->length; cfra++) {
03057             if(fcu) {
03058                 facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
03059             } else {
03060                 facf = fallback_fac;
03061             }
03062             facf *= v->globalSpeed;
03063 
03064             cursor += facf;
03065 
03066             if (cursor >= seq->seq1->len) {
03067                 v->frameMap[cfra] = seq->seq1->len - 1;
03068             } else {
03069                 v->frameMap[cfra] = cursor;
03070                 v->lastValidFrame = cfra;
03071             }
03072         }
03073     } else {
03074         float facf;
03075 
03076         v->lastValidFrame = 0;
03077         for (cfra = 0; cfra < v->length; cfra++) {
03078 
03079             if(fcu) {
03080                 facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
03081             } else {
03082                 facf = fallback_fac;
03083             }
03084 
03085             if (flags & SEQ_SPEED_COMPRESS_IPO_Y) {
03086                 facf *= seq->seq1->len;
03087             }
03088             facf *= v->globalSpeed;
03089             
03090             if (facf >= seq->seq1->len) {
03091                 facf = seq->seq1->len - 1;
03092             } else {
03093                 v->lastValidFrame = cfra;
03094             }
03095             v->frameMap[cfra] = facf;
03096         }
03097     }
03098 }
03099 
03100 /* **********************************************************************
03101    sequence effect factory
03102    ********************************************************************** */
03103 
03104 
03105 static void init_noop(struct Sequence *UNUSED(seq))
03106 {
03107 
03108 }
03109 
03110 static void load_noop(struct Sequence *UNUSED(seq))
03111 {
03112 
03113 }
03114 
03115 static void init_plugin_noop(struct Sequence *UNUSED(seq), const char *UNUSED(fname))
03116 {
03117 
03118 }
03119 
03120 static void free_noop(struct Sequence *UNUSED(seq))
03121 {
03122 
03123 }
03124 
03125 static int num_inputs_default(void)
03126 {
03127     return 2;
03128 }
03129 
03130 static int early_out_noop(struct Sequence *UNUSED(seq),
03131               float UNUSED(facf0), float UNUSED(facf1))
03132 {
03133     return 0;
03134 }
03135 
03136 static int early_out_fade(struct Sequence *UNUSED(seq),
03137               float facf0, float facf1)
03138 {
03139     if (facf0 == 0.0f && facf1 == 0.0f) {
03140         return 1;
03141     } else if (facf0 == 1.0f && facf1 == 1.0f) {
03142         return 2;
03143     }
03144     return 0;
03145 }
03146 
03147 static int early_out_mul_input2(struct Sequence *UNUSED(seq),
03148                 float facf0, float facf1)
03149 {
03150     if (facf0 == 0.0f && facf1 == 0.0f) {
03151         return 1;
03152     }
03153     return 0;
03154 }
03155 
03156 static void store_icu_yrange_noop(struct Sequence * UNUSED(seq),
03157                   short UNUSED(adrcode), float *UNUSED(ymin), float *UNUSED(ymax))
03158 {
03159     /* defaults are fine */
03160 }
03161 
03162 static void get_default_fac_noop(struct Sequence *UNUSED(seq), float UNUSED(cfra),
03163                  float * facf0, float * facf1)
03164 {
03165     *facf0 = *facf1 = 1.0;
03166 }
03167 
03168 static void get_default_fac_fade(struct Sequence *seq, float cfra,
03169                  float * facf0, float * facf1)
03170 {
03171     *facf0 = (float)(cfra - seq->startdisp);
03172     *facf1 = (float)(*facf0 + 0.5f);
03173     *facf0 /= seq->len;
03174     *facf1 /= seq->len;
03175 }
03176 
03177 static struct ImBuf * do_overdrop_effect(SeqRenderData context, 
03178                      Sequence *UNUSED(seq), 
03179                      float UNUSED(cfra),
03180                      float facf0, float facf1, 
03181                      struct ImBuf * ibuf1, 
03182                      struct ImBuf * ibuf2, 
03183                      struct ImBuf * ibuf3)
03184 {
03185     struct ImBuf * out = prepare_effect_imbufs(context,ibuf1, ibuf2, ibuf3);
03186     int x = context.rectx;
03187     int y = context.recty;
03188 
03189     if (out->rect_float) {
03190         do_drop_effect_float(
03191             facf0, facf1, x, y,
03192             ibuf1->rect_float, ibuf2->rect_float,
03193             out->rect_float);
03194         do_alphaover_effect_float(
03195             facf0, facf1, x, y,
03196             ibuf1->rect_float, ibuf2->rect_float,
03197             out->rect_float);
03198     } else {
03199         do_drop_effect_byte(
03200             facf0, facf1, x, y,
03201             (char*) ibuf1->rect, 
03202             (char*) ibuf2->rect,
03203             (char*) out->rect);
03204         do_alphaover_effect_byte(
03205             facf0, facf1, x, y,
03206             (char*) ibuf1->rect, (char*) ibuf2->rect,
03207             (char*) out->rect);
03208     }
03209 
03210     return out;
03211 }
03212 
03213 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
03214 {
03215     struct SeqEffectHandle rval;
03216     int sequence_type = seq_type;
03217 
03218     rval.init = init_noop;
03219     rval.init_plugin = init_plugin_noop;
03220     rval.num_inputs = num_inputs_default;
03221     rval.load = load_noop;
03222     rval.free = free_noop;
03223     rval.early_out = early_out_noop;
03224     rval.get_default_fac = get_default_fac_noop;
03225     rval.store_icu_yrange = store_icu_yrange_noop;
03226     rval.execute = NULL;
03227     rval.copy = NULL;
03228 
03229     switch (sequence_type) {
03230     case SEQ_CROSS:
03231         rval.execute = do_cross_effect;
03232         rval.early_out = early_out_fade;
03233         rval.get_default_fac = get_default_fac_fade;
03234         break;
03235     case SEQ_GAMCROSS:
03236         rval.init = init_gammacross;
03237         rval.load = load_gammacross;
03238         rval.free = free_gammacross;
03239         rval.early_out = early_out_fade;
03240         rval.get_default_fac = get_default_fac_fade;
03241         rval.execute = do_gammacross_effect;
03242         break;
03243     case SEQ_ADD:
03244         rval.execute = do_add_effect;
03245         rval.early_out = early_out_mul_input2;
03246         break;
03247     case SEQ_SUB:
03248         rval.execute = do_sub_effect;
03249         rval.early_out = early_out_mul_input2;
03250         break;
03251     case SEQ_MUL:
03252         rval.execute = do_mul_effect;
03253         rval.early_out = early_out_mul_input2;
03254         break;
03255     case SEQ_ALPHAOVER:
03256         rval.init = init_alpha_over_or_under;
03257         rval.execute = do_alphaover_effect;
03258         break;
03259     case SEQ_OVERDROP:
03260         rval.execute = do_overdrop_effect;
03261         break;
03262     case SEQ_ALPHAUNDER:
03263         rval.init = init_alpha_over_or_under;
03264         rval.execute = do_alphaunder_effect;
03265         break;
03266     case SEQ_WIPE:
03267         rval.init = init_wipe_effect;
03268         rval.num_inputs = num_inputs_wipe;
03269         rval.free = free_wipe_effect;
03270         rval.copy = copy_wipe_effect;
03271         rval.early_out = early_out_fade;
03272         rval.get_default_fac = get_default_fac_fade;
03273         rval.execute = do_wipe_effect;
03274         break;
03275     case SEQ_GLOW:
03276         rval.init = init_glow_effect;
03277         rval.num_inputs = num_inputs_glow;
03278         rval.free = free_glow_effect;
03279         rval.copy = copy_glow_effect;
03280         rval.execute = do_glow_effect;
03281         break;
03282     case SEQ_TRANSFORM:
03283         rval.init = init_transform_effect;
03284         rval.num_inputs = num_inputs_transform;
03285         rval.free = free_transform_effect;
03286         rval.copy = copy_transform_effect;
03287         rval.execute = do_transform_effect;
03288         break;
03289     case SEQ_SPEED:
03290         rval.init = init_speed_effect;
03291         rval.num_inputs = num_inputs_speed;
03292         rval.load = load_speed_effect;
03293         rval.free = free_speed_effect;
03294         rval.copy = copy_speed_effect;
03295         rval.execute = do_cross_effect;
03296         rval.early_out = early_out_speed;
03297         rval.store_icu_yrange = store_icu_yrange_speed;
03298         break;
03299     case SEQ_COLOR:
03300         rval.init = init_solid_color;
03301         rval.num_inputs = num_inputs_color;
03302         rval.early_out = early_out_color;
03303         rval.free = free_solid_color;
03304         rval.copy = copy_solid_color;
03305         rval.execute = do_solid_color;
03306         break;
03307     case SEQ_PLUGIN:
03308         rval.init_plugin = init_plugin;
03309         rval.num_inputs = num_inputs_plugin;
03310         rval.load = load_plugin;
03311         rval.free = free_plugin;
03312         rval.copy = copy_plugin;
03313         rval.execute = do_plugin_effect;
03314         rval.early_out = do_plugin_early_out;
03315         rval.get_default_fac = get_default_fac_fade;
03316         break;
03317     case SEQ_MULTICAM:
03318         rval.num_inputs = num_inputs_multicam;
03319         rval.early_out = early_out_multicam;
03320         rval.execute = do_multicam;
03321         break;
03322     case SEQ_ADJUSTMENT:
03323         rval.num_inputs = num_inputs_adjustment;
03324         rval.early_out = early_out_adjustment;
03325         rval.execute = do_adjustment;
03326         break;
03327     }
03328 
03329     return rval;
03330 }
03331 
03332 
03333 struct SeqEffectHandle get_sequence_effect(Sequence * seq)
03334 {
03335     struct SeqEffectHandle rval= {NULL};
03336 
03337     if (seq->type & SEQ_EFFECT) {
03338         rval = get_sequence_effect_impl(seq->type);
03339         if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
03340             rval.load(seq);
03341             seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
03342         }
03343     }
03344 
03345     return rval;
03346 }
03347 
03348 struct SeqEffectHandle get_sequence_blend(Sequence * seq)
03349 {
03350     struct SeqEffectHandle rval= {NULL};
03351 
03352     if (seq->blend_mode != 0) {
03353         rval = get_sequence_effect_impl(seq->blend_mode);
03354         if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
03355             rval.load(seq);
03356             seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
03357         }
03358     }
03359 
03360     return rval;
03361 }
03362 
03363 int get_sequence_effect_num_inputs(int seq_type)
03364 {
03365     struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
03366 
03367     int cnt = rval.num_inputs();
03368     if (rval.execute) {
03369         return cnt;
03370     }
03371     return 0;
03372 }