|
Blender
V2.59
|
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 }