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