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