1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 *
19 * - Blender Foundation, 2003-2009
20 * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
21 */
22
23 /** \file
24 * \ingroup bke
25 */
26
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_listbase.h"
34 #include "BLI_math.h" /* windows needs for M_PI */
35 #include "BLI_path_util.h"
36 #include "BLI_rect.h"
37 #include "BLI_string.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40
41 #include "DNA_anim_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_sequence_types.h"
44 #include "DNA_space_types.h"
45
46 #include "BKE_fcurve.h"
47 #include "BKE_lib_id.h"
48 #include "BKE_main.h"
49 #include "BKE_sequencer.h"
50
51 #include "IMB_colormanagement.h"
52 #include "IMB_imbuf.h"
53 #include "IMB_imbuf_types.h"
54 #include "IMB_metadata.h"
55
56 #include "BLI_math_color_blend.h"
57
58 #include "RNA_access.h"
59
60 #include "RE_pipeline.h"
61
62 #include "BLF_api.h"
63
64 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type);
65
slice_get_byte_buffers(const SeqRenderData * context,const ImBuf * ibuf1,const ImBuf * ibuf2,const ImBuf * ibuf3,const ImBuf * out,int start_line,unsigned char ** rect1,unsigned char ** rect2,unsigned char ** rect3,unsigned char ** rect_out)66 static void slice_get_byte_buffers(const SeqRenderData *context,
67 const ImBuf *ibuf1,
68 const ImBuf *ibuf2,
69 const ImBuf *ibuf3,
70 const ImBuf *out,
71 int start_line,
72 unsigned char **rect1,
73 unsigned char **rect2,
74 unsigned char **rect3,
75 unsigned char **rect_out)
76 {
77 int offset = 4 * start_line * context->rectx;
78
79 *rect1 = (unsigned char *)ibuf1->rect + offset;
80 *rect_out = (unsigned char *)out->rect + offset;
81
82 if (ibuf2) {
83 *rect2 = (unsigned char *)ibuf2->rect + offset;
84 }
85
86 if (ibuf3) {
87 *rect3 = (unsigned char *)ibuf3->rect + offset;
88 }
89 }
90
slice_get_float_buffers(const SeqRenderData * context,const ImBuf * ibuf1,const ImBuf * ibuf2,const ImBuf * ibuf3,const ImBuf * out,int start_line,float ** rect1,float ** rect2,float ** rect3,float ** rect_out)91 static void slice_get_float_buffers(const SeqRenderData *context,
92 const ImBuf *ibuf1,
93 const ImBuf *ibuf2,
94 const ImBuf *ibuf3,
95 const ImBuf *out,
96 int start_line,
97 float **rect1,
98 float **rect2,
99 float **rect3,
100 float **rect_out)
101 {
102 int offset = 4 * start_line * context->rectx;
103
104 *rect1 = ibuf1->rect_float + offset;
105 *rect_out = out->rect_float + offset;
106
107 if (ibuf2) {
108 *rect2 = ibuf2->rect_float + offset;
109 }
110
111 if (ibuf3) {
112 *rect3 = ibuf3->rect_float + offset;
113 }
114 }
115
116 /*********************** Glow effect *************************/
117
118 enum {
119 GlowR = 0,
120 GlowG = 1,
121 GlowB = 2,
122 GlowA = 3,
123 };
124
prepare_effect_imbufs(const SeqRenderData * context,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)125 static ImBuf *prepare_effect_imbufs(const SeqRenderData *context,
126 ImBuf *ibuf1,
127 ImBuf *ibuf2,
128 ImBuf *ibuf3)
129 {
130 ImBuf *out;
131 Scene *scene = context->scene;
132 int x = context->rectx;
133 int y = context->recty;
134
135 if (!ibuf1 && !ibuf2 && !ibuf3) {
136 /* hmmm, global float option ? */
137 out = IMB_allocImBuf(x, y, 32, IB_rect);
138 }
139 else if ((ibuf1 && ibuf1->rect_float) || (ibuf2 && ibuf2->rect_float) ||
140 (ibuf3 && ibuf3->rect_float)) {
141 /* if any inputs are rectfloat, output is float too */
142
143 out = IMB_allocImBuf(x, y, 32, IB_rectfloat);
144 }
145 else {
146 out = IMB_allocImBuf(x, y, 32, IB_rect);
147 }
148
149 if (out->rect_float) {
150 if (ibuf1 && !ibuf1->rect_float) {
151 BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true);
152 }
153
154 if (ibuf2 && !ibuf2->rect_float) {
155 BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true);
156 }
157
158 if (ibuf3 && !ibuf3->rect_float) {
159 BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true);
160 }
161
162 IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name);
163 }
164 else {
165 if (ibuf1 && !ibuf1->rect) {
166 IMB_rect_from_float(ibuf1);
167 }
168
169 if (ibuf2 && !ibuf2->rect) {
170 IMB_rect_from_float(ibuf2);
171 }
172
173 if (ibuf3 && !ibuf3->rect) {
174 IMB_rect_from_float(ibuf3);
175 }
176 }
177
178 /* If effect only affecting a single channel, forward input's metadata to the output. */
179 if (ibuf1 != NULL && ibuf1 == ibuf2 && ibuf2 == ibuf3) {
180 IMB_metadata_copy(out, ibuf1);
181 }
182
183 return out;
184 }
185
186 /*********************** Alpha Over *************************/
187
init_alpha_over_or_under(Sequence * seq)188 static void init_alpha_over_or_under(Sequence *seq)
189 {
190 Sequence *seq1 = seq->seq1;
191 Sequence *seq2 = seq->seq2;
192
193 seq->seq2 = seq1;
194 seq->seq1 = seq2;
195 }
196
do_alphaover_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)197 static void do_alphaover_effect_byte(float facf0,
198 float facf1,
199 int x,
200 int y,
201 unsigned char *rect1,
202 unsigned char *rect2,
203 unsigned char *out)
204 {
205 float fac2, mfac, fac, fac4;
206 int xo;
207 unsigned char *cp1, *cp2, *rt;
208 float tempc[4], rt1[4], rt2[4];
209
210 xo = x;
211 cp1 = rect1;
212 cp2 = rect2;
213 rt = out;
214
215 fac2 = facf0;
216 fac4 = facf1;
217
218 while (y--) {
219 x = xo;
220 while (x--) {
221 /* rt = rt1 over rt2 (alpha from rt1) */
222
223 straight_uchar_to_premul_float(rt1, cp1);
224 straight_uchar_to_premul_float(rt2, cp2);
225
226 fac = fac2;
227 mfac = 1.0f - fac2 * rt1[3];
228
229 if (fac <= 0.0f) {
230 *((unsigned int *)rt) = *((unsigned int *)cp2);
231 }
232 else if (mfac <= 0.0f) {
233 *((unsigned int *)rt) = *((unsigned int *)cp1);
234 }
235 else {
236 tempc[0] = fac * rt1[0] + mfac * rt2[0];
237 tempc[1] = fac * rt1[1] + mfac * rt2[1];
238 tempc[2] = fac * rt1[2] + mfac * rt2[2];
239 tempc[3] = fac * rt1[3] + mfac * rt2[3];
240
241 premul_float_to_straight_uchar(rt, tempc);
242 }
243 cp1 += 4;
244 cp2 += 4;
245 rt += 4;
246 }
247
248 if (y == 0) {
249 break;
250 }
251 y--;
252
253 x = xo;
254 while (x--) {
255 straight_uchar_to_premul_float(rt1, cp1);
256 straight_uchar_to_premul_float(rt2, cp2);
257
258 fac = fac4;
259 mfac = 1.0f - (fac4 * rt1[3]);
260
261 if (fac <= 0.0f) {
262 *((unsigned int *)rt) = *((unsigned int *)cp2);
263 }
264 else if (mfac <= 0.0f) {
265 *((unsigned int *)rt) = *((unsigned int *)cp1);
266 }
267 else {
268 tempc[0] = fac * rt1[0] + mfac * rt2[0];
269 tempc[1] = fac * rt1[1] + mfac * rt2[1];
270 tempc[2] = fac * rt1[2] + mfac * rt2[2];
271 tempc[3] = fac * rt1[3] + mfac * rt2[3];
272
273 premul_float_to_straight_uchar(rt, tempc);
274 }
275 cp1 += 4;
276 cp2 += 4;
277 rt += 4;
278 }
279 }
280 }
281
do_alphaover_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)282 static void do_alphaover_effect_float(
283 float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
284 {
285 float fac2, mfac, fac, fac4;
286 int xo;
287 float *rt1, *rt2, *rt;
288
289 xo = x;
290 rt1 = rect1;
291 rt2 = rect2;
292 rt = out;
293
294 fac2 = facf0;
295 fac4 = facf1;
296
297 while (y--) {
298 x = xo;
299 while (x--) {
300 /* rt = rt1 over rt2 (alpha from rt1) */
301
302 fac = fac2;
303 mfac = 1.0f - (fac2 * rt1[3]);
304
305 if (fac <= 0.0f) {
306 memcpy(rt, rt2, sizeof(float[4]));
307 }
308 else if (mfac <= 0) {
309 memcpy(rt, rt1, sizeof(float[4]));
310 }
311 else {
312 rt[0] = fac * rt1[0] + mfac * rt2[0];
313 rt[1] = fac * rt1[1] + mfac * rt2[1];
314 rt[2] = fac * rt1[2] + mfac * rt2[2];
315 rt[3] = fac * rt1[3] + mfac * rt2[3];
316 }
317 rt1 += 4;
318 rt2 += 4;
319 rt += 4;
320 }
321
322 if (y == 0) {
323 break;
324 }
325 y--;
326
327 x = xo;
328 while (x--) {
329 fac = fac4;
330 mfac = 1.0f - (fac4 * rt1[3]);
331
332 if (fac <= 0.0f) {
333 memcpy(rt, rt2, sizeof(float[4]));
334 }
335 else if (mfac <= 0.0f) {
336 memcpy(rt, rt1, sizeof(float[4]));
337 }
338 else {
339 rt[0] = fac * rt1[0] + mfac * rt2[0];
340 rt[1] = fac * rt1[1] + mfac * rt2[1];
341 rt[2] = fac * rt1[2] + mfac * rt2[2];
342 rt[3] = fac * rt1[3] + mfac * rt2[3];
343 }
344 rt1 += 4;
345 rt2 += 4;
346 rt += 4;
347 }
348 }
349 }
350
do_alphaover_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)351 static void do_alphaover_effect(const SeqRenderData *context,
352 Sequence *UNUSED(seq),
353 float UNUSED(cfra),
354 float facf0,
355 float facf1,
356 ImBuf *ibuf1,
357 ImBuf *ibuf2,
358 ImBuf *UNUSED(ibuf3),
359 int start_line,
360 int total_lines,
361 ImBuf *out)
362 {
363 if (out->rect_float) {
364 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
365
366 slice_get_float_buffers(
367 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
368
369 do_alphaover_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
370 }
371 else {
372 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
373
374 slice_get_byte_buffers(
375 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
376
377 do_alphaover_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
378 }
379 }
380
381 /*********************** Alpha Under *************************/
382
do_alphaunder_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)383 static void do_alphaunder_effect_byte(float facf0,
384 float facf1,
385 int x,
386 int y,
387 unsigned char *rect1,
388 unsigned char *rect2,
389 unsigned char *out)
390 {
391 float fac2, fac, fac4;
392 int xo;
393 unsigned char *cp1, *cp2, *rt;
394 float tempc[4], rt1[4], rt2[4];
395
396 xo = x;
397 cp1 = rect1;
398 cp2 = rect2;
399 rt = out;
400
401 fac2 = facf0;
402 fac4 = facf1;
403
404 while (y--) {
405 x = xo;
406 while (x--) {
407 /* rt = rt1 under rt2 (alpha from rt2) */
408 straight_uchar_to_premul_float(rt1, cp1);
409 straight_uchar_to_premul_float(rt2, cp2);
410
411 /* this complex optimization is because the
412 * 'skybuf' can be crossed in
413 */
414 if (rt2[3] <= 0.0f && fac2 >= 1.0f) {
415 *((unsigned int *)rt) = *((unsigned int *)cp1);
416 }
417 else if (rt2[3] >= 1.0f) {
418 *((unsigned int *)rt) = *((unsigned int *)cp2);
419 }
420 else {
421 fac = (fac2 * (1.0f - rt2[3]));
422
423 if (fac <= 0) {
424 *((unsigned int *)rt) = *((unsigned int *)cp2);
425 }
426 else {
427 tempc[0] = (fac * rt1[0] + rt2[0]);
428 tempc[1] = (fac * rt1[1] + rt2[1]);
429 tempc[2] = (fac * rt1[2] + rt2[2]);
430 tempc[3] = (fac * rt1[3] + rt2[3]);
431
432 premul_float_to_straight_uchar(rt, tempc);
433 }
434 }
435 cp1 += 4;
436 cp2 += 4;
437 rt += 4;
438 }
439
440 if (y == 0) {
441 break;
442 }
443 y--;
444
445 x = xo;
446 while (x--) {
447 straight_uchar_to_premul_float(rt1, cp1);
448 straight_uchar_to_premul_float(rt2, cp2);
449
450 if (rt2[3] <= 0.0f && fac4 >= 1.0f) {
451 *((unsigned int *)rt) = *((unsigned int *)cp1);
452 }
453 else if (rt2[3] >= 1.0f) {
454 *((unsigned int *)rt) = *((unsigned int *)cp2);
455 }
456 else {
457 fac = (fac4 * (1.0f - rt2[3]));
458
459 if (fac <= 0) {
460 *((unsigned int *)rt) = *((unsigned int *)cp2);
461 }
462 else {
463 tempc[0] = (fac * rt1[0] + rt2[0]);
464 tempc[1] = (fac * rt1[1] + rt2[1]);
465 tempc[2] = (fac * rt1[2] + rt2[2]);
466 tempc[3] = (fac * rt1[3] + rt2[3]);
467
468 premul_float_to_straight_uchar(rt, tempc);
469 }
470 }
471 cp1 += 4;
472 cp2 += 4;
473 rt += 4;
474 }
475 }
476 }
477
do_alphaunder_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)478 static void do_alphaunder_effect_float(
479 float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
480 {
481 float fac2, fac, fac4;
482 int xo;
483 float *rt1, *rt2, *rt;
484
485 xo = x;
486 rt1 = rect1;
487 rt2 = rect2;
488 rt = out;
489
490 fac2 = facf0;
491 fac4 = facf1;
492
493 while (y--) {
494 x = xo;
495 while (x--) {
496 /* rt = rt1 under rt2 (alpha from rt2) */
497
498 /* this complex optimization is because the
499 * 'skybuf' can be crossed in
500 */
501 if (rt2[3] <= 0 && fac2 >= 1.0f) {
502 memcpy(rt, rt1, sizeof(float[4]));
503 }
504 else if (rt2[3] >= 1.0f) {
505 memcpy(rt, rt2, sizeof(float[4]));
506 }
507 else {
508 fac = fac2 * (1.0f - rt2[3]);
509
510 if (fac == 0) {
511 memcpy(rt, rt2, sizeof(float[4]));
512 }
513 else {
514 rt[0] = fac * rt1[0] + rt2[0];
515 rt[1] = fac * rt1[1] + rt2[1];
516 rt[2] = fac * rt1[2] + rt2[2];
517 rt[3] = fac * rt1[3] + rt2[3];
518 }
519 }
520 rt1 += 4;
521 rt2 += 4;
522 rt += 4;
523 }
524
525 if (y == 0) {
526 break;
527 }
528 y--;
529
530 x = xo;
531 while (x--) {
532 if (rt2[3] <= 0 && fac4 >= 1.0f) {
533 memcpy(rt, rt1, sizeof(float[4]));
534 }
535 else if (rt2[3] >= 1.0f) {
536 memcpy(rt, rt2, sizeof(float[4]));
537 }
538 else {
539 fac = fac4 * (1.0f - rt2[3]);
540
541 if (fac == 0) {
542 memcpy(rt, rt2, sizeof(float[4]));
543 }
544 else {
545 rt[0] = fac * rt1[0] + rt2[0];
546 rt[1] = fac * rt1[1] + rt2[1];
547 rt[2] = fac * rt1[2] + rt2[2];
548 rt[3] = fac * rt1[3] + rt2[3];
549 }
550 }
551 rt1 += 4;
552 rt2 += 4;
553 rt += 4;
554 }
555 }
556 }
557
do_alphaunder_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)558 static void do_alphaunder_effect(const SeqRenderData *context,
559 Sequence *UNUSED(seq),
560 float UNUSED(cfra),
561 float facf0,
562 float facf1,
563 ImBuf *ibuf1,
564 ImBuf *ibuf2,
565 ImBuf *UNUSED(ibuf3),
566 int start_line,
567 int total_lines,
568 ImBuf *out)
569 {
570 if (out->rect_float) {
571 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
572
573 slice_get_float_buffers(
574 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
575
576 do_alphaunder_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
577 }
578 else {
579 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
580
581 slice_get_byte_buffers(
582 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
583
584 do_alphaunder_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
585 }
586 }
587
588 /*********************** Cross *************************/
589
do_cross_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)590 static void do_cross_effect_byte(float facf0,
591 float facf1,
592 int x,
593 int y,
594 unsigned char *rect1,
595 unsigned char *rect2,
596 unsigned char *out)
597 {
598 int fac1, fac2, fac3, fac4;
599 int xo;
600 unsigned char *rt1, *rt2, *rt;
601
602 xo = x;
603 rt1 = rect1;
604 rt2 = rect2;
605 rt = out;
606
607 fac2 = (int)(256.0f * facf0);
608 fac1 = 256 - fac2;
609 fac4 = (int)(256.0f * facf1);
610 fac3 = 256 - fac4;
611
612 while (y--) {
613 x = xo;
614 while (x--) {
615 rt[0] = (fac1 * rt1[0] + fac2 * rt2[0]) >> 8;
616 rt[1] = (fac1 * rt1[1] + fac2 * rt2[1]) >> 8;
617 rt[2] = (fac1 * rt1[2] + fac2 * rt2[2]) >> 8;
618 rt[3] = (fac1 * rt1[3] + fac2 * rt2[3]) >> 8;
619
620 rt1 += 4;
621 rt2 += 4;
622 rt += 4;
623 }
624
625 if (y == 0) {
626 break;
627 }
628 y--;
629
630 x = xo;
631 while (x--) {
632 rt[0] = (fac3 * rt1[0] + fac4 * rt2[0]) >> 8;
633 rt[1] = (fac3 * rt1[1] + fac4 * rt2[1]) >> 8;
634 rt[2] = (fac3 * rt1[2] + fac4 * rt2[2]) >> 8;
635 rt[3] = (fac3 * rt1[3] + fac4 * rt2[3]) >> 8;
636
637 rt1 += 4;
638 rt2 += 4;
639 rt += 4;
640 }
641 }
642 }
643
do_cross_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)644 static void do_cross_effect_float(
645 float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
646 {
647 float fac1, fac2, fac3, fac4;
648 int xo;
649 float *rt1, *rt2, *rt;
650
651 xo = x;
652 rt1 = rect1;
653 rt2 = rect2;
654 rt = out;
655
656 fac2 = facf0;
657 fac1 = 1.0f - fac2;
658 fac4 = facf1;
659 fac3 = 1.0f - fac4;
660
661 while (y--) {
662 x = xo;
663 while (x--) {
664 rt[0] = fac1 * rt1[0] + fac2 * rt2[0];
665 rt[1] = fac1 * rt1[1] + fac2 * rt2[1];
666 rt[2] = fac1 * rt1[2] + fac2 * rt2[2];
667 rt[3] = fac1 * rt1[3] + fac2 * rt2[3];
668
669 rt1 += 4;
670 rt2 += 4;
671 rt += 4;
672 }
673
674 if (y == 0) {
675 break;
676 }
677 y--;
678
679 x = xo;
680 while (x--) {
681 rt[0] = fac3 * rt1[0] + fac4 * rt2[0];
682 rt[1] = fac3 * rt1[1] + fac4 * rt2[1];
683 rt[2] = fac3 * rt1[2] + fac4 * rt2[2];
684 rt[3] = fac3 * rt1[3] + fac4 * rt2[3];
685
686 rt1 += 4;
687 rt2 += 4;
688 rt += 4;
689 }
690 }
691 }
692
do_cross_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)693 static void do_cross_effect(const SeqRenderData *context,
694 Sequence *UNUSED(seq),
695 float UNUSED(cfra),
696 float facf0,
697 float facf1,
698 ImBuf *ibuf1,
699 ImBuf *ibuf2,
700 ImBuf *UNUSED(ibuf3),
701 int start_line,
702 int total_lines,
703 ImBuf *out)
704 {
705 if (out->rect_float) {
706 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
707
708 slice_get_float_buffers(
709 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
710
711 do_cross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
712 }
713 else {
714 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
715
716 slice_get_byte_buffers(
717 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
718
719 do_cross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
720 }
721 }
722
723 /*********************** Gamma Cross *************************/
724
725 /* copied code from initrender.c */
726 static unsigned short gamtab[65536];
727 static unsigned short igamtab1[256];
728 static bool gamma_tabs_init = false;
729
730 #define RE_GAMMA_TABLE_SIZE 400
731
732 static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
733 static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
734 static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
735 static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
736 static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1];
737 static float color_step;
738 static float inv_color_step;
739 static float valid_gamma;
740 static float valid_inv_gamma;
741
makeGammaTables(float gamma)742 static void makeGammaTables(float gamma)
743 {
744 /* we need two tables: one forward, one backward */
745 int i;
746
747 valid_gamma = gamma;
748 valid_inv_gamma = 1.0f / gamma;
749 color_step = 1.0f / RE_GAMMA_TABLE_SIZE;
750 inv_color_step = (float)RE_GAMMA_TABLE_SIZE;
751
752 /* We could squeeze out the two range tables to gain some memory */
753 for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
754 color_domain_table[i] = i * color_step;
755 gamma_range_table[i] = pow(color_domain_table[i], valid_gamma);
756 inv_gamma_range_table[i] = pow(color_domain_table[i], valid_inv_gamma);
757 }
758
759 /* The end of the table should match 1.0 carefully. In order to avoid
760 * rounding errors, we just set this explicitly. The last segment may
761 * have a different length than the other segments, but our
762 * interpolation is insensitive to that
763 */
764 color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0;
765 gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
766 inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
767
768 /* To speed up calculations, we make these calc factor tables. They are
769 * multiplication factors used in scaling the interpolation
770 */
771 for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
772 gamfactor_table[i] = inv_color_step * (gamma_range_table[i + 1] - gamma_range_table[i]);
773 inv_gamfactor_table[i] = inv_color_step *
774 (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]);
775 }
776 }
777
gammaCorrect(float c)778 static float gammaCorrect(float c)
779 {
780 int i;
781 float res;
782
783 i = floorf(c * inv_color_step);
784 /* Clip to range [0, 1]: outside, just do the complete calculation.
785 * We may have some performance problems here. Stretching up the LUT
786 * may help solve that, by exchanging LUT size for the interpolation.
787 * Negative colors are explicitly handled.
788 */
789 if (UNLIKELY(i < 0)) {
790 res = -powf(-c, valid_gamma);
791 }
792 else if (i >= RE_GAMMA_TABLE_SIZE) {
793 res = powf(c, valid_gamma);
794 }
795 else {
796 res = gamma_range_table[i] + ((c - color_domain_table[i]) * gamfactor_table[i]);
797 }
798
799 return res;
800 }
801
802 /* ------------------------------------------------------------------------- */
803
invGammaCorrect(float c)804 static float invGammaCorrect(float c)
805 {
806 int i;
807 float res = 0.0;
808
809 i = floorf(c * inv_color_step);
810 /* Negative colors are explicitly handled */
811 if (UNLIKELY(i < 0)) {
812 res = -powf(-c, valid_inv_gamma);
813 }
814 else if (i >= RE_GAMMA_TABLE_SIZE) {
815 res = powf(c, valid_inv_gamma);
816 }
817 else {
818 res = inv_gamma_range_table[i] + ((c - color_domain_table[i]) * inv_gamfactor_table[i]);
819 }
820
821 return res;
822 }
823
gamtabs(float gamma)824 static void gamtabs(float gamma)
825 {
826 float val, igamma = 1.0f / gamma;
827 int a;
828
829 /* gamtab: in short, out short */
830 for (a = 0; a < 65536; a++) {
831 val = a;
832 val /= 65535.0f;
833
834 if (gamma == 2.0f) {
835 val = sqrtf(val);
836 }
837 else if (gamma != 1.0f) {
838 val = powf(val, igamma);
839 }
840
841 gamtab[a] = (65535.99f * val);
842 }
843 /* inverse gamtab1 : in byte, out short */
844 for (a = 1; a <= 256; a++) {
845 if (gamma == 2.0f) {
846 igamtab1[a - 1] = a * a - 1;
847 }
848 else if (gamma == 1.0f) {
849 igamtab1[a - 1] = 256 * a - 1;
850 }
851 else {
852 val = a / 256.0f;
853 igamtab1[a - 1] = (65535.0 * pow(val, gamma)) - 1;
854 }
855 }
856 }
857
build_gammatabs(void)858 static void build_gammatabs(void)
859 {
860 if (gamma_tabs_init == false) {
861 gamtabs(2.0f);
862 makeGammaTables(2.0f);
863 gamma_tabs_init = true;
864 }
865 }
866
init_gammacross(Sequence * UNUSED (seq))867 static void init_gammacross(Sequence *UNUSED(seq))
868 {
869 }
870
load_gammacross(Sequence * UNUSED (seq))871 static void load_gammacross(Sequence *UNUSED(seq))
872 {
873 }
874
free_gammacross(Sequence * UNUSED (seq),const bool UNUSED (do_id_user))875 static void free_gammacross(Sequence *UNUSED(seq), const bool UNUSED(do_id_user))
876 {
877 }
878
do_gammacross_effect_byte(float facf0,float UNUSED (facf1),int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)879 static void do_gammacross_effect_byte(float facf0,
880 float UNUSED(facf1),
881 int x,
882 int y,
883 unsigned char *rect1,
884 unsigned char *rect2,
885 unsigned char *out)
886 {
887 float fac1, fac2;
888 int xo;
889 unsigned char *cp1, *cp2, *rt;
890 float rt1[4], rt2[4], tempc[4];
891
892 xo = x;
893 cp1 = rect1;
894 cp2 = rect2;
895 rt = out;
896
897 fac2 = facf0;
898 fac1 = 1.0f - fac2;
899
900 while (y--) {
901 x = xo;
902 while (x--) {
903 straight_uchar_to_premul_float(rt1, cp1);
904 straight_uchar_to_premul_float(rt2, cp2);
905
906 tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
907 tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
908 tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
909 tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
910
911 premul_float_to_straight_uchar(rt, tempc);
912 cp1 += 4;
913 cp2 += 4;
914 rt += 4;
915 }
916
917 if (y == 0) {
918 break;
919 }
920 y--;
921
922 x = xo;
923 while (x--) {
924 straight_uchar_to_premul_float(rt1, cp1);
925 straight_uchar_to_premul_float(rt2, cp2);
926
927 tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
928 tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
929 tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
930 tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
931
932 premul_float_to_straight_uchar(rt, tempc);
933 cp1 += 4;
934 cp2 += 4;
935 rt += 4;
936 }
937 }
938 }
939
do_gammacross_effect_float(float facf0,float UNUSED (facf1),int x,int y,float * rect1,float * rect2,float * out)940 static void do_gammacross_effect_float(
941 float facf0, float UNUSED(facf1), int x, int y, float *rect1, float *rect2, float *out)
942 {
943 float fac1, fac2;
944 int xo;
945 float *rt1, *rt2, *rt;
946
947 xo = x;
948 rt1 = rect1;
949 rt2 = rect2;
950 rt = out;
951
952 fac2 = facf0;
953 fac1 = 1.0f - fac2;
954
955 while (y--) {
956 x = xo * 4;
957 while (x--) {
958 *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
959 rt1++;
960 rt2++;
961 rt++;
962 }
963
964 if (y == 0) {
965 break;
966 }
967 y--;
968
969 x = xo * 4;
970 while (x--) {
971 *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
972
973 rt1++;
974 rt2++;
975 rt++;
976 }
977 }
978 }
979
gammacross_init_execution(const SeqRenderData * context,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)980 static struct ImBuf *gammacross_init_execution(const SeqRenderData *context,
981 ImBuf *ibuf1,
982 ImBuf *ibuf2,
983 ImBuf *ibuf3)
984 {
985 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
986 build_gammatabs();
987
988 return out;
989 }
990
do_gammacross_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)991 static void do_gammacross_effect(const SeqRenderData *context,
992 Sequence *UNUSED(seq),
993 float UNUSED(cfra),
994 float facf0,
995 float facf1,
996 ImBuf *ibuf1,
997 ImBuf *ibuf2,
998 ImBuf *UNUSED(ibuf3),
999 int start_line,
1000 int total_lines,
1001 ImBuf *out)
1002 {
1003 if (out->rect_float) {
1004 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1005
1006 slice_get_float_buffers(
1007 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1008
1009 do_gammacross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1010 }
1011 else {
1012 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1013
1014 slice_get_byte_buffers(
1015 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1016
1017 do_gammacross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1018 }
1019 }
1020
1021 /*********************** Add *************************/
1022
do_add_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)1023 static void do_add_effect_byte(float facf0,
1024 float facf1,
1025 int x,
1026 int y,
1027 unsigned char *rect1,
1028 unsigned char *rect2,
1029 unsigned char *out)
1030 {
1031 int xo, fac1, fac3;
1032 unsigned char *cp1, *cp2, *rt;
1033
1034 xo = x;
1035 cp1 = rect1;
1036 cp2 = rect2;
1037 rt = out;
1038
1039 fac1 = (int)(256.0f * facf0);
1040 fac3 = (int)(256.0f * facf1);
1041
1042 while (y--) {
1043 x = xo;
1044
1045 while (x--) {
1046 const int m = fac1 * (int)cp2[3];
1047 rt[0] = min_ii(cp1[0] + ((m * cp2[0]) >> 16), 255);
1048 rt[1] = min_ii(cp1[1] + ((m * cp2[1]) >> 16), 255);
1049 rt[2] = min_ii(cp1[2] + ((m * cp2[2]) >> 16), 255);
1050 rt[3] = cp1[3];
1051
1052 cp1 += 4;
1053 cp2 += 4;
1054 rt += 4;
1055 }
1056
1057 if (y == 0) {
1058 break;
1059 }
1060 y--;
1061
1062 x = xo;
1063 while (x--) {
1064 const int m = fac3 * (int)cp2[3];
1065 rt[0] = min_ii(cp1[0] + ((m * cp2[0]) >> 16), 255);
1066 rt[1] = min_ii(cp1[1] + ((m * cp2[1]) >> 16), 255);
1067 rt[2] = min_ii(cp1[2] + ((m * cp2[2]) >> 16), 255);
1068 rt[3] = cp1[3];
1069
1070 cp1 += 4;
1071 cp2 += 4;
1072 rt += 4;
1073 }
1074 }
1075 }
1076
do_add_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)1077 static void do_add_effect_float(
1078 float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
1079 {
1080 int xo;
1081 float fac1, fac3;
1082 float *rt1, *rt2, *rt;
1083
1084 xo = x;
1085 rt1 = rect1;
1086 rt2 = rect2;
1087 rt = out;
1088
1089 fac1 = facf0;
1090 fac3 = facf1;
1091
1092 while (y--) {
1093 x = xo;
1094 while (x--) {
1095 const float m = (1.0f - (rt1[3] * (1.0f - fac1))) * rt2[3];
1096 rt[0] = rt1[0] + m * rt2[0];
1097 rt[1] = rt1[1] + m * rt2[1];
1098 rt[2] = rt1[2] + m * rt2[2];
1099 rt[3] = rt1[3];
1100
1101 rt1 += 4;
1102 rt2 += 4;
1103 rt += 4;
1104 }
1105
1106 if (y == 0) {
1107 break;
1108 }
1109 y--;
1110
1111 x = xo;
1112 while (x--) {
1113 const float m = (1.0f - (rt1[3] * (1.0f - fac3))) * rt2[3];
1114 rt[0] = rt1[0] + m * rt2[0];
1115 rt[1] = rt1[1] + m * rt2[1];
1116 rt[2] = rt1[2] + m * rt2[2];
1117 rt[3] = rt1[3];
1118
1119 rt1 += 4;
1120 rt2 += 4;
1121 rt += 4;
1122 }
1123 }
1124 }
1125
do_add_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1126 static void do_add_effect(const SeqRenderData *context,
1127 Sequence *UNUSED(seq),
1128 float UNUSED(cfra),
1129 float facf0,
1130 float facf1,
1131 ImBuf *ibuf1,
1132 ImBuf *ibuf2,
1133 ImBuf *UNUSED(ibuf3),
1134 int start_line,
1135 int total_lines,
1136 ImBuf *out)
1137 {
1138 if (out->rect_float) {
1139 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1140
1141 slice_get_float_buffers(
1142 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1143
1144 do_add_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1145 }
1146 else {
1147 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1148
1149 slice_get_byte_buffers(
1150 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1151
1152 do_add_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1153 }
1154 }
1155
1156 /*********************** Sub *************************/
1157
do_sub_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)1158 static void do_sub_effect_byte(float facf0,
1159 float facf1,
1160 int x,
1161 int y,
1162 unsigned char *rect1,
1163 unsigned char *rect2,
1164 unsigned char *out)
1165 {
1166 int xo, fac1, fac3;
1167 unsigned char *cp1, *cp2, *rt;
1168
1169 xo = x;
1170 cp1 = rect1;
1171 cp2 = rect2;
1172 rt = out;
1173
1174 fac1 = (int)(256.0f * facf0);
1175 fac3 = (int)(256.0f * facf1);
1176
1177 while (y--) {
1178 x = xo;
1179 while (x--) {
1180 const int m = fac1 * (int)cp2[3];
1181 rt[0] = max_ii(cp1[0] - ((m * cp2[0]) >> 16), 0);
1182 rt[1] = max_ii(cp1[1] - ((m * cp2[1]) >> 16), 0);
1183 rt[2] = max_ii(cp1[2] - ((m * cp2[2]) >> 16), 0);
1184 rt[3] = cp1[3];
1185
1186 cp1 += 4;
1187 cp2 += 4;
1188 rt += 4;
1189 }
1190
1191 if (y == 0) {
1192 break;
1193 }
1194 y--;
1195
1196 x = xo;
1197 while (x--) {
1198 const int m = fac3 * (int)cp2[3];
1199 rt[0] = max_ii(cp1[0] - ((m * cp2[0]) >> 16), 0);
1200 rt[1] = max_ii(cp1[1] - ((m * cp2[1]) >> 16), 0);
1201 rt[2] = max_ii(cp1[2] - ((m * cp2[2]) >> 16), 0);
1202 rt[3] = cp1[3];
1203
1204 cp1 += 4;
1205 cp2 += 4;
1206 rt += 4;
1207 }
1208 }
1209 }
1210
do_sub_effect_float(float UNUSED (facf0),float facf1,int x,int y,float * rect1,float * rect2,float * out)1211 static void do_sub_effect_float(
1212 float UNUSED(facf0), float facf1, int x, int y, float *rect1, float *rect2, float *out)
1213 {
1214 int xo;
1215 float /* fac1, */ fac3_inv;
1216 float *rt1, *rt2, *rt;
1217
1218 xo = x;
1219 rt1 = rect1;
1220 rt2 = rect2;
1221 rt = out;
1222
1223 /* UNUSED */
1224 // fac1 = facf0;
1225 fac3_inv = 1.0f - facf1;
1226
1227 while (y--) {
1228 x = xo;
1229 while (x--) {
1230 const float m = (1.0f - (rt1[3] * fac3_inv)) * rt2[3];
1231 rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
1232 rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
1233 rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
1234 rt[3] = rt1[3];
1235
1236 rt1 += 4;
1237 rt2 += 4;
1238 rt += 4;
1239 }
1240
1241 if (y == 0) {
1242 break;
1243 }
1244 y--;
1245
1246 x = xo;
1247 while (x--) {
1248 const float m = (1.0f - (rt1[3] * fac3_inv)) * rt2[3];
1249 rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
1250 rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
1251 rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
1252 rt[3] = rt1[3];
1253
1254 rt1 += 4;
1255 rt2 += 4;
1256 rt += 4;
1257 }
1258 }
1259 }
1260
do_sub_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1261 static void do_sub_effect(const SeqRenderData *context,
1262 Sequence *UNUSED(seq),
1263 float UNUSED(cfra),
1264 float facf0,
1265 float facf1,
1266 ImBuf *ibuf1,
1267 ImBuf *ibuf2,
1268 ImBuf *UNUSED(ibuf3),
1269 int start_line,
1270 int total_lines,
1271 ImBuf *out)
1272 {
1273 if (out->rect_float) {
1274 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1275
1276 slice_get_float_buffers(
1277 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1278
1279 do_sub_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1280 }
1281 else {
1282 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1283
1284 slice_get_byte_buffers(
1285 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1286
1287 do_sub_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1288 }
1289 }
1290
1291 /*********************** Drop *************************/
1292
1293 /* Must be > 0 or add precopy, etc to the function */
1294 #define XOFF 8
1295 #define YOFF 8
1296
do_drop_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect2i,unsigned char * rect1i,unsigned char * outi)1297 static void do_drop_effect_byte(float facf0,
1298 float facf1,
1299 int x,
1300 int y,
1301 unsigned char *rect2i,
1302 unsigned char *rect1i,
1303 unsigned char *outi)
1304 {
1305 int temp, fac, fac1, fac2;
1306 unsigned char *rt1, *rt2, *out;
1307 int field = 1;
1308
1309 const int width = x;
1310 const int height = y;
1311 const int xoff = min_ii(XOFF, width);
1312 const int yoff = min_ii(YOFF, height);
1313
1314 fac1 = (int)(70.0f * facf0);
1315 fac2 = (int)(70.0f * facf1);
1316
1317 rt2 = rect2i + yoff * 4 * width;
1318 rt1 = rect1i;
1319 out = outi;
1320 for (y = 0; y < height - yoff; y++) {
1321 if (field) {
1322 fac = fac1;
1323 }
1324 else {
1325 fac = fac2;
1326 }
1327 field = !field;
1328
1329 memcpy(out, rt1, sizeof(*out) * xoff * 4);
1330 rt1 += xoff * 4;
1331 out += xoff * 4;
1332
1333 for (x = xoff; x < width; x++) {
1334 temp = ((fac * rt2[3]) >> 8);
1335
1336 *(out++) = MAX2(0, *rt1 - temp);
1337 rt1++;
1338 *(out++) = MAX2(0, *rt1 - temp);
1339 rt1++;
1340 *(out++) = MAX2(0, *rt1 - temp);
1341 rt1++;
1342 *(out++) = MAX2(0, *rt1 - temp);
1343 rt1++;
1344 rt2 += 4;
1345 }
1346 rt2 += xoff * 4;
1347 }
1348 memcpy(out, rt1, sizeof(*out) * yoff * 4 * width);
1349 }
1350
do_drop_effect_float(float facf0,float facf1,int x,int y,float * rect2i,float * rect1i,float * outi)1351 static void do_drop_effect_float(
1352 float facf0, float facf1, int x, int y, float *rect2i, float *rect1i, float *outi)
1353 {
1354 float temp, fac, fac1, fac2;
1355 float *rt1, *rt2, *out;
1356 int field = 1;
1357
1358 const int width = x;
1359 const int height = y;
1360 const int xoff = min_ii(XOFF, width);
1361 const int yoff = min_ii(YOFF, height);
1362
1363 fac1 = 70.0f * facf0;
1364 fac2 = 70.0f * facf1;
1365
1366 rt2 = rect2i + yoff * 4 * width;
1367 rt1 = rect1i;
1368 out = outi;
1369 for (y = 0; y < height - yoff; y++) {
1370 if (field) {
1371 fac = fac1;
1372 }
1373 else {
1374 fac = fac2;
1375 }
1376 field = !field;
1377
1378 memcpy(out, rt1, sizeof(*out) * xoff * 4);
1379 rt1 += xoff * 4;
1380 out += xoff * 4;
1381
1382 for (x = xoff; x < width; x++) {
1383 temp = fac * rt2[3];
1384
1385 *(out++) = MAX2(0.0f, *rt1 - temp);
1386 rt1++;
1387 *(out++) = MAX2(0.0f, *rt1 - temp);
1388 rt1++;
1389 *(out++) = MAX2(0.0f, *rt1 - temp);
1390 rt1++;
1391 *(out++) = MAX2(0.0f, *rt1 - temp);
1392 rt1++;
1393 rt2 += 4;
1394 }
1395 rt2 += xoff * 4;
1396 }
1397 memcpy(out, rt1, sizeof(*out) * yoff * 4 * width);
1398 }
1399
1400 /*********************** Mul *************************/
1401
do_mul_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)1402 static void do_mul_effect_byte(float facf0,
1403 float facf1,
1404 int x,
1405 int y,
1406 unsigned char *rect1,
1407 unsigned char *rect2,
1408 unsigned char *out)
1409 {
1410 int xo, fac1, fac3;
1411 unsigned char *rt1, *rt2, *rt;
1412
1413 xo = x;
1414 rt1 = rect1;
1415 rt2 = rect2;
1416 rt = out;
1417
1418 fac1 = (int)(256.0f * facf0);
1419 fac3 = (int)(256.0f * facf1);
1420
1421 /* formula:
1422 * fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + axaux = c * px + py * s; //+centx
1423 * yaux = -s * px + c * py; //+centy
1424 */
1425
1426 while (y--) {
1427
1428 x = xo;
1429 while (x--) {
1430
1431 rt[0] = rt1[0] + ((fac1 * rt1[0] * (rt2[0] - 255)) >> 16);
1432 rt[1] = rt1[1] + ((fac1 * rt1[1] * (rt2[1] - 255)) >> 16);
1433 rt[2] = rt1[2] + ((fac1 * rt1[2] * (rt2[2] - 255)) >> 16);
1434 rt[3] = rt1[3] + ((fac1 * rt1[3] * (rt2[3] - 255)) >> 16);
1435
1436 rt1 += 4;
1437 rt2 += 4;
1438 rt += 4;
1439 }
1440
1441 if (y == 0) {
1442 break;
1443 }
1444 y--;
1445
1446 x = xo;
1447 while (x--) {
1448
1449 rt[0] = rt1[0] + ((fac3 * rt1[0] * (rt2[0] - 255)) >> 16);
1450 rt[1] = rt1[1] + ((fac3 * rt1[1] * (rt2[1] - 255)) >> 16);
1451 rt[2] = rt1[2] + ((fac3 * rt1[2] * (rt2[2] - 255)) >> 16);
1452 rt[3] = rt1[3] + ((fac3 * rt1[3] * (rt2[3] - 255)) >> 16);
1453
1454 rt1 += 4;
1455 rt2 += 4;
1456 rt += 4;
1457 }
1458 }
1459 }
1460
do_mul_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)1461 static void do_mul_effect_float(
1462 float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
1463 {
1464 int xo;
1465 float fac1, fac3;
1466 float *rt1, *rt2, *rt;
1467
1468 xo = x;
1469 rt1 = rect1;
1470 rt2 = rect2;
1471 rt = out;
1472
1473 fac1 = facf0;
1474 fac3 = facf1;
1475
1476 /* formula:
1477 * fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + a
1478 */
1479
1480 while (y--) {
1481 x = xo;
1482 while (x--) {
1483 rt[0] = rt1[0] + fac1 * rt1[0] * (rt2[0] - 1.0f);
1484 rt[1] = rt1[1] + fac1 * rt1[1] * (rt2[1] - 1.0f);
1485 rt[2] = rt1[2] + fac1 * rt1[2] * (rt2[2] - 1.0f);
1486 rt[3] = rt1[3] + fac1 * rt1[3] * (rt2[3] - 1.0f);
1487
1488 rt1 += 4;
1489 rt2 += 4;
1490 rt += 4;
1491 }
1492
1493 if (y == 0) {
1494 break;
1495 }
1496 y--;
1497
1498 x = xo;
1499 while (x--) {
1500 rt[0] = rt1[0] + fac3 * rt1[0] * (rt2[0] - 1.0f);
1501 rt[1] = rt1[1] + fac3 * rt1[1] * (rt2[1] - 1.0f);
1502 rt[2] = rt1[2] + fac3 * rt1[2] * (rt2[2] - 1.0f);
1503 rt[3] = rt1[3] + fac3 * rt1[3] * (rt2[3] - 1.0f);
1504
1505 rt1 += 4;
1506 rt2 += 4;
1507 rt += 4;
1508 }
1509 }
1510 }
1511
do_mul_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1512 static void do_mul_effect(const SeqRenderData *context,
1513 Sequence *UNUSED(seq),
1514 float UNUSED(cfra),
1515 float facf0,
1516 float facf1,
1517 ImBuf *ibuf1,
1518 ImBuf *ibuf2,
1519 ImBuf *UNUSED(ibuf3),
1520 int start_line,
1521 int total_lines,
1522 ImBuf *out)
1523 {
1524 if (out->rect_float) {
1525 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1526
1527 slice_get_float_buffers(
1528 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1529
1530 do_mul_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1531 }
1532 else {
1533 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1534
1535 slice_get_byte_buffers(
1536 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1537
1538 do_mul_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1539 }
1540 }
1541
1542 /*********************** Blend Mode ***************************************/
1543 typedef void (*IMB_blend_func_byte)(unsigned char *dst,
1544 const unsigned char *src1,
1545 const unsigned char *src2);
1546 typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
1547
apply_blend_function_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out,IMB_blend_func_byte blend_function)1548 BLI_INLINE void apply_blend_function_byte(float facf0,
1549 float facf1,
1550 int x,
1551 int y,
1552 unsigned char *rect1,
1553 unsigned char *rect2,
1554 unsigned char *out,
1555 IMB_blend_func_byte blend_function)
1556 {
1557 int xo;
1558 unsigned char *rt1, *rt2, *rt;
1559 unsigned int achannel;
1560 xo = x;
1561 rt1 = rect1;
1562 rt2 = rect2;
1563 rt = out;
1564 while (y--) {
1565 for (x = xo; x > 0; x--) {
1566 achannel = rt1[3];
1567 rt1[3] = (unsigned int)achannel * facf0;
1568 blend_function(rt, rt1, rt2);
1569 rt1[3] = achannel;
1570 rt[3] = rt1[3];
1571 rt1 += 4;
1572 rt2 += 4;
1573 rt += 4;
1574 }
1575 if (y == 0) {
1576 break;
1577 }
1578 y--;
1579 for (x = xo; x > 0; x--) {
1580 achannel = rt1[3];
1581 rt1[3] = (unsigned int)achannel * facf1;
1582 blend_function(rt, rt1, rt2);
1583 rt1[3] = achannel;
1584 rt[3] = rt1[3];
1585 rt1 += 4;
1586 rt2 += 4;
1587 rt += 4;
1588 }
1589 }
1590 }
1591
apply_blend_function_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out,IMB_blend_func_float blend_function)1592 BLI_INLINE void apply_blend_function_float(float facf0,
1593 float facf1,
1594 int x,
1595 int y,
1596 float *rect1,
1597 float *rect2,
1598 float *out,
1599 IMB_blend_func_float blend_function)
1600 {
1601 int xo;
1602 float *rt1, *rt2, *rt;
1603 float achannel;
1604 xo = x;
1605 rt1 = rect1;
1606 rt2 = rect2;
1607 rt = out;
1608 while (y--) {
1609 for (x = xo; x > 0; x--) {
1610 achannel = rt1[3];
1611 rt1[3] = achannel * facf0;
1612 blend_function(rt, rt1, rt2);
1613 rt1[3] = achannel;
1614 rt[3] = rt1[3];
1615 rt1 += 4;
1616 rt2 += 4;
1617 rt += 4;
1618 }
1619 if (y == 0) {
1620 break;
1621 }
1622 y--;
1623 for (x = xo; x > 0; x--) {
1624 achannel = rt1[3];
1625 rt1[3] = achannel * facf1;
1626 blend_function(rt, rt1, rt2);
1627 rt1[3] = achannel;
1628 rt[3] = rt1[3];
1629 rt1 += 4;
1630 rt2 += 4;
1631 rt += 4;
1632 }
1633 }
1634 }
1635
do_blend_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,int btype,float * out)1636 static void do_blend_effect_float(
1637 float facf0, float facf1, int x, int y, float *rect1, float *rect2, int btype, float *out)
1638 {
1639 switch (btype) {
1640 case SEQ_TYPE_ADD:
1641 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_float);
1642 break;
1643 case SEQ_TYPE_SUB:
1644 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_float);
1645 break;
1646 case SEQ_TYPE_MUL:
1647 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_float);
1648 break;
1649 case SEQ_TYPE_DARKEN:
1650 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_float);
1651 break;
1652 case SEQ_TYPE_COLOR_BURN:
1653 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_float);
1654 break;
1655 case SEQ_TYPE_LINEAR_BURN:
1656 apply_blend_function_float(
1657 facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_float);
1658 break;
1659 case SEQ_TYPE_SCREEN:
1660 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_float);
1661 break;
1662 case SEQ_TYPE_LIGHTEN:
1663 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_float);
1664 break;
1665 case SEQ_TYPE_DODGE:
1666 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_float);
1667 break;
1668 case SEQ_TYPE_OVERLAY:
1669 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_float);
1670 break;
1671 case SEQ_TYPE_SOFT_LIGHT:
1672 apply_blend_function_float(
1673 facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_float);
1674 break;
1675 case SEQ_TYPE_HARD_LIGHT:
1676 apply_blend_function_float(
1677 facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_float);
1678 break;
1679 case SEQ_TYPE_PIN_LIGHT:
1680 apply_blend_function_float(
1681 facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_float);
1682 break;
1683 case SEQ_TYPE_LIN_LIGHT:
1684 apply_blend_function_float(
1685 facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_float);
1686 break;
1687 case SEQ_TYPE_VIVID_LIGHT:
1688 apply_blend_function_float(
1689 facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_float);
1690 break;
1691 case SEQ_TYPE_BLEND_COLOR:
1692 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_float);
1693 break;
1694 case SEQ_TYPE_HUE:
1695 apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_float);
1696 break;
1697 case SEQ_TYPE_SATURATION:
1698 apply_blend_function_float(
1699 facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_float);
1700 break;
1701 case SEQ_TYPE_VALUE:
1702 apply_blend_function_float(
1703 facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_float);
1704 break;
1705 case SEQ_TYPE_DIFFERENCE:
1706 apply_blend_function_float(
1707 facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_float);
1708 break;
1709 case SEQ_TYPE_EXCLUSION:
1710 apply_blend_function_float(
1711 facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_float);
1712 break;
1713 default:
1714 break;
1715 }
1716 }
1717
do_blend_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,int btype,unsigned char * out)1718 static void do_blend_effect_byte(float facf0,
1719 float facf1,
1720 int x,
1721 int y,
1722 unsigned char *rect1,
1723 unsigned char *rect2,
1724 int btype,
1725 unsigned char *out)
1726 {
1727 switch (btype) {
1728 case SEQ_TYPE_ADD:
1729 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_byte);
1730 break;
1731 case SEQ_TYPE_SUB:
1732 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_byte);
1733 break;
1734 case SEQ_TYPE_MUL:
1735 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_byte);
1736 break;
1737 case SEQ_TYPE_DARKEN:
1738 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_byte);
1739 break;
1740 case SEQ_TYPE_COLOR_BURN:
1741 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_byte);
1742 break;
1743 case SEQ_TYPE_LINEAR_BURN:
1744 apply_blend_function_byte(
1745 facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_byte);
1746 break;
1747 case SEQ_TYPE_SCREEN:
1748 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_byte);
1749 break;
1750 case SEQ_TYPE_LIGHTEN:
1751 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_byte);
1752 break;
1753 case SEQ_TYPE_DODGE:
1754 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_byte);
1755 break;
1756 case SEQ_TYPE_OVERLAY:
1757 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_byte);
1758 break;
1759 case SEQ_TYPE_SOFT_LIGHT:
1760 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_byte);
1761 break;
1762 case SEQ_TYPE_HARD_LIGHT:
1763 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_byte);
1764 break;
1765 case SEQ_TYPE_PIN_LIGHT:
1766 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_byte);
1767 break;
1768 case SEQ_TYPE_LIN_LIGHT:
1769 apply_blend_function_byte(
1770 facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_byte);
1771 break;
1772 case SEQ_TYPE_VIVID_LIGHT:
1773 apply_blend_function_byte(
1774 facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_byte);
1775 break;
1776 case SEQ_TYPE_BLEND_COLOR:
1777 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_byte);
1778 break;
1779 case SEQ_TYPE_HUE:
1780 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_byte);
1781 break;
1782 case SEQ_TYPE_SATURATION:
1783 apply_blend_function_byte(
1784 facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_byte);
1785 break;
1786 case SEQ_TYPE_VALUE:
1787 apply_blend_function_byte(
1788 facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_byte);
1789 break;
1790 case SEQ_TYPE_DIFFERENCE:
1791 apply_blend_function_byte(
1792 facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_byte);
1793 break;
1794 case SEQ_TYPE_EXCLUSION:
1795 apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_byte);
1796 break;
1797 default:
1798 break;
1799 }
1800 }
1801
do_blend_mode_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1802 static void do_blend_mode_effect(const SeqRenderData *context,
1803 Sequence *seq,
1804 float UNUSED(cfra),
1805 float facf0,
1806 float facf1,
1807 ImBuf *ibuf1,
1808 ImBuf *ibuf2,
1809 ImBuf *UNUSED(ibuf3),
1810 int start_line,
1811 int total_lines,
1812 ImBuf *out)
1813 {
1814 if (out->rect_float) {
1815 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1816 slice_get_float_buffers(
1817 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1818 do_blend_effect_float(
1819 facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
1820 }
1821 else {
1822 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1823 slice_get_byte_buffers(
1824 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1825 do_blend_effect_byte(
1826 facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
1827 }
1828 }
1829 /*********************** Color Mix Effect *************************/
init_colormix_effect(Sequence * seq)1830 static void init_colormix_effect(Sequence *seq)
1831 {
1832 ColorMixVars *data;
1833
1834 if (seq->effectdata) {
1835 MEM_freeN(seq->effectdata);
1836 }
1837 seq->effectdata = MEM_callocN(sizeof(ColorMixVars), "colormixvars");
1838 data = (ColorMixVars *)seq->effectdata;
1839 data->blend_effect = SEQ_TYPE_OVERLAY;
1840 data->factor = 1.0f;
1841 }
1842
do_colormix_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1843 static void do_colormix_effect(const SeqRenderData *context,
1844 Sequence *seq,
1845 float UNUSED(cfra),
1846 float UNUSED(facf0),
1847 float UNUSED(facf1),
1848 ImBuf *ibuf1,
1849 ImBuf *ibuf2,
1850 ImBuf *UNUSED(ibuf3),
1851 int start_line,
1852 int total_lines,
1853 ImBuf *out)
1854 {
1855 float facf;
1856
1857 ColorMixVars *data = seq->effectdata;
1858 facf = data->factor;
1859
1860 if (out->rect_float) {
1861 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1862 slice_get_float_buffers(
1863 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1864 do_blend_effect_float(
1865 facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
1866 }
1867 else {
1868 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1869 slice_get_byte_buffers(
1870 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1871 do_blend_effect_byte(
1872 facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
1873 }
1874 }
1875
1876 /*********************** Wipe *************************/
1877
1878 typedef struct WipeZone {
1879 float angle;
1880 int flip;
1881 int xo, yo;
1882 int width;
1883 float pythangle;
1884 } WipeZone;
1885
precalc_wipe_zone(WipeZone * wipezone,WipeVars * wipe,int xo,int yo)1886 static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
1887 {
1888 wipezone->flip = (wipe->angle < 0.0f);
1889 wipezone->angle = tanf(fabsf(wipe->angle));
1890 wipezone->xo = xo;
1891 wipezone->yo = yo;
1892 wipezone->width = (int)(wipe->edgeWidth * ((xo + yo) / 2.0f));
1893 wipezone->pythangle = 1.0f / sqrtf(wipezone->angle * wipezone->angle + 1.0f);
1894 }
1895
1896 /* This function calculates the blur band for the wipe effects */
in_band(float width,float dist,int side,int dir)1897 static float in_band(float width, float dist, int side, int dir)
1898 {
1899 float alpha;
1900
1901 if (width == 0) {
1902 return (float)side;
1903 }
1904
1905 if (width < dist) {
1906 return (float)side;
1907 }
1908
1909 if (side == 1) {
1910 alpha = (dist + 0.5f * width) / (width);
1911 }
1912 else {
1913 alpha = (0.5f * width - dist) / (width);
1914 }
1915
1916 if (dir == 0) {
1917 alpha = 1 - alpha;
1918 }
1919
1920 return alpha;
1921 }
1922
check_zone(WipeZone * wipezone,int x,int y,Sequence * seq,float facf0)1923 static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float facf0)
1924 {
1925 float posx, posy, hyp, hyp2, angle, hwidth, b1, b2, b3, pointdist;
1926 /* some future stuff */
1927 /* float hyp3, hyp4, b4, b5 */
1928 float temp1, temp2, temp3, temp4; /* some placeholder variables */
1929 int xo = wipezone->xo;
1930 int yo = wipezone->yo;
1931 float halfx = xo * 0.5f;
1932 float halfy = yo * 0.5f;
1933 float widthf, output = 0;
1934 WipeVars *wipe = (WipeVars *)seq->effectdata;
1935 int width;
1936
1937 if (wipezone->flip) {
1938 x = xo - x;
1939 }
1940 angle = wipezone->angle;
1941
1942 if (wipe->forward) {
1943 posx = facf0 * xo;
1944 posy = facf0 * yo;
1945 }
1946 else {
1947 posx = xo - facf0 * xo;
1948 posy = yo - facf0 * yo;
1949 }
1950
1951 switch (wipe->wipetype) {
1952 case DO_SINGLE_WIPE:
1953 width = min_ii(wipezone->width, facf0 * yo);
1954 width = min_ii(width, yo - facf0 * yo);
1955
1956 if (angle == 0.0f) {
1957 b1 = posy;
1958 b2 = y;
1959 hyp = fabsf(y - posy);
1960 }
1961 else {
1962 b1 = posy - (-angle) * posx;
1963 b2 = y - (-angle) * x;
1964 hyp = fabsf(angle * x + y + (-posy - angle * posx)) * wipezone->pythangle;
1965 }
1966
1967 if (angle < 0) {
1968 temp1 = b1;
1969 b1 = b2;
1970 b2 = temp1;
1971 }
1972
1973 if (wipe->forward) {
1974 if (b1 < b2) {
1975 output = in_band(width, hyp, 1, 1);
1976 }
1977 else {
1978 output = in_band(width, hyp, 0, 1);
1979 }
1980 }
1981 else {
1982 if (b1 < b2) {
1983 output = in_band(width, hyp, 0, 1);
1984 }
1985 else {
1986 output = in_band(width, hyp, 1, 1);
1987 }
1988 }
1989 break;
1990
1991 case DO_DOUBLE_WIPE:
1992 if (!wipe->forward) {
1993 facf0 = 1.0f - facf0; /* Go the other direction */
1994 }
1995
1996 width = wipezone->width; /* calculate the blur width */
1997 hwidth = width * 0.5f;
1998 if (angle == 0) {
1999 b1 = posy * 0.5f;
2000 b3 = yo - posy * 0.5f;
2001 b2 = y;
2002
2003 hyp = fabsf(y - posy * 0.5f);
2004 hyp2 = fabsf(y - (yo - posy * 0.5f));
2005 }
2006 else {
2007 b1 = posy * 0.5f - (-angle) * posx * 0.5f;
2008 b3 = (yo - posy * 0.5f) - (-angle) * (xo - posx * 0.5f);
2009 b2 = y - (-angle) * x;
2010
2011 hyp = fabsf(angle * x + y + (-posy * 0.5f - angle * posx * 0.5f)) * wipezone->pythangle;
2012 hyp2 = fabsf(angle * x + y + (-(yo - posy * 0.5f) - angle * (xo - posx * 0.5f))) *
2013 wipezone->pythangle;
2014 }
2015
2016 hwidth = min_ff(hwidth, fabsf(b3 - b1) / 2.0f);
2017
2018 if (b2 < b1 && b2 < b3) {
2019 output = in_band(hwidth, hyp, 0, 1);
2020 }
2021 else if (b2 > b1 && b2 > b3) {
2022 output = in_band(hwidth, hyp2, 0, 1);
2023 }
2024 else {
2025 if (hyp < hwidth && hyp2 > hwidth) {
2026 output = in_band(hwidth, hyp, 1, 1);
2027 }
2028 else if (hyp > hwidth && hyp2 < hwidth) {
2029 output = in_band(hwidth, hyp2, 1, 1);
2030 }
2031 else {
2032 output = in_band(hwidth, hyp2, 1, 1) * in_band(hwidth, hyp, 1, 1);
2033 }
2034 }
2035 if (!wipe->forward) {
2036 output = 1 - output;
2037 }
2038 break;
2039 case DO_CLOCK_WIPE:
2040 /*
2041 * temp1: angle of effect center in rads
2042 * temp2: angle of line through (halfx, halfy) and (x, y) in rads
2043 * temp3: angle of low side of blur
2044 * temp4: angle of high side of blur
2045 */
2046 output = 1.0f - facf0;
2047 widthf = wipe->edgeWidth * 2.0f * (float)M_PI;
2048 temp1 = 2.0f * (float)M_PI * facf0;
2049
2050 if (wipe->forward) {
2051 temp1 = 2.0f * (float)M_PI - temp1;
2052 }
2053
2054 x = x - halfx;
2055 y = y - halfy;
2056
2057 temp2 = asin(abs(y) / hypot(x, y));
2058 if (x <= 0 && y >= 0) {
2059 temp2 = (float)M_PI - temp2;
2060 }
2061 else if (x <= 0 && y <= 0) {
2062 temp2 += (float)M_PI;
2063 }
2064 else if (x >= 0 && y <= 0) {
2065 temp2 = 2.0f * (float)M_PI - temp2;
2066 }
2067
2068 if (wipe->forward) {
2069 temp3 = temp1 - (widthf * 0.5f) * facf0;
2070 temp4 = temp1 + (widthf * 0.5f) * (1 - facf0);
2071 }
2072 else {
2073 temp3 = temp1 - (widthf * 0.5f) * (1 - facf0);
2074 temp4 = temp1 + (widthf * 0.5f) * facf0;
2075 }
2076 if (temp3 < 0) {
2077 temp3 = 0;
2078 }
2079 if (temp4 > 2.0f * (float)M_PI) {
2080 temp4 = 2.0f * (float)M_PI;
2081 }
2082
2083 if (temp2 < temp3) {
2084 output = 0;
2085 }
2086 else if (temp2 > temp4) {
2087 output = 1;
2088 }
2089 else {
2090 output = (temp2 - temp3) / (temp4 - temp3);
2091 }
2092 if (x == 0 && y == 0) {
2093 output = 1;
2094 }
2095 if (output != output) {
2096 output = 1;
2097 }
2098 if (wipe->forward) {
2099 output = 1 - output;
2100 }
2101 break;
2102 case DO_IRIS_WIPE:
2103 if (xo > yo) {
2104 yo = xo;
2105 }
2106 else {
2107 xo = yo;
2108 }
2109
2110 if (!wipe->forward) {
2111 facf0 = 1 - facf0;
2112 }
2113
2114 width = wipezone->width;
2115 hwidth = width * 0.5f;
2116
2117 temp1 = (halfx - (halfx)*facf0);
2118 pointdist = hypotf(temp1, temp1);
2119
2120 temp2 = hypotf(halfx - x, halfy - y);
2121 if (temp2 > pointdist) {
2122 output = in_band(hwidth, fabsf(temp2 - pointdist), 0, 1);
2123 }
2124 else {
2125 output = in_band(hwidth, fabsf(temp2 - pointdist), 1, 1);
2126 }
2127
2128 if (!wipe->forward) {
2129 output = 1 - output;
2130 }
2131
2132 break;
2133 }
2134 if (output < 0) {
2135 output = 0;
2136 }
2137 else if (output > 1) {
2138 output = 1;
2139 }
2140 return output;
2141 }
2142
init_wipe_effect(Sequence * seq)2143 static void init_wipe_effect(Sequence *seq)
2144 {
2145 if (seq->effectdata) {
2146 MEM_freeN(seq->effectdata);
2147 }
2148
2149 seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
2150 }
2151
num_inputs_wipe(void)2152 static int num_inputs_wipe(void)
2153 {
2154 return 2;
2155 }
2156
free_wipe_effect(Sequence * seq,const bool UNUSED (do_id_user))2157 static void free_wipe_effect(Sequence *seq, const bool UNUSED(do_id_user))
2158 {
2159 if (seq->effectdata) {
2160 MEM_freeN(seq->effectdata);
2161 }
2162
2163 seq->effectdata = NULL;
2164 }
2165
copy_wipe_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))2166 static void copy_wipe_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
2167 {
2168 dst->effectdata = MEM_dupallocN(src->effectdata);
2169 }
2170
do_wipe_effect_byte(Sequence * seq,float facf0,float UNUSED (facf1),int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)2171 static void do_wipe_effect_byte(Sequence *seq,
2172 float facf0,
2173 float UNUSED(facf1),
2174 int x,
2175 int y,
2176 unsigned char *rect1,
2177 unsigned char *rect2,
2178 unsigned char *out)
2179 {
2180 WipeZone wipezone;
2181 WipeVars *wipe = (WipeVars *)seq->effectdata;
2182 int xo, yo;
2183 unsigned char *cp1, *cp2, *rt;
2184
2185 precalc_wipe_zone(&wipezone, wipe, x, y);
2186
2187 cp1 = rect1;
2188 cp2 = rect2;
2189 rt = out;
2190
2191 xo = x;
2192 yo = y;
2193 for (y = 0; y < yo; y++) {
2194 for (x = 0; x < xo; x++) {
2195 float check = check_zone(&wipezone, x, y, seq, facf0);
2196 if (check) {
2197 if (cp1) {
2198 float rt1[4], rt2[4], tempc[4];
2199
2200 straight_uchar_to_premul_float(rt1, cp1);
2201 straight_uchar_to_premul_float(rt2, cp2);
2202
2203 tempc[0] = rt1[0] * check + rt2[0] * (1 - check);
2204 tempc[1] = rt1[1] * check + rt2[1] * (1 - check);
2205 tempc[2] = rt1[2] * check + rt2[2] * (1 - check);
2206 tempc[3] = rt1[3] * check + rt2[3] * (1 - check);
2207
2208 premul_float_to_straight_uchar(rt, tempc);
2209 }
2210 else {
2211 rt[0] = 0;
2212 rt[1] = 0;
2213 rt[2] = 0;
2214 rt[3] = 255;
2215 }
2216 }
2217 else {
2218 if (cp2) {
2219 rt[0] = cp2[0];
2220 rt[1] = cp2[1];
2221 rt[2] = cp2[2];
2222 rt[3] = cp2[3];
2223 }
2224 else {
2225 rt[0] = 0;
2226 rt[1] = 0;
2227 rt[2] = 0;
2228 rt[3] = 255;
2229 }
2230 }
2231
2232 rt += 4;
2233 if (cp1 != NULL) {
2234 cp1 += 4;
2235 }
2236 if (cp2 != NULL) {
2237 cp2 += 4;
2238 }
2239 }
2240 }
2241 }
2242
do_wipe_effect_float(Sequence * seq,float facf0,float UNUSED (facf1),int x,int y,float * rect1,float * rect2,float * out)2243 static void do_wipe_effect_float(Sequence *seq,
2244 float facf0,
2245 float UNUSED(facf1),
2246 int x,
2247 int y,
2248 float *rect1,
2249 float *rect2,
2250 float *out)
2251 {
2252 WipeZone wipezone;
2253 WipeVars *wipe = (WipeVars *)seq->effectdata;
2254 int xo, yo;
2255 float *rt1, *rt2, *rt;
2256
2257 precalc_wipe_zone(&wipezone, wipe, x, y);
2258
2259 rt1 = rect1;
2260 rt2 = rect2;
2261 rt = out;
2262
2263 xo = x;
2264 yo = y;
2265 for (y = 0; y < yo; y++) {
2266 for (x = 0; x < xo; x++) {
2267 float check = check_zone(&wipezone, x, y, seq, facf0);
2268 if (check) {
2269 if (rt1) {
2270 rt[0] = rt1[0] * check + rt2[0] * (1 - check);
2271 rt[1] = rt1[1] * check + rt2[1] * (1 - check);
2272 rt[2] = rt1[2] * check + rt2[2] * (1 - check);
2273 rt[3] = rt1[3] * check + rt2[3] * (1 - check);
2274 }
2275 else {
2276 rt[0] = 0;
2277 rt[1] = 0;
2278 rt[2] = 0;
2279 rt[3] = 1.0;
2280 }
2281 }
2282 else {
2283 if (rt2) {
2284 rt[0] = rt2[0];
2285 rt[1] = rt2[1];
2286 rt[2] = rt2[2];
2287 rt[3] = rt2[3];
2288 }
2289 else {
2290 rt[0] = 0;
2291 rt[1] = 0;
2292 rt[2] = 0;
2293 rt[3] = 1.0;
2294 }
2295 }
2296
2297 rt += 4;
2298 if (rt1 != NULL) {
2299 rt1 += 4;
2300 }
2301 if (rt2 != NULL) {
2302 rt2 += 4;
2303 }
2304 }
2305 }
2306 }
2307
do_wipe_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)2308 static ImBuf *do_wipe_effect(const SeqRenderData *context,
2309 Sequence *seq,
2310 float UNUSED(cfra),
2311 float facf0,
2312 float facf1,
2313 ImBuf *ibuf1,
2314 ImBuf *ibuf2,
2315 ImBuf *ibuf3)
2316 {
2317 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2318
2319 if (out->rect_float) {
2320 do_wipe_effect_float(seq,
2321 facf0,
2322 facf1,
2323 context->rectx,
2324 context->recty,
2325 ibuf1->rect_float,
2326 ibuf2->rect_float,
2327 out->rect_float);
2328 }
2329 else {
2330 do_wipe_effect_byte(seq,
2331 facf0,
2332 facf1,
2333 context->rectx,
2334 context->recty,
2335 (unsigned char *)ibuf1->rect,
2336 (unsigned char *)ibuf2->rect,
2337 (unsigned char *)out->rect);
2338 }
2339
2340 return out;
2341 }
2342
2343 /*********************** Transform *************************/
2344
init_transform_effect(Sequence * seq)2345 static void init_transform_effect(Sequence *seq)
2346 {
2347 TransformVars *transform;
2348
2349 if (seq->effectdata) {
2350 MEM_freeN(seq->effectdata);
2351 }
2352
2353 seq->effectdata = MEM_callocN(sizeof(TransformVars), "transformvars");
2354
2355 transform = (TransformVars *)seq->effectdata;
2356
2357 transform->ScalexIni = 1.0f;
2358 transform->ScaleyIni = 1.0f;
2359
2360 transform->xIni = 0.0f;
2361 transform->yIni = 0.0f;
2362
2363 transform->rotIni = 0.0f;
2364
2365 transform->interpolation = 1;
2366 transform->percent = 1;
2367 transform->uniform_scale = 0;
2368 }
2369
num_inputs_transform(void)2370 static int num_inputs_transform(void)
2371 {
2372 return 1;
2373 }
2374
free_transform_effect(Sequence * seq,const bool UNUSED (do_id_user))2375 static void free_transform_effect(Sequence *seq, const bool UNUSED(do_id_user))
2376 {
2377 if (seq->effectdata) {
2378 MEM_freeN(seq->effectdata);
2379 }
2380 seq->effectdata = NULL;
2381 }
2382
copy_transform_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))2383 static void copy_transform_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
2384 {
2385 dst->effectdata = MEM_dupallocN(src->effectdata);
2386 }
2387
transform_image(int x,int y,int start_line,int total_lines,ImBuf * ibuf1,ImBuf * out,float scale_x,float scale_y,float translate_x,float translate_y,float rotate,int interpolation)2388 static void transform_image(int x,
2389 int y,
2390 int start_line,
2391 int total_lines,
2392 ImBuf *ibuf1,
2393 ImBuf *out,
2394 float scale_x,
2395 float scale_y,
2396 float translate_x,
2397 float translate_y,
2398 float rotate,
2399 int interpolation)
2400 {
2401 /* Rotate */
2402 float s = sinf(rotate);
2403 float c = cosf(rotate);
2404
2405 for (int yi = start_line; yi < start_line + total_lines; yi++) {
2406 for (int xi = 0; xi < x; xi++) {
2407 /* translate point */
2408 float xt = xi - translate_x;
2409 float yt = yi - translate_y;
2410
2411 /* rotate point with center ref */
2412 float xr = c * xt + s * yt;
2413 float yr = -s * xt + c * yt;
2414
2415 /* scale point with center ref */
2416 xt = xr / scale_x;
2417 yt = yr / scale_y;
2418
2419 /* undo reference center point */
2420 xt += (x / 2.0f);
2421 yt += (y / 2.0f);
2422
2423 /* interpolate */
2424 switch (interpolation) {
2425 case 0:
2426 nearest_interpolation(ibuf1, out, xt, yt, xi, yi);
2427 break;
2428 case 1:
2429 bilinear_interpolation(ibuf1, out, xt, yt, xi, yi);
2430 break;
2431 case 2:
2432 bicubic_interpolation(ibuf1, out, xt, yt, xi, yi);
2433 break;
2434 }
2435 }
2436 }
2437 }
2438
do_transform_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)2439 static void do_transform_effect(const SeqRenderData *context,
2440 Sequence *seq,
2441 float UNUSED(cfra),
2442 float UNUSED(facf0),
2443 float UNUSED(facf1),
2444 ImBuf *ibuf1,
2445 ImBuf *UNUSED(ibuf2),
2446 ImBuf *UNUSED(ibuf3),
2447 int start_line,
2448 int total_lines,
2449 ImBuf *out)
2450 {
2451 Scene *scene = context->scene;
2452 TransformVars *transform = (TransformVars *)seq->effectdata;
2453 float scale_x, scale_y, translate_x, translate_y, rotate_radians;
2454
2455 /* Scale */
2456 if (transform->uniform_scale) {
2457 scale_x = scale_y = transform->ScalexIni;
2458 }
2459 else {
2460 scale_x = transform->ScalexIni;
2461 scale_y = transform->ScaleyIni;
2462 }
2463
2464 int x = context->rectx;
2465 int y = context->recty;
2466
2467 /* Translate */
2468 if (!transform->percent) {
2469 float rd_s = (scene->r.size / 100.0f);
2470
2471 translate_x = transform->xIni * rd_s + (x / 2.0f);
2472 translate_y = transform->yIni * rd_s + (y / 2.0f);
2473 }
2474 else {
2475 translate_x = x * (transform->xIni / 100.0f) + (x / 2.0f);
2476 translate_y = y * (transform->yIni / 100.0f) + (y / 2.0f);
2477 }
2478
2479 /* Rotate */
2480 rotate_radians = DEG2RADF(transform->rotIni);
2481
2482 transform_image(x,
2483 y,
2484 start_line,
2485 total_lines,
2486 ibuf1,
2487 out,
2488 scale_x,
2489 scale_y,
2490 translate_x,
2491 translate_y,
2492 rotate_radians,
2493 transform->interpolation);
2494 }
2495
2496 /*********************** Glow *************************/
2497
RVBlurBitmap2_float(float * map,int width,int height,float blur,int quality)2498 static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality)
2499 {
2500 /* Much better than the previous blur!
2501 * We do the blurring in two passes which is a whole lot faster.
2502 * I changed the math around to implement an actual Gaussian distribution.
2503 *
2504 * Watch out though, it tends to misbehave with large blur values on
2505 * a small bitmap. Avoid avoid! */
2506
2507 float *temp = NULL, *swap;
2508 float *filter = NULL;
2509 int x, y, i, fx, fy;
2510 int index, ix, halfWidth;
2511 float fval, k, curColor[4], curColor2[4], weight = 0;
2512
2513 /* If we're not really blurring, bail out */
2514 if (blur <= 0) {
2515 return;
2516 }
2517
2518 /* Allocate memory for the tempmap and the blur filter matrix */
2519 temp = MEM_mallocN(sizeof(float[4]) * width * height, "blurbitmaptemp");
2520 if (!temp) {
2521 return;
2522 }
2523
2524 /* Allocate memory for the filter elements */
2525 halfWidth = ((quality + 1) * blur);
2526 filter = (float *)MEM_mallocN(sizeof(float) * halfWidth * 2, "blurbitmapfilter");
2527 if (!filter) {
2528 MEM_freeN(temp);
2529 return;
2530 }
2531
2532 /* Apparently we're calculating a bell curve based on the standard deviation (or radius)
2533 * This code is based on an example posted to comp.graphics.algorithms by
2534 * Blancmange <bmange@airdmhor.gen.nz>
2535 */
2536
2537 k = -1.0f / (2.0f * (float)M_PI * blur * blur);
2538
2539 for (ix = 0; ix < halfWidth; ix++) {
2540 weight = (float)exp(k * (ix * ix));
2541 filter[halfWidth - ix] = weight;
2542 filter[halfWidth + ix] = weight;
2543 }
2544 filter[0] = weight;
2545
2546 /* Normalize the array */
2547 fval = 0;
2548 for (ix = 0; ix < halfWidth * 2; ix++) {
2549 fval += filter[ix];
2550 }
2551
2552 for (ix = 0; ix < halfWidth * 2; ix++) {
2553 filter[ix] /= fval;
2554 }
2555
2556 /* Blur the rows */
2557 for (y = 0; y < height; y++) {
2558 /* Do the left & right strips */
2559 for (x = 0; x < halfWidth; x++) {
2560 fx = 0;
2561 zero_v4(curColor);
2562 zero_v4(curColor2);
2563
2564 for (i = x - halfWidth; i < x + halfWidth; i++) {
2565 if ((i >= 0) && (i < width)) {
2566 index = (i + y * width) * 4;
2567 madd_v4_v4fl(curColor, map + index, filter[fx]);
2568
2569 index = (width - 1 - i + y * width) * 4;
2570 madd_v4_v4fl(curColor2, map + index, filter[fx]);
2571 }
2572 fx++;
2573 }
2574 index = (x + y * width) * 4;
2575 copy_v4_v4(temp + index, curColor);
2576
2577 index = (width - 1 - x + y * width) * 4;
2578 copy_v4_v4(temp + index, curColor2);
2579 }
2580
2581 /* Do the main body */
2582 for (x = halfWidth; x < width - halfWidth; x++) {
2583 fx = 0;
2584 zero_v4(curColor);
2585 for (i = x - halfWidth; i < x + halfWidth; i++) {
2586 index = (i + y * width) * 4;
2587 madd_v4_v4fl(curColor, map + index, filter[fx]);
2588 fx++;
2589 }
2590 index = (x + y * width) * 4;
2591 copy_v4_v4(temp + index, curColor);
2592 }
2593 }
2594
2595 /* Swap buffers */
2596 swap = temp;
2597 temp = map;
2598 map = swap;
2599
2600 /* Blur the columns */
2601 for (x = 0; x < width; x++) {
2602 /* Do the top & bottom strips */
2603 for (y = 0; y < halfWidth; y++) {
2604 fy = 0;
2605 zero_v4(curColor);
2606 zero_v4(curColor2);
2607 for (i = y - halfWidth; i < y + halfWidth; i++) {
2608 if ((i >= 0) && (i < height)) {
2609 /* Bottom */
2610 index = (x + i * width) * 4;
2611 madd_v4_v4fl(curColor, map + index, filter[fy]);
2612
2613 /* Top */
2614 index = (x + (height - 1 - i) * width) * 4;
2615 madd_v4_v4fl(curColor2, map + index, filter[fy]);
2616 }
2617 fy++;
2618 }
2619 index = (x + y * width) * 4;
2620 copy_v4_v4(temp + index, curColor);
2621
2622 index = (x + (height - 1 - y) * width) * 4;
2623 copy_v4_v4(temp + index, curColor2);
2624 }
2625
2626 /* Do the main body */
2627 for (y = halfWidth; y < height - halfWidth; y++) {
2628 fy = 0;
2629 zero_v4(curColor);
2630 for (i = y - halfWidth; i < y + halfWidth; i++) {
2631 index = (x + i * width) * 4;
2632 madd_v4_v4fl(curColor, map + index, filter[fy]);
2633 fy++;
2634 }
2635 index = (x + y * width) * 4;
2636 copy_v4_v4(temp + index, curColor);
2637 }
2638 }
2639
2640 /* Swap buffers */
2641 swap = temp;
2642 temp = map; /* map = swap; */ /* UNUSED */
2643
2644 /* Tidy up */
2645 MEM_freeN(filter);
2646 MEM_freeN(temp);
2647 }
2648
RVAddBitmaps_float(float * a,float * b,float * c,int width,int height)2649 static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int height)
2650 {
2651 int x, y, index;
2652
2653 for (y = 0; y < height; y++) {
2654 for (x = 0; x < width; x++) {
2655 index = (x + y * width) * 4;
2656 c[index + GlowR] = min_ff(1.0f, a[index + GlowR] + b[index + GlowR]);
2657 c[index + GlowG] = min_ff(1.0f, a[index + GlowG] + b[index + GlowG]);
2658 c[index + GlowB] = min_ff(1.0f, a[index + GlowB] + b[index + GlowB]);
2659 c[index + GlowA] = min_ff(1.0f, a[index + GlowA] + b[index + GlowA]);
2660 }
2661 }
2662 }
2663
RVIsolateHighlights_float(const float * in,float * out,int width,int height,float threshold,float boost,float clamp)2664 static void RVIsolateHighlights_float(
2665 const float *in, float *out, int width, int height, float threshold, float boost, float clamp)
2666 {
2667 int x, y, index;
2668 float intensity;
2669
2670 for (y = 0; y < height; y++) {
2671 for (x = 0; x < width; x++) {
2672 index = (x + y * width) * 4;
2673
2674 /* Isolate the intensity */
2675 intensity = (in[index + GlowR] + in[index + GlowG] + in[index + GlowB] - threshold);
2676 if (intensity > 0) {
2677 out[index + GlowR] = min_ff(clamp, (in[index + GlowR] * boost * intensity));
2678 out[index + GlowG] = min_ff(clamp, (in[index + GlowG] * boost * intensity));
2679 out[index + GlowB] = min_ff(clamp, (in[index + GlowB] * boost * intensity));
2680 out[index + GlowA] = min_ff(clamp, (in[index + GlowA] * boost * intensity));
2681 }
2682 else {
2683 out[index + GlowR] = 0;
2684 out[index + GlowG] = 0;
2685 out[index + GlowB] = 0;
2686 out[index + GlowA] = 0;
2687 }
2688 }
2689 }
2690 }
2691
init_glow_effect(Sequence * seq)2692 static void init_glow_effect(Sequence *seq)
2693 {
2694 GlowVars *glow;
2695
2696 if (seq->effectdata) {
2697 MEM_freeN(seq->effectdata);
2698 }
2699
2700 seq->effectdata = MEM_callocN(sizeof(GlowVars), "glowvars");
2701
2702 glow = (GlowVars *)seq->effectdata;
2703 glow->fMini = 0.25;
2704 glow->fClamp = 1.0;
2705 glow->fBoost = 0.5;
2706 glow->dDist = 3.0;
2707 glow->dQuality = 3;
2708 glow->bNoComp = 0;
2709 }
2710
num_inputs_glow(void)2711 static int num_inputs_glow(void)
2712 {
2713 return 1;
2714 }
2715
free_glow_effect(Sequence * seq,const bool UNUSED (do_id_user))2716 static void free_glow_effect(Sequence *seq, const bool UNUSED(do_id_user))
2717 {
2718 if (seq->effectdata) {
2719 MEM_freeN(seq->effectdata);
2720 }
2721
2722 seq->effectdata = NULL;
2723 }
2724
copy_glow_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))2725 static void copy_glow_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
2726 {
2727 dst->effectdata = MEM_dupallocN(src->effectdata);
2728 }
2729
do_glow_effect_byte(Sequence * seq,int render_size,float facf0,float UNUSED (facf1),int x,int y,unsigned char * rect1,unsigned char * UNUSED (rect2),unsigned char * out)2730 static void do_glow_effect_byte(Sequence *seq,
2731 int render_size,
2732 float facf0,
2733 float UNUSED(facf1),
2734 int x,
2735 int y,
2736 unsigned char *rect1,
2737 unsigned char *UNUSED(rect2),
2738 unsigned char *out)
2739 {
2740 float *outbuf, *inbuf;
2741 GlowVars *glow = (GlowVars *)seq->effectdata;
2742
2743 inbuf = MEM_mallocN(sizeof(float[4]) * x * y, "glow effect input");
2744 outbuf = MEM_mallocN(sizeof(float[4]) * x * y, "glow effect output");
2745
2746 IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, x, y, x, x);
2747 IMB_buffer_float_premultiply(inbuf, x, y);
2748
2749 RVIsolateHighlights_float(
2750 inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
2751 RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
2752 if (!glow->bNoComp) {
2753 RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
2754 }
2755
2756 IMB_buffer_float_unpremultiply(outbuf, x, y);
2757 IMB_buffer_byte_from_float(
2758 out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, x, y, x, x);
2759
2760 MEM_freeN(inbuf);
2761 MEM_freeN(outbuf);
2762 }
2763
do_glow_effect_float(Sequence * seq,int render_size,float facf0,float UNUSED (facf1),int x,int y,float * rect1,float * UNUSED (rect2),float * out)2764 static void do_glow_effect_float(Sequence *seq,
2765 int render_size,
2766 float facf0,
2767 float UNUSED(facf1),
2768 int x,
2769 int y,
2770 float *rect1,
2771 float *UNUSED(rect2),
2772 float *out)
2773 {
2774 float *outbuf = out;
2775 float *inbuf = rect1;
2776 GlowVars *glow = (GlowVars *)seq->effectdata;
2777
2778 RVIsolateHighlights_float(
2779 inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
2780 RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
2781 if (!glow->bNoComp) {
2782 RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
2783 }
2784 }
2785
do_glow_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)2786 static ImBuf *do_glow_effect(const SeqRenderData *context,
2787 Sequence *seq,
2788 float UNUSED(cfra),
2789 float facf0,
2790 float facf1,
2791 ImBuf *ibuf1,
2792 ImBuf *ibuf2,
2793 ImBuf *ibuf3)
2794 {
2795 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2796
2797 int render_size = 100 * context->rectx / context->scene->r.xsch;
2798
2799 if (out->rect_float) {
2800 do_glow_effect_float(seq,
2801 render_size,
2802 facf0,
2803 facf1,
2804 context->rectx,
2805 context->recty,
2806 ibuf1->rect_float,
2807 NULL,
2808 out->rect_float);
2809 }
2810 else {
2811 do_glow_effect_byte(seq,
2812 render_size,
2813 facf0,
2814 facf1,
2815 context->rectx,
2816 context->recty,
2817 (unsigned char *)ibuf1->rect,
2818 NULL,
2819 (unsigned char *)out->rect);
2820 }
2821
2822 return out;
2823 }
2824
2825 /*********************** Solid color *************************/
2826
init_solid_color(Sequence * seq)2827 static void init_solid_color(Sequence *seq)
2828 {
2829 SolidColorVars *cv;
2830
2831 if (seq->effectdata) {
2832 MEM_freeN(seq->effectdata);
2833 }
2834
2835 seq->effectdata = MEM_callocN(sizeof(SolidColorVars), "solidcolor");
2836
2837 cv = (SolidColorVars *)seq->effectdata;
2838 cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
2839 }
2840
num_inputs_color(void)2841 static int num_inputs_color(void)
2842 {
2843 return 0;
2844 }
2845
free_solid_color(Sequence * seq,const bool UNUSED (do_id_user))2846 static void free_solid_color(Sequence *seq, const bool UNUSED(do_id_user))
2847 {
2848 if (seq->effectdata) {
2849 MEM_freeN(seq->effectdata);
2850 }
2851
2852 seq->effectdata = NULL;
2853 }
2854
copy_solid_color(Sequence * dst,Sequence * src,const int UNUSED (flag))2855 static void copy_solid_color(Sequence *dst, Sequence *src, const int UNUSED(flag))
2856 {
2857 dst->effectdata = MEM_dupallocN(src->effectdata);
2858 }
2859
early_out_color(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))2860 static int early_out_color(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2861 {
2862 return EARLY_NO_INPUT;
2863 }
2864
do_solid_color(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)2865 static ImBuf *do_solid_color(const SeqRenderData *context,
2866 Sequence *seq,
2867 float UNUSED(cfra),
2868 float facf0,
2869 float facf1,
2870 ImBuf *ibuf1,
2871 ImBuf *ibuf2,
2872 ImBuf *ibuf3)
2873 {
2874 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2875
2876 SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
2877
2878 unsigned char *rect;
2879 float *rect_float;
2880 int x; /*= context->rectx;*/ /*UNUSED*/
2881 int y; /*= context->recty;*/ /*UNUSED*/
2882
2883 if (out->rect) {
2884 unsigned char col0[3];
2885 unsigned char col1[3];
2886
2887 col0[0] = facf0 * cv->col[0] * 255;
2888 col0[1] = facf0 * cv->col[1] * 255;
2889 col0[2] = facf0 * cv->col[2] * 255;
2890
2891 col1[0] = facf1 * cv->col[0] * 255;
2892 col1[1] = facf1 * cv->col[1] * 255;
2893 col1[2] = facf1 * cv->col[2] * 255;
2894
2895 rect = (unsigned char *)out->rect;
2896
2897 for (y = 0; y < out->y; y++) {
2898 for (x = 0; x < out->x; x++, rect += 4) {
2899 rect[0] = col0[0];
2900 rect[1] = col0[1];
2901 rect[2] = col0[2];
2902 rect[3] = 255;
2903 }
2904 y++;
2905 if (y < out->y) {
2906 for (x = 0; x < out->x; x++, rect += 4) {
2907 rect[0] = col1[0];
2908 rect[1] = col1[1];
2909 rect[2] = col1[2];
2910 rect[3] = 255;
2911 }
2912 }
2913 }
2914 }
2915 else if (out->rect_float) {
2916 float col0[3];
2917 float col1[3];
2918
2919 col0[0] = facf0 * cv->col[0];
2920 col0[1] = facf0 * cv->col[1];
2921 col0[2] = facf0 * cv->col[2];
2922
2923 col1[0] = facf1 * cv->col[0];
2924 col1[1] = facf1 * cv->col[1];
2925 col1[2] = facf1 * cv->col[2];
2926
2927 rect_float = out->rect_float;
2928
2929 for (y = 0; y < out->y; y++) {
2930 for (x = 0; x < out->x; x++, rect_float += 4) {
2931 rect_float[0] = col0[0];
2932 rect_float[1] = col0[1];
2933 rect_float[2] = col0[2];
2934 rect_float[3] = 1.0;
2935 }
2936 y++;
2937 if (y < out->y) {
2938 for (x = 0; x < out->x; x++, rect_float += 4) {
2939 rect_float[0] = col1[0];
2940 rect_float[1] = col1[1];
2941 rect_float[2] = col1[2];
2942 rect_float[3] = 1.0;
2943 }
2944 }
2945 }
2946 }
2947 return out;
2948 }
2949
2950 /*********************** Mulitcam *************************/
2951
2952 /* no effect inputs for multicam, we use give_ibuf_seq */
num_inputs_multicam(void)2953 static int num_inputs_multicam(void)
2954 {
2955 return 0;
2956 }
2957
early_out_multicam(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))2958 static int early_out_multicam(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2959 {
2960 return EARLY_NO_INPUT;
2961 }
2962
do_multicam(const SeqRenderData * context,Sequence * seq,float cfra,float UNUSED (facf0),float UNUSED (facf1),ImBuf * UNUSED (ibuf1),ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3))2963 static ImBuf *do_multicam(const SeqRenderData *context,
2964 Sequence *seq,
2965 float cfra,
2966 float UNUSED(facf0),
2967 float UNUSED(facf1),
2968 ImBuf *UNUSED(ibuf1),
2969 ImBuf *UNUSED(ibuf2),
2970 ImBuf *UNUSED(ibuf3))
2971 {
2972 ImBuf *out;
2973 Editing *ed;
2974 ListBase *seqbasep;
2975
2976 if (seq->multicam_source == 0 || seq->multicam_source >= seq->machine) {
2977 return NULL;
2978 }
2979
2980 ed = context->scene->ed;
2981 if (!ed) {
2982 return NULL;
2983 }
2984 seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq);
2985 if (!seqbasep) {
2986 return NULL;
2987 }
2988
2989 out = BKE_sequencer_give_ibuf_seqbase(context, cfra, seq->multicam_source, seqbasep);
2990
2991 return out;
2992 }
2993
2994 /*********************** Adjustment *************************/
2995
2996 /* no effect inputs for adjustment, we use give_ibuf_seq */
num_inputs_adjustment(void)2997 static int num_inputs_adjustment(void)
2998 {
2999 return 0;
3000 }
3001
early_out_adjustment(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))3002 static int early_out_adjustment(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
3003 {
3004 return EARLY_NO_INPUT;
3005 }
3006
do_adjustment_impl(const SeqRenderData * context,Sequence * seq,float cfra)3007 static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, float cfra)
3008 {
3009 Editing *ed;
3010 ListBase *seqbasep;
3011 ImBuf *i = NULL;
3012
3013 ed = context->scene->ed;
3014
3015 seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq);
3016
3017 if (seq->machine > 1) {
3018 i = BKE_sequencer_give_ibuf_seqbase(context, cfra, seq->machine - 1, seqbasep);
3019 }
3020
3021 /* found nothing? so let's work the way up the metastrip stack, so
3022 * that it is possible to group a bunch of adjustment strips into
3023 * a metastrip and have that work on everything below the metastrip
3024 */
3025
3026 if (!i) {
3027 Sequence *meta;
3028
3029 meta = BKE_sequence_metastrip(&ed->seqbase, NULL, seq);
3030
3031 if (meta) {
3032 i = do_adjustment_impl(context, meta, cfra);
3033 }
3034 }
3035
3036 return i;
3037 }
3038
do_adjustment(const SeqRenderData * context,Sequence * seq,float cfra,float UNUSED (facf0),float UNUSED (facf1),ImBuf * UNUSED (ibuf1),ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3))3039 static ImBuf *do_adjustment(const SeqRenderData *context,
3040 Sequence *seq,
3041 float cfra,
3042 float UNUSED(facf0),
3043 float UNUSED(facf1),
3044 ImBuf *UNUSED(ibuf1),
3045 ImBuf *UNUSED(ibuf2),
3046 ImBuf *UNUSED(ibuf3))
3047 {
3048 ImBuf *out;
3049 Editing *ed;
3050
3051 ed = context->scene->ed;
3052
3053 if (!ed) {
3054 return NULL;
3055 }
3056
3057 out = do_adjustment_impl(context, seq, cfra);
3058
3059 return out;
3060 }
3061
3062 /*********************** Speed *************************/
3063
init_speed_effect(Sequence * seq)3064 static void init_speed_effect(Sequence *seq)
3065 {
3066 SpeedControlVars *v;
3067
3068 if (seq->effectdata) {
3069 MEM_freeN(seq->effectdata);
3070 }
3071
3072 seq->effectdata = MEM_callocN(sizeof(SpeedControlVars), "speedcontrolvars");
3073
3074 v = (SpeedControlVars *)seq->effectdata;
3075 v->globalSpeed = 1.0;
3076 v->frameMap = NULL;
3077 v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */
3078 v->length = 0;
3079 }
3080
load_speed_effect(Sequence * seq)3081 static void load_speed_effect(Sequence *seq)
3082 {
3083 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3084
3085 v->frameMap = NULL;
3086 v->length = 0;
3087 }
3088
num_inputs_speed(void)3089 static int num_inputs_speed(void)
3090 {
3091 return 1;
3092 }
3093
free_speed_effect(Sequence * seq,const bool UNUSED (do_id_user))3094 static void free_speed_effect(Sequence *seq, const bool UNUSED(do_id_user))
3095 {
3096 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3097 if (v->frameMap) {
3098 MEM_freeN(v->frameMap);
3099 }
3100 if (seq->effectdata) {
3101 MEM_freeN(seq->effectdata);
3102 }
3103 seq->effectdata = NULL;
3104 }
3105
copy_speed_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))3106 static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
3107 {
3108 SpeedControlVars *v;
3109 dst->effectdata = MEM_dupallocN(src->effectdata);
3110 v = (SpeedControlVars *)dst->effectdata;
3111 v->frameMap = NULL;
3112 v->length = 0;
3113 }
3114
early_out_speed(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))3115 static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
3116 {
3117 return EARLY_DO_EFFECT;
3118 }
3119
store_icu_yrange_speed(Sequence * seq,short UNUSED (adrcode),float * ymin,float * ymax)3120 static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float *ymin, float *ymax)
3121 {
3122 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3123
3124 /* if not already done, load / initialize data */
3125 BKE_sequence_get_effect(seq);
3126
3127 if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
3128 *ymin = -100.0;
3129 *ymax = 100.0;
3130 }
3131 else {
3132 if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
3133 *ymin = 0.0;
3134 *ymax = 1.0;
3135 }
3136 else {
3137 *ymin = 0.0;
3138 *ymax = seq->len;
3139 }
3140 }
3141 }
3142
BKE_sequence_effect_speed_rebuild_map(Scene * scene,Sequence * seq,bool force)3143 void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force)
3144 {
3145 int cfra;
3146 float fallback_fac = 1.0f;
3147 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3148 FCurve *fcu = NULL;
3149 int flags = v->flags;
3150
3151 /* if not already done, load / initialize data */
3152 BKE_sequence_get_effect(seq);
3153
3154 if ((force == false) && (seq->len == v->length) && (v->frameMap != NULL)) {
3155 return;
3156 }
3157 if ((seq->seq1 == NULL) || (seq->len < 1)) {
3158 /* make coverity happy and check for (CID 598) input strip ... */
3159 return;
3160 }
3161
3162 /* XXX - new in 2.5x. should we use the animation system this way?
3163 * The fcurve is needed because many frames need evaluating at once - campbell */
3164 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
3165 if (!v->frameMap || v->length != seq->len) {
3166 if (v->frameMap) {
3167 MEM_freeN(v->frameMap);
3168 }
3169
3170 v->length = seq->len;
3171
3172 v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap");
3173 }
3174
3175 fallback_fac = 1.0;
3176
3177 if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
3178 if ((seq->seq1->enddisp != seq->seq1->start) && (seq->seq1->len != 0)) {
3179 fallback_fac = (float)seq->seq1->len / (float)(seq->seq1->enddisp - seq->seq1->start);
3180 flags = SEQ_SPEED_INTEGRATE;
3181 fcu = NULL;
3182 }
3183 }
3184 else {
3185 /* if there is no fcurve, use value as simple multiplier */
3186 if (!fcu) {
3187 fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/
3188 }
3189 }
3190
3191 if (flags & SEQ_SPEED_INTEGRATE) {
3192 float cursor = 0;
3193 float facf;
3194
3195 v->frameMap[0] = 0;
3196 v->lastValidFrame = 0;
3197
3198 for (cfra = 1; cfra < v->length; cfra++) {
3199 if (fcu) {
3200 facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
3201 }
3202 else {
3203 facf = fallback_fac;
3204 }
3205 facf *= v->globalSpeed;
3206
3207 cursor += facf;
3208
3209 if (cursor >= seq->seq1->len) {
3210 v->frameMap[cfra] = seq->seq1->len - 1;
3211 }
3212 else {
3213 v->frameMap[cfra] = cursor;
3214 v->lastValidFrame = cfra;
3215 }
3216 }
3217 }
3218 else {
3219 float facf;
3220
3221 v->lastValidFrame = 0;
3222 for (cfra = 0; cfra < v->length; cfra++) {
3223
3224 if (fcu) {
3225 facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
3226 }
3227 else {
3228 facf = fallback_fac;
3229 }
3230
3231 if (flags & SEQ_SPEED_COMPRESS_IPO_Y) {
3232 facf *= seq->seq1->len;
3233 }
3234 facf *= v->globalSpeed;
3235
3236 if (facf >= seq->seq1->len) {
3237 facf = seq->seq1->len - 1;
3238 }
3239 else {
3240 v->lastValidFrame = cfra;
3241 }
3242 v->frameMap[cfra] = facf;
3243 }
3244 }
3245 }
3246
3247 /* Override cfra when rendering speed effect input. */
BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData * context,Sequence * seq,float cfra,int input)3248 float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context,
3249 Sequence *seq,
3250 float cfra,
3251 int input)
3252 {
3253 int nr = BKE_sequencer_give_stripelem_index(seq, cfra);
3254 SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
3255 BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false);
3256
3257 /* No interpolation. */
3258 if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) {
3259 return seq->start + s->frameMap[nr];
3260 }
3261
3262 /* We need to provide current and next image for interpolation. */
3263 if (input == 0) { /* Current frame. */
3264 return floor(seq->start + s->frameMap[nr]);
3265 }
3266 /* Next frame. */
3267 return ceil(seq->start + s->frameMap[nr]);
3268 }
3269
speed_effect_interpolation_ratio_get(SpeedControlVars * s,Sequence * seq,float cfra)3270 static float speed_effect_interpolation_ratio_get(SpeedControlVars *s, Sequence *seq, float cfra)
3271 {
3272 int nr = BKE_sequencer_give_stripelem_index(seq, cfra);
3273 return s->frameMap[nr] - floor(s->frameMap[nr]);
3274 }
3275
do_speed_effect(const SeqRenderData * context,Sequence * seq,float cfra,float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)3276 static ImBuf *do_speed_effect(const SeqRenderData *context,
3277 Sequence *seq,
3278 float cfra,
3279 float facf0,
3280 float facf1,
3281 ImBuf *ibuf1,
3282 ImBuf *ibuf2,
3283 ImBuf *ibuf3)
3284 {
3285 SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
3286 struct SeqEffectHandle cross_effect = get_sequence_effect_impl(SEQ_TYPE_CROSS);
3287 ImBuf *out;
3288
3289 if (s->flags & SEQ_SPEED_USE_INTERPOLATION) {
3290 out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
3291 facf0 = facf1 = speed_effect_interpolation_ratio_get(s, seq, cfra);
3292 /* Current frame is ibuf1, next frame is ibuf2. */
3293 out = BKE_sequencer_effect_execute_threaded(
3294 &cross_effect, context, NULL, cfra, facf0, facf1, ibuf1, ibuf2, ibuf3);
3295 return out;
3296 }
3297
3298 /* No interpolation. */
3299 return IMB_dupImBuf(ibuf1);
3300 }
3301
3302 /*********************** overdrop *************************/
3303
do_overdrop_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)3304 static void do_overdrop_effect(const SeqRenderData *context,
3305 Sequence *UNUSED(seq),
3306 float UNUSED(cfra),
3307 float facf0,
3308 float facf1,
3309 ImBuf *ibuf1,
3310 ImBuf *ibuf2,
3311 ImBuf *UNUSED(ibuf3),
3312 int start_line,
3313 int total_lines,
3314 ImBuf *out)
3315 {
3316 int x = context->rectx;
3317 int y = total_lines;
3318
3319 if (out->rect_float) {
3320 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3321
3322 slice_get_float_buffers(
3323 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3324
3325 do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
3326 do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
3327 }
3328 else {
3329 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3330
3331 slice_get_byte_buffers(
3332 context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3333
3334 do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
3335 do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
3336 }
3337 }
3338
3339 /*********************** Gaussian Blur *************************/
3340
3341 /* NOTE: This gaussian blur implementation accumulates values in the square
3342 * kernel rather that doing X direction and then Y direction because of the
3343 * lack of using multiple-staged filters.
3344 *
3345 * Once we can we'll implement a way to apply filter as multiple stages we
3346 * can optimize hell of a lot in here.
3347 */
3348
init_gaussian_blur_effect(Sequence * seq)3349 static void init_gaussian_blur_effect(Sequence *seq)
3350 {
3351 if (seq->effectdata) {
3352 MEM_freeN(seq->effectdata);
3353 }
3354
3355 seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
3356 }
3357
num_inputs_gaussian_blur(void)3358 static int num_inputs_gaussian_blur(void)
3359 {
3360 return 1;
3361 }
3362
free_gaussian_blur_effect(Sequence * seq,const bool UNUSED (do_id_user))3363 static void free_gaussian_blur_effect(Sequence *seq, const bool UNUSED(do_id_user))
3364 {
3365 if (seq->effectdata) {
3366 MEM_freeN(seq->effectdata);
3367 }
3368
3369 seq->effectdata = NULL;
3370 }
3371
copy_gaussian_blur_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))3372 static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
3373 {
3374 dst->effectdata = MEM_dupallocN(src->effectdata);
3375 }
3376
early_out_gaussian_blur(Sequence * seq,float UNUSED (facf0),float UNUSED (facf1))3377 static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
3378 {
3379 GaussianBlurVars *data = seq->effectdata;
3380 if (data->size_x == 0.0f && data->size_y == 0) {
3381 return EARLY_USE_INPUT_1;
3382 }
3383 return EARLY_DO_EFFECT;
3384 }
3385
3386 /* TODO(sergey): De-duplicate with compositor. */
make_gaussian_blur_kernel(float rad,int size)3387 static float *make_gaussian_blur_kernel(float rad, int size)
3388 {
3389 float *gausstab, sum, val;
3390 float fac;
3391 int i, n;
3392
3393 n = 2 * size + 1;
3394
3395 gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
3396
3397 sum = 0.0f;
3398 fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
3399 for (i = -size; i <= size; i++) {
3400 val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
3401 sum += val;
3402 gausstab[i + size] = val;
3403 }
3404
3405 sum = 1.0f / sum;
3406 for (i = 0; i < n; i++) {
3407 gausstab[i] *= sum;
3408 }
3409
3410 return gausstab;
3411 }
3412
do_gaussian_blur_effect_byte_x(Sequence * seq,int start_line,int x,int y,int frame_width,int UNUSED (frame_height),const unsigned char * rect,unsigned char * out)3413 static void do_gaussian_blur_effect_byte_x(Sequence *seq,
3414 int start_line,
3415 int x,
3416 int y,
3417 int frame_width,
3418 int UNUSED(frame_height),
3419 const unsigned char *rect,
3420 unsigned char *out)
3421 {
3422 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3423 GaussianBlurVars *data = seq->effectdata;
3424 const int size_x = (int)(data->size_x + 0.5f);
3425 int i, j;
3426
3427 /* Make gaussian weight table. */
3428 float *gausstab_x;
3429 gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
3430
3431 for (i = 0; i < y; i++) {
3432 for (j = 0; j < x; j++) {
3433 int out_index = INDEX(j, i);
3434 float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3435 float accum_weight = 0.0f;
3436
3437 for (int current_x = j - size_x; current_x <= j + size_x; current_x++) {
3438 if (current_x < 0 || current_x >= frame_width) {
3439 /* Out of bounds. */
3440 continue;
3441 }
3442 int index = INDEX(current_x, i + start_line);
3443 float weight = gausstab_x[current_x - j + size_x];
3444 accum[0] += rect[index] * weight;
3445 accum[1] += rect[index + 1] * weight;
3446 accum[2] += rect[index + 2] * weight;
3447 accum[3] += rect[index + 3] * weight;
3448 accum_weight += weight;
3449 }
3450
3451 float inv_accum_weight = 1.0f / accum_weight;
3452 out[out_index + 0] = accum[0] * inv_accum_weight;
3453 out[out_index + 1] = accum[1] * inv_accum_weight;
3454 out[out_index + 2] = accum[2] * inv_accum_weight;
3455 out[out_index + 3] = accum[3] * inv_accum_weight;
3456 }
3457 }
3458
3459 MEM_freeN(gausstab_x);
3460 #undef INDEX
3461 }
3462
do_gaussian_blur_effect_byte_y(Sequence * seq,int start_line,int x,int y,int UNUSED (frame_width),int frame_height,const unsigned char * rect,unsigned char * out)3463 static void do_gaussian_blur_effect_byte_y(Sequence *seq,
3464 int start_line,
3465 int x,
3466 int y,
3467 int UNUSED(frame_width),
3468 int frame_height,
3469 const unsigned char *rect,
3470 unsigned char *out)
3471 {
3472 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3473 GaussianBlurVars *data = seq->effectdata;
3474 const int size_y = (int)(data->size_y + 0.5f);
3475 int i, j;
3476
3477 /* Make gaussian weight table. */
3478 float *gausstab_y;
3479 gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
3480
3481 for (i = 0; i < y; i++) {
3482 for (j = 0; j < x; j++) {
3483 int out_index = INDEX(j, i);
3484 float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3485 float accum_weight = 0.0f;
3486 for (int current_y = i - size_y; current_y <= i + size_y; current_y++) {
3487 if (current_y < -start_line || current_y + start_line >= frame_height) {
3488 /* Out of bounds. */
3489 continue;
3490 }
3491 int index = INDEX(j, current_y + start_line);
3492 float weight = gausstab_y[current_y - i + size_y];
3493 accum[0] += rect[index] * weight;
3494 accum[1] += rect[index + 1] * weight;
3495 accum[2] += rect[index + 2] * weight;
3496 accum[3] += rect[index + 3] * weight;
3497 accum_weight += weight;
3498 }
3499 float inv_accum_weight = 1.0f / accum_weight;
3500 out[out_index + 0] = accum[0] * inv_accum_weight;
3501 out[out_index + 1] = accum[1] * inv_accum_weight;
3502 out[out_index + 2] = accum[2] * inv_accum_weight;
3503 out[out_index + 3] = accum[3] * inv_accum_weight;
3504 }
3505 }
3506
3507 MEM_freeN(gausstab_y);
3508 #undef INDEX
3509 }
3510
do_gaussian_blur_effect_float_x(Sequence * seq,int start_line,int x,int y,int frame_width,int UNUSED (frame_height),float * rect,float * out)3511 static void do_gaussian_blur_effect_float_x(Sequence *seq,
3512 int start_line,
3513 int x,
3514 int y,
3515 int frame_width,
3516 int UNUSED(frame_height),
3517 float *rect,
3518 float *out)
3519 {
3520 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3521 GaussianBlurVars *data = seq->effectdata;
3522 const int size_x = (int)(data->size_x + 0.5f);
3523 int i, j;
3524
3525 /* Make gaussian weight table. */
3526 float *gausstab_x;
3527 gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
3528
3529 for (i = 0; i < y; i++) {
3530 for (j = 0; j < x; j++) {
3531 int out_index = INDEX(j, i);
3532 float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3533 float accum_weight = 0.0f;
3534 for (int current_x = j - size_x; current_x <= j + size_x; current_x++) {
3535 if (current_x < 0 || current_x >= frame_width) {
3536 /* Out of bounds. */
3537 continue;
3538 }
3539 int index = INDEX(current_x, i + start_line);
3540 float weight = gausstab_x[current_x - j + size_x];
3541 madd_v4_v4fl(accum, &rect[index], weight);
3542 accum_weight += weight;
3543 }
3544 mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
3545 }
3546 }
3547
3548 MEM_freeN(gausstab_x);
3549 #undef INDEX
3550 }
3551
do_gaussian_blur_effect_float_y(Sequence * seq,int start_line,int x,int y,int UNUSED (frame_width),int frame_height,float * rect,float * out)3552 static void do_gaussian_blur_effect_float_y(Sequence *seq,
3553 int start_line,
3554 int x,
3555 int y,
3556 int UNUSED(frame_width),
3557 int frame_height,
3558 float *rect,
3559 float *out)
3560 {
3561 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3562 GaussianBlurVars *data = seq->effectdata;
3563 const int size_y = (int)(data->size_y + 0.5f);
3564 int i, j;
3565
3566 /* Make gaussian weight table. */
3567 float *gausstab_y;
3568 gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
3569
3570 for (i = 0; i < y; i++) {
3571 for (j = 0; j < x; j++) {
3572 int out_index = INDEX(j, i);
3573 float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3574 float accum_weight = 0.0f;
3575 for (int current_y = i - size_y; current_y <= i + size_y; current_y++) {
3576 if (current_y < -start_line || current_y + start_line >= frame_height) {
3577 /* Out of bounds. */
3578 continue;
3579 }
3580 int index = INDEX(j, current_y + start_line);
3581 float weight = gausstab_y[current_y - i + size_y];
3582 madd_v4_v4fl(accum, &rect[index], weight);
3583 accum_weight += weight;
3584 }
3585 mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
3586 }
3587 }
3588
3589 MEM_freeN(gausstab_y);
3590 #undef INDEX
3591 }
3592
do_gaussian_blur_effect_x_cb(const SeqRenderData * context,Sequence * seq,ImBuf * ibuf,int start_line,int total_lines,ImBuf * out)3593 static void do_gaussian_blur_effect_x_cb(const SeqRenderData *context,
3594 Sequence *seq,
3595 ImBuf *ibuf,
3596 int start_line,
3597 int total_lines,
3598 ImBuf *out)
3599 {
3600 if (out->rect_float) {
3601 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3602
3603 slice_get_float_buffers(
3604 context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3605
3606 do_gaussian_blur_effect_float_x(seq,
3607 start_line,
3608 context->rectx,
3609 total_lines,
3610 context->rectx,
3611 context->recty,
3612 ibuf->rect_float,
3613 rect_out);
3614 }
3615 else {
3616 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3617
3618 slice_get_byte_buffers(
3619 context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3620
3621 do_gaussian_blur_effect_byte_x(seq,
3622 start_line,
3623 context->rectx,
3624 total_lines,
3625 context->rectx,
3626 context->recty,
3627 (unsigned char *)ibuf->rect,
3628 rect_out);
3629 }
3630 }
3631
do_gaussian_blur_effect_y_cb(const SeqRenderData * context,Sequence * seq,ImBuf * ibuf,int start_line,int total_lines,ImBuf * out)3632 static void do_gaussian_blur_effect_y_cb(const SeqRenderData *context,
3633 Sequence *seq,
3634 ImBuf *ibuf,
3635 int start_line,
3636 int total_lines,
3637 ImBuf *out)
3638 {
3639 if (out->rect_float) {
3640 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3641
3642 slice_get_float_buffers(
3643 context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3644
3645 do_gaussian_blur_effect_float_y(seq,
3646 start_line,
3647 context->rectx,
3648 total_lines,
3649 context->rectx,
3650 context->recty,
3651 ibuf->rect_float,
3652 rect_out);
3653 }
3654 else {
3655 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3656
3657 slice_get_byte_buffers(
3658 context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3659
3660 do_gaussian_blur_effect_byte_y(seq,
3661 start_line,
3662 context->rectx,
3663 total_lines,
3664 context->rectx,
3665 context->recty,
3666 (unsigned char *)ibuf->rect,
3667 rect_out);
3668 }
3669 }
3670
3671 typedef struct RenderGaussianBlurEffectInitData {
3672 const SeqRenderData *context;
3673 Sequence *seq;
3674 ImBuf *ibuf;
3675 ImBuf *out;
3676 } RenderGaussianBlurEffectInitData;
3677
3678 typedef struct RenderGaussianBlurEffectThread {
3679 const SeqRenderData *context;
3680 Sequence *seq;
3681 ImBuf *ibuf;
3682 ImBuf *out;
3683 int start_line, tot_line;
3684 } RenderGaussianBlurEffectThread;
3685
render_effect_execute_init_handle(void * handle_v,int start_line,int tot_line,void * init_data_v)3686 static void render_effect_execute_init_handle(void *handle_v,
3687 int start_line,
3688 int tot_line,
3689 void *init_data_v)
3690 {
3691 RenderGaussianBlurEffectThread *handle = (RenderGaussianBlurEffectThread *)handle_v;
3692 RenderGaussianBlurEffectInitData *init_data = (RenderGaussianBlurEffectInitData *)init_data_v;
3693
3694 handle->context = init_data->context;
3695 handle->seq = init_data->seq;
3696 handle->ibuf = init_data->ibuf;
3697 handle->out = init_data->out;
3698
3699 handle->start_line = start_line;
3700 handle->tot_line = tot_line;
3701 }
3702
render_effect_execute_do_x_thread(void * thread_data_v)3703 static void *render_effect_execute_do_x_thread(void *thread_data_v)
3704 {
3705 RenderGaussianBlurEffectThread *thread_data = (RenderGaussianBlurEffectThread *)thread_data_v;
3706 do_gaussian_blur_effect_x_cb(thread_data->context,
3707 thread_data->seq,
3708 thread_data->ibuf,
3709 thread_data->start_line,
3710 thread_data->tot_line,
3711 thread_data->out);
3712 return NULL;
3713 }
3714
render_effect_execute_do_y_thread(void * thread_data_v)3715 static void *render_effect_execute_do_y_thread(void *thread_data_v)
3716 {
3717 RenderGaussianBlurEffectThread *thread_data = (RenderGaussianBlurEffectThread *)thread_data_v;
3718 do_gaussian_blur_effect_y_cb(thread_data->context,
3719 thread_data->seq,
3720 thread_data->ibuf,
3721 thread_data->start_line,
3722 thread_data->tot_line,
3723 thread_data->out);
3724
3725 return NULL;
3726 }
3727
do_gaussian_blur_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3))3728 static ImBuf *do_gaussian_blur_effect(const SeqRenderData *context,
3729 Sequence *seq,
3730 float UNUSED(cfra),
3731 float UNUSED(facf0),
3732 float UNUSED(facf1),
3733 ImBuf *ibuf1,
3734 ImBuf *UNUSED(ibuf2),
3735 ImBuf *UNUSED(ibuf3))
3736 {
3737 ImBuf *out = prepare_effect_imbufs(context, ibuf1, NULL, NULL);
3738
3739 RenderGaussianBlurEffectInitData init_data;
3740
3741 init_data.context = context;
3742 init_data.seq = seq;
3743 init_data.ibuf = ibuf1;
3744 init_data.out = out;
3745
3746 IMB_processor_apply_threaded(out->y,
3747 sizeof(RenderGaussianBlurEffectThread),
3748 &init_data,
3749 render_effect_execute_init_handle,
3750 render_effect_execute_do_x_thread);
3751
3752 ibuf1 = out;
3753 init_data.ibuf = ibuf1;
3754 out = prepare_effect_imbufs(context, ibuf1, NULL, NULL);
3755 init_data.out = out;
3756
3757 IMB_processor_apply_threaded(out->y,
3758 sizeof(RenderGaussianBlurEffectThread),
3759 &init_data,
3760 render_effect_execute_init_handle,
3761 render_effect_execute_do_y_thread);
3762
3763 IMB_freeImBuf(ibuf1);
3764
3765 return out;
3766 }
3767
3768 /*********************** text *************************/
3769
init_text_effect(Sequence * seq)3770 static void init_text_effect(Sequence *seq)
3771 {
3772 TextVars *data;
3773
3774 if (seq->effectdata) {
3775 MEM_freeN(seq->effectdata);
3776 }
3777
3778 data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
3779 data->text_font = NULL;
3780 data->text_blf_id = -1;
3781 data->text_size = 30;
3782
3783 copy_v4_fl(data->color, 1.0f);
3784 data->shadow_color[3] = 1.0f;
3785
3786 BLI_strncpy(data->text, "Text", sizeof(data->text));
3787
3788 data->loc[0] = 0.5f;
3789 data->align = SEQ_TEXT_ALIGN_X_CENTER;
3790 data->align_y = SEQ_TEXT_ALIGN_Y_BOTTOM;
3791 }
3792
BKE_sequencer_text_font_unload(TextVars * data,const bool do_id_user)3793 void BKE_sequencer_text_font_unload(TextVars *data, const bool do_id_user)
3794 {
3795 if (data) {
3796 /* Unlink the VFont */
3797 if (do_id_user && data->text_font != NULL) {
3798 id_us_min(&data->text_font->id);
3799 data->text_font = NULL;
3800 }
3801
3802 /* Unload the BLF font. */
3803 if (data->text_blf_id >= 0) {
3804 BLF_unload_id(data->text_blf_id);
3805 }
3806 }
3807 }
3808
BKE_sequencer_text_font_load(TextVars * data,const bool do_id_user)3809 void BKE_sequencer_text_font_load(TextVars *data, const bool do_id_user)
3810 {
3811 if (data->text_font != NULL) {
3812 if (do_id_user) {
3813 id_us_plus(&data->text_font->id);
3814 }
3815
3816 char path[FILE_MAX];
3817 STRNCPY(path, data->text_font->filepath);
3818 BLI_assert(BLI_thread_is_main());
3819 BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&data->text_font->id));
3820
3821 data->text_blf_id = BLF_load(path);
3822 }
3823 }
3824
free_text_effect(Sequence * seq,const bool do_id_user)3825 static void free_text_effect(Sequence *seq, const bool do_id_user)
3826 {
3827 TextVars *data = seq->effectdata;
3828 BKE_sequencer_text_font_unload(data, do_id_user);
3829
3830 if (data) {
3831 MEM_freeN(data);
3832 seq->effectdata = NULL;
3833 }
3834 }
3835
load_text_effect(Sequence * seq)3836 static void load_text_effect(Sequence *seq)
3837 {
3838 TextVars *data = seq->effectdata;
3839 BKE_sequencer_text_font_load(data, false);
3840 }
3841
copy_text_effect(Sequence * dst,Sequence * src,const int flag)3842 static void copy_text_effect(Sequence *dst, Sequence *src, const int flag)
3843 {
3844 dst->effectdata = MEM_dupallocN(src->effectdata);
3845 TextVars *data = dst->effectdata;
3846
3847 data->text_blf_id = -1;
3848 BKE_sequencer_text_font_load(data, (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0);
3849 }
3850
num_inputs_text(void)3851 static int num_inputs_text(void)
3852 {
3853 return 0;
3854 }
3855
early_out_text(Sequence * seq,float UNUSED (facf0),float UNUSED (facf1))3856 static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
3857 {
3858 TextVars *data = seq->effectdata;
3859 if (data->text[0] == 0 || data->text_size < 1 ||
3860 ((data->color[3] == 0.0f) &&
3861 (data->shadow_color[3] == 0.0f || (data->flag & SEQ_TEXT_SHADOW) == 0))) {
3862 return EARLY_USE_INPUT_1;
3863 }
3864 return EARLY_NO_INPUT;
3865 }
3866
do_text_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)3867 static ImBuf *do_text_effect(const SeqRenderData *context,
3868 Sequence *seq,
3869 float UNUSED(cfra),
3870 float UNUSED(facf0),
3871 float UNUSED(facf1),
3872 ImBuf *ibuf1,
3873 ImBuf *ibuf2,
3874 ImBuf *ibuf3)
3875 {
3876 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
3877 TextVars *data = seq->effectdata;
3878 int width = out->x;
3879 int height = out->y;
3880 struct ColorManagedDisplay *display;
3881 const char *display_device;
3882 int font = blf_mono_font_render;
3883 int line_height;
3884 int y_ofs, x, y;
3885 double proxy_size_comp;
3886
3887 if (data->text_blf_id == SEQ_FONT_NOT_LOADED) {
3888 data->text_blf_id = -1;
3889
3890 if (data->text_font) {
3891 data->text_blf_id = BLF_load(data->text_font->filepath);
3892 }
3893 }
3894
3895 if (data->text_blf_id >= 0) {
3896 font = data->text_blf_id;
3897 }
3898
3899 display_device = context->scene->display_settings.display_device;
3900 display = IMB_colormanagement_display_get_named(display_device);
3901
3902 /* Compensate text size for preview render size. */
3903 proxy_size_comp = context->scene->r.size / 100.0;
3904 if (context->preview_render_size != SEQ_RENDER_SIZE_SCENE) {
3905 proxy_size_comp = BKE_sequencer_rendersize_to_scale_factor(context->preview_render_size);
3906 }
3907
3908 /* set before return */
3909 BLF_size(font, proxy_size_comp * data->text_size, 72);
3910
3911 BLF_enable(font, BLF_WORD_WRAP);
3912
3913 /* use max width to enable newlines only */
3914 BLF_wordwrap(font, (data->wrap_width != 0.0f) ? data->wrap_width * width : -1);
3915
3916 BLF_buffer(
3917 font, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display);
3918
3919 line_height = BLF_height_max(font);
3920
3921 y_ofs = -BLF_descender(font);
3922
3923 x = (data->loc[0] * width);
3924 y = (data->loc[1] * height) + y_ofs;
3925
3926 if ((data->align == SEQ_TEXT_ALIGN_X_LEFT) && (data->align_y == SEQ_TEXT_ALIGN_Y_TOP)) {
3927 y -= line_height;
3928 }
3929 else {
3930 /* vars for calculating wordwrap */
3931 struct {
3932 struct ResultBLF info;
3933 rctf rect;
3934 } wrap;
3935
3936 BLF_boundbox_ex(font, data->text, sizeof(data->text), &wrap.rect, &wrap.info);
3937
3938 if (data->align == SEQ_TEXT_ALIGN_X_RIGHT) {
3939 x -= BLI_rctf_size_x(&wrap.rect);
3940 }
3941 else if (data->align == SEQ_TEXT_ALIGN_X_CENTER) {
3942 x -= BLI_rctf_size_x(&wrap.rect) / 2;
3943 }
3944
3945 if (data->align_y == SEQ_TEXT_ALIGN_Y_TOP) {
3946 y -= line_height;
3947 }
3948 else if (data->align_y == SEQ_TEXT_ALIGN_Y_BOTTOM) {
3949 y += (wrap.info.lines - 1) * line_height;
3950 }
3951 else if (data->align_y == SEQ_TEXT_ALIGN_Y_CENTER) {
3952 y += (((wrap.info.lines - 1) / 2) * line_height) - (line_height / 2);
3953 }
3954 }
3955
3956 /* BLF_SHADOW won't work with buffers, instead use cheap shadow trick */
3957 if (data->flag & SEQ_TEXT_SHADOW) {
3958 int fontx, fonty;
3959 fontx = BLF_width_max(font);
3960 fonty = line_height;
3961 BLF_position(font, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0f);
3962 BLF_buffer_col(font, data->shadow_color);
3963 BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX);
3964 }
3965
3966 BLF_position(font, x, y, 0.0f);
3967 BLF_buffer_col(font, data->color);
3968 BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX);
3969
3970 BLF_buffer(font, NULL, NULL, 0, 0, 0, NULL);
3971
3972 BLF_disable(font, BLF_WORD_WRAP);
3973
3974 return out;
3975 }
3976
3977 /*********************** sequence effect factory *************************/
3978
init_noop(Sequence * UNUSED (seq))3979 static void init_noop(Sequence *UNUSED(seq))
3980 {
3981 }
3982
load_noop(Sequence * UNUSED (seq))3983 static void load_noop(Sequence *UNUSED(seq))
3984 {
3985 }
3986
free_noop(Sequence * UNUSED (seq),const bool UNUSED (do_id_user))3987 static void free_noop(Sequence *UNUSED(seq), const bool UNUSED(do_id_user))
3988 {
3989 }
3990
num_inputs_default(void)3991 static int num_inputs_default(void)
3992 {
3993 return 2;
3994 }
3995
copy_effect_default(Sequence * dst,Sequence * src,const int UNUSED (flag))3996 static void copy_effect_default(Sequence *dst, Sequence *src, const int UNUSED(flag))
3997 {
3998 dst->effectdata = MEM_dupallocN(src->effectdata);
3999 }
4000
free_effect_default(Sequence * seq,const bool UNUSED (do_id_user))4001 static void free_effect_default(Sequence *seq, const bool UNUSED(do_id_user))
4002 {
4003 if (seq->effectdata) {
4004 MEM_freeN(seq->effectdata);
4005 }
4006
4007 seq->effectdata = NULL;
4008 }
4009
early_out_noop(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))4010 static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
4011 {
4012 return EARLY_DO_EFFECT;
4013 }
4014
early_out_fade(Sequence * UNUSED (seq),float facf0,float facf1)4015 static int early_out_fade(Sequence *UNUSED(seq), float facf0, float facf1)
4016 {
4017 if (facf0 == 0.0f && facf1 == 0.0f) {
4018 return EARLY_USE_INPUT_1;
4019 }
4020 if (facf0 == 1.0f && facf1 == 1.0f) {
4021 return EARLY_USE_INPUT_2;
4022 }
4023 return EARLY_DO_EFFECT;
4024 }
4025
early_out_mul_input2(Sequence * UNUSED (seq),float facf0,float facf1)4026 static int early_out_mul_input2(Sequence *UNUSED(seq), float facf0, float facf1)
4027 {
4028 if (facf0 == 0.0f && facf1 == 0.0f) {
4029 return EARLY_USE_INPUT_1;
4030 }
4031 return EARLY_DO_EFFECT;
4032 }
4033
store_icu_yrange_noop(Sequence * UNUSED (seq),short UNUSED (adrcode),float * UNUSED (ymin),float * UNUSED (ymax))4034 static void store_icu_yrange_noop(Sequence *UNUSED(seq),
4035 short UNUSED(adrcode),
4036 float *UNUSED(ymin),
4037 float *UNUSED(ymax))
4038 {
4039 /* defaults are fine */
4040 }
4041
get_default_fac_noop(Sequence * UNUSED (seq),float UNUSED (cfra),float * facf0,float * facf1)4042 static void get_default_fac_noop(Sequence *UNUSED(seq),
4043 float UNUSED(cfra),
4044 float *facf0,
4045 float *facf1)
4046 {
4047 *facf0 = *facf1 = 1.0;
4048 }
4049
get_default_fac_fade(Sequence * seq,float cfra,float * facf0,float * facf1)4050 static void get_default_fac_fade(Sequence *seq, float cfra, float *facf0, float *facf1)
4051 {
4052 *facf0 = (float)(cfra - seq->startdisp);
4053 *facf1 = (float)(*facf0 + 0.5f);
4054 *facf0 /= seq->len;
4055 *facf1 /= seq->len;
4056 }
4057
init_execution(const SeqRenderData * context,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)4058 static struct ImBuf *init_execution(const SeqRenderData *context,
4059 ImBuf *ibuf1,
4060 ImBuf *ibuf2,
4061 ImBuf *ibuf3)
4062 {
4063 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
4064
4065 return out;
4066 }
4067
get_sequence_effect_impl(int seq_type)4068 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
4069 {
4070 struct SeqEffectHandle rval;
4071 int sequence_type = seq_type;
4072
4073 rval.multithreaded = false;
4074 rval.supports_mask = false;
4075 rval.init = init_noop;
4076 rval.num_inputs = num_inputs_default;
4077 rval.load = load_noop;
4078 rval.free = free_noop;
4079 rval.early_out = early_out_noop;
4080 rval.get_default_fac = get_default_fac_noop;
4081 rval.store_icu_yrange = store_icu_yrange_noop;
4082 rval.execute = NULL;
4083 rval.init_execution = init_execution;
4084 rval.execute_slice = NULL;
4085 rval.copy = NULL;
4086
4087 switch (sequence_type) {
4088 case SEQ_TYPE_CROSS:
4089 rval.multithreaded = true;
4090 rval.execute_slice = do_cross_effect;
4091 rval.early_out = early_out_fade;
4092 rval.get_default_fac = get_default_fac_fade;
4093 break;
4094 case SEQ_TYPE_GAMCROSS:
4095 rval.multithreaded = true;
4096 rval.init = init_gammacross;
4097 rval.load = load_gammacross;
4098 rval.free = free_gammacross;
4099 rval.early_out = early_out_fade;
4100 rval.get_default_fac = get_default_fac_fade;
4101 rval.init_execution = gammacross_init_execution;
4102 rval.execute_slice = do_gammacross_effect;
4103 break;
4104 case SEQ_TYPE_ADD:
4105 rval.multithreaded = true;
4106 rval.execute_slice = do_add_effect;
4107 rval.early_out = early_out_mul_input2;
4108 break;
4109 case SEQ_TYPE_SUB:
4110 rval.multithreaded = true;
4111 rval.execute_slice = do_sub_effect;
4112 rval.early_out = early_out_mul_input2;
4113 break;
4114 case SEQ_TYPE_MUL:
4115 rval.multithreaded = true;
4116 rval.execute_slice = do_mul_effect;
4117 rval.early_out = early_out_mul_input2;
4118 break;
4119 case SEQ_TYPE_SCREEN:
4120 case SEQ_TYPE_OVERLAY:
4121 case SEQ_TYPE_COLOR_BURN:
4122 case SEQ_TYPE_LINEAR_BURN:
4123 case SEQ_TYPE_DARKEN:
4124 case SEQ_TYPE_LIGHTEN:
4125 case SEQ_TYPE_DODGE:
4126 case SEQ_TYPE_SOFT_LIGHT:
4127 case SEQ_TYPE_HARD_LIGHT:
4128 case SEQ_TYPE_PIN_LIGHT:
4129 case SEQ_TYPE_LIN_LIGHT:
4130 case SEQ_TYPE_VIVID_LIGHT:
4131 case SEQ_TYPE_BLEND_COLOR:
4132 case SEQ_TYPE_HUE:
4133 case SEQ_TYPE_SATURATION:
4134 case SEQ_TYPE_VALUE:
4135 case SEQ_TYPE_DIFFERENCE:
4136 case SEQ_TYPE_EXCLUSION:
4137 rval.multithreaded = true;
4138 rval.execute_slice = do_blend_mode_effect;
4139 rval.early_out = early_out_mul_input2;
4140 break;
4141 case SEQ_TYPE_COLORMIX:
4142 rval.multithreaded = true;
4143 rval.init = init_colormix_effect;
4144 rval.free = free_effect_default;
4145 rval.copy = copy_effect_default;
4146 rval.execute_slice = do_colormix_effect;
4147 rval.early_out = early_out_mul_input2;
4148 break;
4149 case SEQ_TYPE_ALPHAOVER:
4150 rval.multithreaded = true;
4151 rval.init = init_alpha_over_or_under;
4152 rval.execute_slice = do_alphaover_effect;
4153 break;
4154 case SEQ_TYPE_OVERDROP:
4155 rval.multithreaded = true;
4156 rval.execute_slice = do_overdrop_effect;
4157 break;
4158 case SEQ_TYPE_ALPHAUNDER:
4159 rval.multithreaded = true;
4160 rval.init = init_alpha_over_or_under;
4161 rval.execute_slice = do_alphaunder_effect;
4162 break;
4163 case SEQ_TYPE_WIPE:
4164 rval.init = init_wipe_effect;
4165 rval.num_inputs = num_inputs_wipe;
4166 rval.free = free_wipe_effect;
4167 rval.copy = copy_wipe_effect;
4168 rval.early_out = early_out_fade;
4169 rval.get_default_fac = get_default_fac_fade;
4170 rval.execute = do_wipe_effect;
4171 break;
4172 case SEQ_TYPE_GLOW:
4173 rval.init = init_glow_effect;
4174 rval.num_inputs = num_inputs_glow;
4175 rval.free = free_glow_effect;
4176 rval.copy = copy_glow_effect;
4177 rval.execute = do_glow_effect;
4178 break;
4179 case SEQ_TYPE_TRANSFORM:
4180 rval.multithreaded = true;
4181 rval.init = init_transform_effect;
4182 rval.num_inputs = num_inputs_transform;
4183 rval.free = free_transform_effect;
4184 rval.copy = copy_transform_effect;
4185 rval.execute_slice = do_transform_effect;
4186 break;
4187 case SEQ_TYPE_SPEED:
4188 rval.init = init_speed_effect;
4189 rval.num_inputs = num_inputs_speed;
4190 rval.load = load_speed_effect;
4191 rval.free = free_speed_effect;
4192 rval.copy = copy_speed_effect;
4193 rval.execute = do_speed_effect;
4194 rval.early_out = early_out_speed;
4195 rval.store_icu_yrange = store_icu_yrange_speed;
4196 break;
4197 case SEQ_TYPE_COLOR:
4198 rval.init = init_solid_color;
4199 rval.num_inputs = num_inputs_color;
4200 rval.early_out = early_out_color;
4201 rval.free = free_solid_color;
4202 rval.copy = copy_solid_color;
4203 rval.execute = do_solid_color;
4204 break;
4205 case SEQ_TYPE_MULTICAM:
4206 rval.num_inputs = num_inputs_multicam;
4207 rval.early_out = early_out_multicam;
4208 rval.execute = do_multicam;
4209 break;
4210 case SEQ_TYPE_ADJUSTMENT:
4211 rval.supports_mask = true;
4212 rval.num_inputs = num_inputs_adjustment;
4213 rval.early_out = early_out_adjustment;
4214 rval.execute = do_adjustment;
4215 break;
4216 case SEQ_TYPE_GAUSSIAN_BLUR:
4217 rval.init = init_gaussian_blur_effect;
4218 rval.num_inputs = num_inputs_gaussian_blur;
4219 rval.free = free_gaussian_blur_effect;
4220 rval.copy = copy_gaussian_blur_effect;
4221 rval.early_out = early_out_gaussian_blur;
4222 rval.execute = do_gaussian_blur_effect;
4223 break;
4224 case SEQ_TYPE_TEXT:
4225 rval.num_inputs = num_inputs_text;
4226 rval.init = init_text_effect;
4227 rval.free = free_text_effect;
4228 rval.load = load_text_effect;
4229 rval.copy = copy_text_effect;
4230 rval.early_out = early_out_text;
4231 rval.execute = do_text_effect;
4232 break;
4233 }
4234
4235 return rval;
4236 }
4237
BKE_sequence_get_effect(Sequence * seq)4238 struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq)
4239 {
4240 struct SeqEffectHandle rval = {false, false, NULL};
4241
4242 if (seq->type & SEQ_TYPE_EFFECT) {
4243 rval = get_sequence_effect_impl(seq->type);
4244 if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
4245 rval.load(seq);
4246 seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
4247 }
4248 }
4249
4250 return rval;
4251 }
4252
BKE_sequence_get_blend(Sequence * seq)4253 struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq)
4254 {
4255 struct SeqEffectHandle rval = {false, false, NULL};
4256
4257 if (seq->blend_mode != 0) {
4258 if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
4259 /* load the effect first */
4260 rval = get_sequence_effect_impl(seq->type);
4261 rval.load(seq);
4262 }
4263
4264 rval = get_sequence_effect_impl(seq->blend_mode);
4265 if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
4266 /* now load the blend and unset unloaded flag */
4267 rval.load(seq);
4268 seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
4269 }
4270 }
4271
4272 return rval;
4273 }
4274
BKE_sequence_effect_get_num_inputs(int seq_type)4275 int BKE_sequence_effect_get_num_inputs(int seq_type)
4276 {
4277 struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
4278
4279 int cnt = rval.num_inputs();
4280 if (rval.execute || (rval.execute_slice && rval.init_execution)) {
4281 return cnt;
4282 }
4283 return 0;
4284 }
4285
BKE_sequence_effect_get_supports_mask(int seq_type)4286 int BKE_sequence_effect_get_supports_mask(int seq_type)
4287 {
4288 struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
4289
4290 return rval.supports_mask;
4291 }
4292