2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
22 * - Blender Foundation, 2003-2009
23 * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/seqeffects.c
37 #include "MEM_guardedalloc.h"
39 #include "BLI_math.h" /* windows needs for M_PI */
40 #include "BLI_utildefines.h"
41 #include "BLI_string.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_sequence_types.h"
45 #include "DNA_anim_types.h"
47 #include "BKE_fcurve.h"
48 #include "BKE_sequencer.h"
50 #include "IMB_imbuf_types.h"
51 #include "IMB_imbuf.h"
52 #include "IMB_colormanagement.h"
54 #include "RNA_access.h"
56 #include "RE_pipeline.h"
60 static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
61 const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
62 unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
64 int offset = 4 * start_line * context->rectx;
66 *rect1 = (unsigned char *)ibuf1->rect + offset;
67 *rect_out = (unsigned char *)out->rect + offset;
70 *rect2 = (unsigned char *)ibuf2->rect + offset;
73 *rect3 = (unsigned char *)ibuf3->rect + offset;
76 static void slice_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
77 const ImBuf *ibuf3, const ImBuf *out, int start_line,
78 float **rect1, float **rect2, float **rect3, float **rect_out)
80 int offset = 4 * start_line * context->rectx;
82 *rect1 = ibuf1->rect_float + offset;
83 *rect_out = out->rect_float + offset;
86 *rect2 = ibuf2->rect_float + offset;
89 *rect3 = ibuf3->rect_float + offset;
92 /*********************** Glow effect *************************/
101 static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
104 Scene *scene = context->scene;
105 int x = context->rectx;
106 int y = context->recty;
108 if (!ibuf1 && !ibuf2 && !ibuf3) {
109 /* hmmm, global float option ? */
110 out = IMB_allocImBuf(x, y, 32, IB_rect);
112 else if ((ibuf1 && ibuf1->rect_float) ||
113 (ibuf2 && ibuf2->rect_float) ||
114 (ibuf3 && ibuf3->rect_float))
116 /* if any inputs are rectfloat, output is float too */
118 out = IMB_allocImBuf(x, y, 32, IB_rectfloat);
121 out = IMB_allocImBuf(x, y, 32, IB_rect);
124 if (ibuf1 && !ibuf1->rect_float && out->rect_float) {
125 BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true);
127 if (ibuf2 && !ibuf2->rect_float && out->rect_float) {
128 BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true);
130 if (ibuf3 && !ibuf3->rect_float && out->rect_float) {
131 BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true);
134 if (ibuf1 && !ibuf1->rect && !out->rect_float) {
135 IMB_rect_from_float(ibuf1);
137 if (ibuf2 && !ibuf2->rect && !out->rect_float) {
138 IMB_rect_from_float(ibuf2);
140 if (ibuf3 && !ibuf3->rect && !out->rect_float) {
141 IMB_rect_from_float(ibuf3);
145 IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name);
150 /*********************** Alpha Over *************************/
152 static void init_alpha_over_or_under(Sequence *seq)
154 Sequence *seq1 = seq->seq1;
155 Sequence *seq2 = seq->seq2;
161 static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
163 float fac2, mfac, fac, fac4;
165 unsigned char *cp1, *cp2, *rt;
166 float tempc[4], rt1[4], rt2[4];
179 /* rt = rt1 over rt2 (alpha from rt1) */
181 straight_uchar_to_premul_float(rt1, cp1);
182 straight_uchar_to_premul_float(rt2, cp2);
185 mfac = 1.0f - fac2 * rt1[3];
187 if (fac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp2);
188 else if (mfac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp1);
190 tempc[0] = fac * rt1[0] + mfac * rt2[0];
191 tempc[1] = fac * rt1[1] + mfac * rt2[1];
192 tempc[2] = fac * rt1[2] + mfac * rt2[2];
193 tempc[3] = fac * rt1[3] + mfac * rt2[3];
195 premul_float_to_straight_uchar(rt, tempc);
197 cp1 += 4; cp2 += 4; rt += 4;
205 straight_uchar_to_premul_float(rt1, cp1);
206 straight_uchar_to_premul_float(rt2, cp2);
209 mfac = 1.0f - (fac4 * rt1[3]);
211 if (fac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp2);
212 else if (mfac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp1);
214 tempc[0] = fac * rt1[0] + mfac * rt2[0];
215 tempc[1] = fac * rt1[1] + mfac * rt2[1];
216 tempc[2] = fac * rt1[2] + mfac * rt2[2];
217 tempc[3] = fac * rt1[3] + mfac * rt2[3];
219 premul_float_to_straight_uchar(rt, tempc);
221 cp1 += 4; cp2 += 4; rt += 4;
226 static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
228 float fac2, mfac, fac, fac4;
230 float *rt1, *rt2, *rt;
243 /* rt = rt1 over rt2 (alpha from rt1) */
246 mfac = 1.0f - (fac2 * rt1[3]);
249 memcpy(rt, rt2, 4 * sizeof(float));
251 else if (mfac <= 0) {
252 memcpy(rt, rt1, 4 * sizeof(float));
255 rt[0] = fac * rt1[0] + mfac * rt2[0];
256 rt[1] = fac * rt1[1] + mfac * rt2[1];
257 rt[2] = fac * rt1[2] + mfac * rt2[2];
258 rt[3] = fac * rt1[3] + mfac * rt2[3];
260 rt1 += 4; rt2 += 4; rt += 4;
270 mfac = 1.0f - (fac4 * rt1[3]);
273 memcpy(rt, rt2, 4 * sizeof(float));
275 else if (mfac <= 0.0f) {
276 memcpy(rt, rt1, 4 * sizeof(float));
279 rt[0] = fac * rt1[0] + mfac * rt2[0];
280 rt[1] = fac * rt1[1] + mfac * rt2[1];
281 rt[2] = fac * rt1[2] + mfac * rt2[2];
282 rt[3] = fac * rt1[3] + mfac * rt2[3];
284 rt1 += 4; rt2 += 4; rt += 4;
289 static void do_alphaover_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0,
290 float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
291 int start_line, int total_lines, ImBuf *out)
293 if (out->rect_float) {
294 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
296 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
298 do_alphaover_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
301 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
303 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
305 do_alphaover_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
309 /*********************** Alpha Under *************************/
311 static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
313 float fac2, fac, fac4;
315 unsigned char *cp1, *cp2, *rt;
316 float tempc[4], rt1[4], rt2[4];
329 /* rt = rt1 under rt2 (alpha from rt2) */
330 straight_uchar_to_premul_float(rt1, cp1);
331 straight_uchar_to_premul_float(rt2, cp2);
333 /* this complex optimization is because the
334 * 'skybuf' can be crossed in
336 if (rt2[3] <= 0.0f && fac2 >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp1);
337 else if (rt2[3] >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp2);
339 fac = (fac2 * (1.0f - rt2[3]));
341 if (fac <= 0) *((unsigned int *) rt) = *((unsigned int *) cp2);
343 tempc[0] = (fac * rt1[0] + rt2[0]);
344 tempc[1] = (fac * rt1[1] + rt2[1]);
345 tempc[2] = (fac * rt1[2] + rt2[2]);
346 tempc[3] = (fac * rt1[3] + rt2[3]);
348 premul_float_to_straight_uchar(rt, tempc);
351 cp1 += 4; cp2 += 4; rt += 4;
360 straight_uchar_to_premul_float(rt1, cp1);
361 straight_uchar_to_premul_float(rt2, cp2);
363 if (rt2[3] <= 0.0f && fac4 >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp1);
364 else if (rt2[3] >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp2);
366 fac = (fac4 * (1.0f - rt2[3]));
368 if (fac <= 0) *((unsigned int *)rt) = *((unsigned int *)cp2);
370 tempc[0] = (fac * rt1[0] + rt2[0]);
371 tempc[1] = (fac * rt1[1] + rt2[1]);
372 tempc[2] = (fac * rt1[2] + rt2[2]);
373 tempc[3] = (fac * rt1[3] + rt2[3]);
375 premul_float_to_straight_uchar(rt, tempc);
378 cp1 += 4; cp2 += 4; rt += 4;
383 static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
385 float fac2, fac, fac4;
387 float *rt1, *rt2, *rt;
400 /* rt = rt1 under rt2 (alpha from rt2) */
402 /* this complex optimization is because the
403 * 'skybuf' can be crossed in
405 if (rt2[3] <= 0 && fac2 >= 1.0f) {
406 memcpy(rt, rt1, 4 * sizeof(float));
408 else if (rt2[3] >= 1.0f) {
409 memcpy(rt, rt2, 4 * sizeof(float));
412 fac = fac2 * (1.0f - rt2[3]);
415 memcpy(rt, rt2, 4 * sizeof(float));
418 rt[0] = fac * rt1[0] + rt2[0];
419 rt[1] = fac * rt1[1] + rt2[1];
420 rt[2] = fac * rt1[2] + rt2[2];
421 rt[3] = fac * rt1[3] + rt2[3];
424 rt1 += 4; rt2 += 4; rt += 4;
433 if (rt2[3] <= 0 && fac4 >= 1.0f) {
434 memcpy(rt, rt1, 4 * sizeof(float));
436 else if (rt2[3] >= 1.0f) {
437 memcpy(rt, rt2, 4 * sizeof(float));
440 fac = fac4 * (1.0f - rt2[3]);
443 memcpy(rt, rt2, 4 * sizeof(float));
446 rt[0] = fac * rt1[0] + rt2[0];
447 rt[1] = fac * rt1[1] + rt2[1];
448 rt[2] = fac * rt1[2] + rt2[2];
449 rt[3] = fac * rt1[3] + rt2[3];
452 rt1 += 4; rt2 += 4; rt += 4;
457 static void do_alphaunder_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra),
458 float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
459 int start_line, int total_lines, ImBuf *out)
461 if (out->rect_float) {
462 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
464 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
466 do_alphaunder_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
469 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
471 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
473 do_alphaunder_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
477 /*********************** Cross *************************/
479 static void do_cross_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
481 int fac1, fac2, fac3, fac4;
483 unsigned char *rt1, *rt2, *rt;
490 fac2 = (int) (256.0f * facf0);
492 fac4 = (int) (256.0f * facf1);
498 rt[0] = (fac1 * rt1[0] + fac2 * rt2[0]) >> 8;
499 rt[1] = (fac1 * rt1[1] + fac2 * rt2[1]) >> 8;
500 rt[2] = (fac1 * rt1[2] + fac2 * rt2[2]) >> 8;
501 rt[3] = (fac1 * rt1[3] + fac2 * rt2[3]) >> 8;
503 rt1 += 4; rt2 += 4; rt += 4;
512 rt[0] = (fac3 * rt1[0] + fac4 * rt2[0]) >> 8;
513 rt[1] = (fac3 * rt1[1] + fac4 * rt2[1]) >> 8;
514 rt[2] = (fac3 * rt1[2] + fac4 * rt2[2]) >> 8;
515 rt[3] = (fac3 * rt1[3] + fac4 * rt2[3]) >> 8;
517 rt1 += 4; rt2 += 4; rt += 4;
523 static void do_cross_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
525 float fac1, fac2, fac3, fac4;
527 float *rt1, *rt2, *rt;
542 rt[0] = fac1 * rt1[0] + fac2 * rt2[0];
543 rt[1] = fac1 * rt1[1] + fac2 * rt2[1];
544 rt[2] = fac1 * rt1[2] + fac2 * rt2[2];
545 rt[3] = fac1 * rt1[3] + fac2 * rt2[3];
547 rt1 += 4; rt2 += 4; rt += 4;
556 rt[0] = fac3 * rt1[0] + fac4 * rt2[0];
557 rt[1] = fac3 * rt1[1] + fac4 * rt2[1];
558 rt[2] = fac3 * rt1[2] + fac4 * rt2[2];
559 rt[3] = fac3 * rt1[3] + fac4 * rt2[3];
561 rt1 += 4; rt2 += 4; rt += 4;
567 static void do_cross_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra),
568 float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
569 int start_line, int total_lines, ImBuf *out)
571 if (out->rect_float) {
572 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
574 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
576 do_cross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
579 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
581 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
583 do_cross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
587 /*********************** Gamma Cross *************************/
589 /* copied code from initrender.c */
590 static unsigned short gamtab[65536];
591 static unsigned short igamtab1[256];
592 static bool gamma_tabs_init = false;
594 #define RE_GAMMA_TABLE_SIZE 400
596 static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
597 static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
598 static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
599 static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
600 static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1];
601 static float color_step;
602 static float inv_color_step;
603 static float valid_gamma;
604 static float valid_inv_gamma;
606 static void makeGammaTables(float gamma)
608 /* we need two tables: one forward, one backward */
612 valid_inv_gamma = 1.0f / gamma;
613 color_step = 1.0f / RE_GAMMA_TABLE_SIZE;
614 inv_color_step = (float) RE_GAMMA_TABLE_SIZE;
616 /* We could squeeze out the two range tables to gain some memory */
617 for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
618 color_domain_table[i] = i * color_step;
619 gamma_range_table[i] = pow(color_domain_table[i], valid_gamma);
620 inv_gamma_range_table[i] = pow(color_domain_table[i], valid_inv_gamma);
623 /* The end of the table should match 1.0 carefully. In order to avoid
624 * rounding errors, we just set this explicitly. The last segment may
625 * have a different length than the other segments, but our
626 * interpolation is insensitive to that
628 color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0;
629 gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
630 inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
632 /* To speed up calculations, we make these calc factor tables. They are
633 * multiplication factors used in scaling the interpolation
635 for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
636 gamfactor_table[i] = inv_color_step * (gamma_range_table[i + 1] - gamma_range_table[i]);
637 inv_gamfactor_table[i] = inv_color_step * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]);
642 static float gammaCorrect(float c)
647 i = floorf(c * inv_color_step);
648 /* Clip to range [0, 1]: outside, just do the complete calculation.
649 * We may have some performance problems here. Stretching up the LUT
650 * may help solve that, by exchanging LUT size for the interpolation.
651 * Negative colors are explicitly handled.
653 if (UNLIKELY(i < 0)) res = -powf(-c, valid_gamma);
654 else if (i >= RE_GAMMA_TABLE_SIZE) res = powf(c, valid_gamma);
655 else res = gamma_range_table[i] +
656 ((c - color_domain_table[i]) * gamfactor_table[i]);
661 /* ------------------------------------------------------------------------- */
663 static float invGammaCorrect(float c)
668 i = floorf(c * inv_color_step);
669 /* Negative colors are explicitly handled */
670 if (UNLIKELY(i < 0)) res = -powf(-c, valid_inv_gamma);
671 else if (i >= RE_GAMMA_TABLE_SIZE) res = powf(c, valid_inv_gamma);
672 else res = inv_gamma_range_table[i] +
673 ((c - color_domain_table[i]) * inv_gamfactor_table[i]);
678 static void gamtabs(float gamma)
680 float val, igamma = 1.0f / gamma;
683 /* gamtab: in short, out short */
684 for (a = 0; a < 65536; a++) {
690 else if (gamma != 1.0f)
691 val = powf(val, igamma);
693 gamtab[a] = (65535.99f * val);
695 /* inverse gamtab1 : in byte, out short */
696 for (a = 1; a <= 256; a++) {
697 if (gamma == 2.0f) igamtab1[a - 1] = a * a - 1;
698 else if (gamma == 1.0f) igamtab1[a - 1] = 256 * a - 1;
701 igamtab1[a - 1] = (65535.0 * pow(val, gamma)) - 1;
706 static void build_gammatabs(void)
708 if (gamma_tabs_init == false) {
710 makeGammaTables(2.0f);
711 gamma_tabs_init = true;
715 static void init_gammacross(Sequence *UNUSED(seq))
719 static void load_gammacross(Sequence *UNUSED(seq))
723 static void free_gammacross(Sequence *UNUSED(seq))
727 static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), int x, int y, unsigned char *rect1,
728 unsigned char *rect2, unsigned char *out)
732 unsigned char *cp1, *cp2, *rt;
733 float rt1[4], rt2[4], tempc[4];
746 straight_uchar_to_premul_float(rt1, cp1);
747 straight_uchar_to_premul_float(rt2, cp2);
749 tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
750 tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
751 tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
752 tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
754 premul_float_to_straight_uchar(rt, tempc);
755 cp1 += 4; cp2 += 4; rt += 4;
764 straight_uchar_to_premul_float(rt1, cp1);
765 straight_uchar_to_premul_float(rt2, cp2);
767 tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
768 tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
769 tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
770 tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
772 premul_float_to_straight_uchar(rt, tempc);
773 cp1 += 4; cp2 += 4; rt += 4;
778 static void do_gammacross_effect_float(float facf0, float UNUSED(facf1), int x, int y, float *rect1,
779 float *rect2, float *out)
783 float *rt1, *rt2, *rt;
796 *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
806 *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
813 static struct ImBuf *gammacross_init_execution(const SeqRenderData *context, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
815 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
821 static void do_gammacross_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra),
822 float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
823 int start_line, int total_lines, ImBuf *out)
825 if (out->rect_float) {
826 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
828 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
830 do_gammacross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
833 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
835 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
837 do_gammacross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
841 /*********************** Add *************************/
843 static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2,
847 unsigned char *cp1, *cp2, *rt;
854 fac1 = (int)(256.0f * facf0);
855 fac3 = (int)(256.0f * facf1);
861 rt[0] = min_ii(cp1[0] + ((fac1 * cp2[0]) >> 8), 255);
862 rt[1] = min_ii(cp1[1] + ((fac1 * cp2[1]) >> 8), 255);
863 rt[2] = min_ii(cp1[2] + ((fac1 * cp2[2]) >> 8), 255);
866 cp1 += 4; cp2 += 4; rt += 4;
875 rt[0] = min_ii(cp1[0] + ((fac3 * cp2[0]) >> 8), 255);
876 rt[1] = min_ii(cp1[1] + ((fac3 * cp2[1]) >> 8), 255);
877 rt[2] = min_ii(cp1[2] + ((fac3 * cp2[2]) >> 8), 255);
880 cp1 += 4; cp2 += 4; rt += 4;
885 static void do_add_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
889 float *rt1, *rt2, *rt;
902 m = 1.0f - (rt1[3] * (1.0f - fac1));
903 rt[0] = rt1[0] + m * rt2[0];
904 rt[1] = rt1[1] + m * rt2[1];
905 rt[2] = rt1[2] + m * rt2[2];
908 rt1 += 4; rt2 += 4; rt += 4;
917 m = 1.0f - (rt1[3] * (1.0f - fac3));
918 rt[0] = rt1[0] + m * rt2[0];
919 rt[1] = rt1[1] + m * rt2[1];
920 rt[2] = rt1[2] + m * rt2[2];
923 rt1 += 4; rt2 += 4; rt += 4;
928 static void do_add_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
929 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
931 if (out->rect_float) {
932 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
934 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
936 do_add_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
939 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
941 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
943 do_add_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
947 /*********************** Sub *************************/
949 static void do_sub_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
952 unsigned char *cp1, *cp2, *rt;
959 fac1 = (int) (256.0f * facf0);
960 fac3 = (int) (256.0f * facf1);
965 rt[0] = max_ii(cp1[0] - ((fac1 * cp2[0]) >> 8), 0);
966 rt[1] = max_ii(cp1[1] - ((fac1 * cp2[1]) >> 8), 0);
967 rt[2] = max_ii(cp1[2] - ((fac1 * cp2[2]) >> 8), 0);
970 cp1 += 4; cp2 += 4; rt += 4;
979 rt[0] = max_ii(cp1[0] - ((fac3 * cp2[0]) >> 8), 0);
980 rt[1] = max_ii(cp1[1] - ((fac3 * cp2[1]) >> 8), 0);
981 rt[2] = max_ii(cp1[2] - ((fac3 * cp2[2]) >> 8), 0);
984 cp1 += 4; cp2 += 4; rt += 4;
989 static void do_sub_effect_float(float UNUSED(facf0), float facf1, int x, int y, float *rect1, float *rect2, float *out)
992 float m /*, fac1*/, fac3;
993 float *rt1, *rt2, *rt;
1007 m = 1.0f - (rt1[3] * (1 - fac3));
1008 rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
1009 rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
1010 rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
1013 rt1 += 4; rt2 += 4; rt += 4;
1022 m = 1.0f - (rt1[3] * (1 - fac3));
1023 rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
1024 rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
1025 rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
1028 rt1 += 4; rt2 += 4; rt += 4;
1033 static void do_sub_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
1034 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
1036 if (out->rect_float) {
1037 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1039 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1041 do_sub_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1044 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1046 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1048 do_sub_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1052 /*********************** Drop *************************/
1054 /* Must be > 0 or add precopy, etc to the function */
1058 static void do_drop_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect2i, unsigned char *rect1i, unsigned char *outi)
1060 int height, width, temp, fac, fac1, fac2;
1061 unsigned char *rt1, *rt2, *out;
1067 fac1 = (int) (70.0f * facf0);
1068 fac2 = (int) (70.0f * facf1);
1070 rt2 = (unsigned char *) (rect2i + YOFF * width);
1071 rt1 = (unsigned char *) rect1i;
1072 out = (unsigned char *) outi;
1073 for (y = 0; y < height - YOFF; y++) {
1074 if (field) fac = fac1;
1078 memcpy(out, rt1, sizeof(int) * XOFF);
1082 for (x = XOFF; x < width; x++) {
1083 temp = ((fac * rt2[3]) >> 8);
1085 *(out++) = MAX2(0, *rt1 - temp); rt1++;
1086 *(out++) = MAX2(0, *rt1 - temp); rt1++;
1087 *(out++) = MAX2(0, *rt1 - temp); rt1++;
1088 *(out++) = MAX2(0, *rt1 - temp); rt1++;
1093 memcpy(out, rt1, sizeof(int) * YOFF * width);
1096 static void do_drop_effect_float(float facf0, float facf1, int x, int y, float *rect2i, float *rect1i, float *outi)
1099 float temp, fac, fac1, fac2;
1100 float *rt1, *rt2, *out;
1106 fac1 = 70.0f * facf0;
1107 fac2 = 70.0f * facf1;
1109 rt2 = (rect2i + YOFF * width);
1112 for (y = 0; y < height - YOFF; y++) {
1113 if (field) fac = fac1;
1117 memcpy(out, rt1, 4 * sizeof(float) * XOFF);
1121 for (x = XOFF; x < width; x++) {
1122 temp = fac * rt2[3];
1124 *(out++) = MAX2(0.0f, *rt1 - temp); rt1++;
1125 *(out++) = MAX2(0.0f, *rt1 - temp); rt1++;
1126 *(out++) = MAX2(0.0f, *rt1 - temp); rt1++;
1127 *(out++) = MAX2(0.0f, *rt1 - temp); rt1++;
1132 memcpy(out, rt1, 4 * sizeof(float) * YOFF * width);
1135 /*********************** Mul *************************/
1137 static void do_mul_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2,
1141 unsigned char *rt1, *rt2, *rt;
1148 fac1 = (int)(256.0f * facf0);
1149 fac3 = (int)(256.0f * facf1);
1152 * fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + axaux = c * px + py * s; //+centx
1153 * yaux = -s * px + c * py; //+centy
1161 rt[0] = rt1[0] + ((fac1 * rt1[0] * (rt2[0] - 255)) >> 16);
1162 rt[1] = rt1[1] + ((fac1 * rt1[1] * (rt2[1] - 255)) >> 16);
1163 rt[2] = rt1[2] + ((fac1 * rt1[2] * (rt2[2] - 255)) >> 16);
1164 rt[3] = rt1[3] + ((fac1 * rt1[3] * (rt2[3] - 255)) >> 16);
1166 rt1 += 4; rt2 += 4; rt += 4;
1175 rt[0] = rt1[0] + ((fac3 * rt1[0] * (rt2[0] - 255)) >> 16);
1176 rt[1] = rt1[1] + ((fac3 * rt1[1] * (rt2[1] - 255)) >> 16);
1177 rt[2] = rt1[2] + ((fac3 * rt1[2] * (rt2[2] - 255)) >> 16);
1178 rt[3] = rt1[3] + ((fac3 * rt1[3] * (rt2[3] - 255)) >> 16);
1180 rt1 += 4; rt2 += 4; rt += 4;
1185 static void do_mul_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
1189 float *rt1, *rt2, *rt;
1200 * fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + a
1206 rt[0] = rt1[0] + fac1 * rt1[0] * (rt2[0] - 1.0f);
1207 rt[1] = rt1[1] + fac1 * rt1[1] * (rt2[1] - 1.0f);
1208 rt[2] = rt1[2] + fac1 * rt1[2] * (rt2[2] - 1.0f);
1209 rt[3] = rt1[3] + fac1 * rt1[3] * (rt2[3] - 1.0f);
1211 rt1 += 4; rt2 += 4; rt += 4;
1220 rt[0] = rt1[0] + fac3 * rt1[0] * (rt2[0] - 1.0f);
1221 rt[1] = rt1[1] + fac3 * rt1[1] * (rt2[1] - 1.0f);
1222 rt[2] = rt1[2] + fac3 * rt1[2] * (rt2[2] - 1.0f);
1223 rt[3] = rt1[3] + fac3 * rt1[3] * (rt2[3] - 1.0f);
1225 rt1 += 4; rt2 += 4; rt += 4;
1230 static void do_mul_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
1231 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
1233 if (out->rect_float) {
1234 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1236 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1238 do_mul_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1241 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1243 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1245 do_mul_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1249 /*********************** Wipe *************************/
1251 typedef struct WipeZone {
1259 static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
1261 wipezone->flip = (wipe->angle < 0.0f);
1262 wipezone->angle = tanf(fabsf(wipe->angle));
1265 wipezone->width = (int)(wipe->edgeWidth * ((xo + yo) / 2.0f));
1266 wipezone->pythangle = 1.0f / sqrtf(wipezone->angle * wipezone->angle + 1.0f);
1269 /* This function calculates the blur band for the wipe effects */
1270 static float in_band(float width, float dist, int side, int dir)
1281 alpha = (dist + 0.5f * width) / (width);
1283 alpha = (0.5f * width - dist) / (width);
1291 static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float facf0)
1293 float posx, posy, hyp, hyp2, angle, hwidth, b1, b2, b3, pointdist;
1294 /* some future stuff */
1295 /* float hyp3, hyp4, b4, b5 */
1296 float temp1, temp2, temp3, temp4; /* some placeholder variables */
1297 int xo = wipezone->xo;
1298 int yo = wipezone->yo;
1299 float halfx = xo * 0.5f;
1300 float halfy = yo * 0.5f;
1301 float widthf, output = 0;
1302 WipeVars *wipe = (WipeVars *)seq->effectdata;
1305 if (wipezone->flip) x = xo - x;
1306 angle = wipezone->angle;
1308 if (wipe->forward) {
1313 posx = xo - facf0 * xo;
1314 posy = yo - facf0 * yo;
1317 switch (wipe->wipetype) {
1318 case DO_SINGLE_WIPE:
1319 width = min_ii(wipezone->width, facf0 * yo);
1320 width = min_ii(width, yo - facf0 * yo);
1322 if (angle == 0.0f) {
1325 hyp = fabsf(y - posy);
1328 b1 = posy - (-angle) * posx;
1329 b2 = y - (-angle) * x;
1330 hyp = fabsf(angle * x + y + (-posy - angle * posx)) * wipezone->pythangle;
1339 if (wipe->forward) {
1341 output = in_band(width, hyp, 1, 1);
1343 output = in_band(width, hyp, 0, 1);
1347 output = in_band(width, hyp, 0, 1);
1349 output = in_band(width, hyp, 1, 1);
1353 case DO_DOUBLE_WIPE:
1355 facf0 = 1.0f - facf0; /* Go the other direction */
1357 width = wipezone->width; /* calculate the blur width */
1358 hwidth = width * 0.5f;
1361 b3 = yo - posy * 0.5f;
1364 hyp = fabsf(y - posy * 0.5f);
1365 hyp2 = fabsf(y - (yo - posy * 0.5f));
1368 b1 = posy * 0.5f - (-angle) * posx * 0.5f;
1369 b3 = (yo - posy * 0.5f) - (-angle) * (xo - posx * 0.5f);
1370 b2 = y - (-angle) * x;
1372 hyp = fabsf(angle * x + y + (-posy * 0.5f - angle * posx * 0.5f)) * wipezone->pythangle;
1373 hyp2 = fabsf(angle * x + y + (-(yo - posy * 0.5f) - angle * (xo - posx * 0.5f))) * wipezone->pythangle;
1376 hwidth = min_ff(hwidth, fabsf(b3 - b1) / 2.0f);
1378 if (b2 < b1 && b2 < b3) {
1379 output = in_band(hwidth, hyp, 0, 1);
1381 else if (b2 > b1 && b2 > b3) {
1382 output = in_band(hwidth, hyp2, 0, 1);
1385 if (hyp < hwidth && hyp2 > hwidth)
1386 output = in_band(hwidth, hyp, 1, 1);
1387 else if (hyp > hwidth && hyp2 < hwidth)
1388 output = in_band(hwidth, hyp2, 1, 1);
1390 output = in_band(hwidth, hyp2, 1, 1) * in_band(hwidth, hyp, 1, 1);
1392 if (!wipe->forward) output = 1 - output;
1396 * temp1: angle of effect center in rads
1397 * temp2: angle of line through (halfx, halfy) and (x, y) in rads
1398 * temp3: angle of low side of blur
1399 * temp4: angle of high side of blur
1401 output = 1.0f - facf0;
1402 widthf = wipe->edgeWidth * 2.0f * (float)M_PI;
1403 temp1 = 2.0f * (float)M_PI * facf0;
1405 if (wipe->forward) {
1406 temp1 = 2.0f * (float)M_PI - temp1;
1412 temp2 = asin(abs(y) / hypot(x, y));
1413 if (x <= 0 && y >= 0) temp2 = (float)M_PI - temp2;
1414 else if (x <= 0 && y <= 0) temp2 += (float)M_PI;
1415 else if (x >= 0 && y <= 0) temp2 = 2.0f * (float)M_PI - temp2;
1417 if (wipe->forward) {
1418 temp3 = temp1 - (widthf * 0.5f) * facf0;
1419 temp4 = temp1 + (widthf * 0.5f) * (1 - facf0);
1422 temp3 = temp1 - (widthf * 0.5f) * (1 - facf0);
1423 temp4 = temp1 + (widthf * 0.5f) * facf0;
1425 if (temp3 < 0) temp3 = 0;
1426 if (temp4 > 2.0f * (float)M_PI) temp4 = 2.0f * (float)M_PI;
1429 if (temp2 < temp3) output = 0;
1430 else if (temp2 > temp4) output = 1;
1431 else output = (temp2 - temp3) / (temp4 - temp3);
1432 if (x == 0 && y == 0) output = 1;
1433 if (output != output) output = 1;
1434 if (wipe->forward) output = 1 - output;
1436 /* BOX WIPE IS NOT WORKING YET */
1437 /* case DO_CROSS_WIPE: */
1438 /* BOX WIPE IS NOT WORKING YET */
1441 if (invert) facf0 = 1 - facf0;
1443 width = (int)(wipe->edgeWidth * ((xo + yo) / 2.0));
1444 hwidth = (float)width / 2.0;
1445 if (angle == 0) angle = 0.000001;
1446 b1 = posy / 2 - (-angle) * posx / 2;
1447 b3 = (yo - posy / 2) - (-angle) * (xo - posx / 2);
1448 b2 = y - (-angle) * x;
1450 hyp = abs(angle * x + y + (-posy / 2 - angle * posx / 2)) * wipezone->pythangle;
1451 hyp2 = abs(angle * x + y + (-(yo - posy / 2) - angle * (xo - posx / 2))) * wipezone->pythangle;
1453 temp1 = xo * (1 - facf0 / 2) - xo * facf0 / 2;
1454 temp2 = yo * (1 - facf0 / 2) - yo * facf0 / 2;
1455 pointdist = hypot(temp1, temp2);
1457 if (b2 < b1 && b2 < b3) {
1458 if (hwidth < pointdist)
1459 output = in_band(wipezone, hwidth, hyp, facf0, 0, 1);
1461 else if (b2 > b1 && b2 > b3) {
1462 if (hwidth < pointdist)
1463 output = in_band(wipezone, hwidth, hyp2, facf0, 0, 1);
1466 if (hyp < hwidth && hyp2 > hwidth)
1467 output = in_band(wipezone, hwidth, hyp, facf0, 1, 1);
1468 else if (hyp > hwidth && hyp2 < hwidth)
1469 output = in_band(wipezone, hwidth, hyp2, facf0, 1, 1);
1471 output = in_band(wipezone, hwidth, hyp2, facf0, 1, 1) * in_band(wipezone, hwidth, hyp, facf0, 1, 1);
1474 if (invert) facf0 = 1 - facf0;
1476 b1 = posy / 2 - (-angle) * posx / 2;
1477 b3 = (yo - posy / 2) - (-angle) * (xo - posx / 2);
1478 b2 = y - (-angle) * x;
1480 hyp = abs(angle * x + y + (-posy / 2 - angle * posx / 2)) * wipezone->pythangle;
1481 hyp2 = abs(angle * x + y + (-(yo - posy / 2) - angle * (xo - posx / 2))) * wipezone->pythangle;
1483 if (b2 < b1 && b2 < b3) {
1484 if (hwidth < pointdist)
1485 output *= in_band(wipezone, hwidth, hyp, facf0, 0, 1);
1487 else if (b2 > b1 && b2 > b3) {
1488 if (hwidth < pointdist)
1489 output *= in_band(wipezone, hwidth, hyp2, facf0, 0, 1);
1492 if (hyp < hwidth && hyp2 > hwidth)
1493 output *= in_band(wipezone, hwidth, hyp, facf0, 1, 1);
1494 else if (hyp > hwidth && hyp2 < hwidth)
1495 output *= in_band(wipezone, hwidth, hyp2, facf0, 1, 1);
1497 output *= in_band(wipezone, hwidth, hyp2, facf0, 1, 1) * in_band(wipezone, hwidth, hyp, facf0, 1, 1);
1503 if (xo > yo) yo = xo;
1506 if (!wipe->forward) facf0 = 1 - facf0;
1508 width = wipezone->width;
1509 hwidth = width * 0.5f;
1511 temp1 = (halfx - (halfx) * facf0);
1512 pointdist = hypotf(temp1, temp1);
1514 temp2 = hypotf(halfx - x, halfy - y);
1515 if (temp2 > pointdist) output = in_band(hwidth, fabsf(temp2 - pointdist), 0, 1);
1516 else output = in_band(hwidth, fabsf(temp2 - pointdist), 1, 1);
1518 if (!wipe->forward) output = 1 - output;
1522 if (output < 0) output = 0;
1523 else if (output > 1) output = 1;
1527 static void init_wipe_effect(Sequence *seq)
1529 if (seq->effectdata)
1530 MEM_freeN(seq->effectdata);
1532 seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
1535 static int num_inputs_wipe(void)
1540 static void free_wipe_effect(Sequence *seq)
1542 if (seq->effectdata)
1543 MEM_freeN(seq->effectdata);
1545 seq->effectdata = NULL;
1548 static void copy_wipe_effect(Sequence *dst, Sequence *src)
1550 dst->effectdata = MEM_dupallocN(src->effectdata);
1553 static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1), int x, int y, unsigned char *rect1,
1554 unsigned char *rect2, unsigned char *out)
1557 WipeVars *wipe = (WipeVars *)seq->effectdata;
1559 unsigned char *cp1, *cp2, *rt;
1561 precalc_wipe_zone(&wipezone, wipe, x, y);
1569 for (y = 0; y < yo; y++) {
1570 for (x = 0; x < xo; x++) {
1571 float check = check_zone(&wipezone, x, y, seq, facf0);
1574 float rt1[4], rt2[4], tempc[4];
1576 straight_uchar_to_premul_float(rt1, cp1);
1577 straight_uchar_to_premul_float(rt2, cp2);
1579 tempc[0] = rt1[0] * check + rt2[0] * (1 - check);
1580 tempc[1] = rt1[1] * check + rt2[1] * (1 - check);
1581 tempc[2] = rt1[2] * check + rt2[2] * (1 - check);
1582 tempc[3] = rt1[3] * check + rt2[3] * (1 - check);
1584 premul_float_to_straight_uchar(rt, tempc);
1619 static void do_wipe_effect_float(Sequence *seq, float facf0, float UNUSED(facf1), int x, int y, float *rect1,
1620 float *rect2, float *out)
1623 WipeVars *wipe = (WipeVars *)seq->effectdata;
1625 float *rt1, *rt2, *rt;
1627 precalc_wipe_zone(&wipezone, wipe, x, y);
1635 for (y = 0; y < yo; y++) {
1636 for (x = 0; x < xo; x++) {
1637 float check = check_zone(&wipezone, x, y, seq, facf0);
1640 rt[0] = rt1[0] * check + rt2[0] * (1 - check);
1641 rt[1] = rt1[1] * check + rt2[1] * (1 - check);
1642 rt[2] = rt1[2] * check + rt2[2] * (1 - check);
1643 rt[3] = rt1[3] * check + rt2[3] * (1 - check);
1678 static ImBuf *do_wipe_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float facf0, float facf1,
1679 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
1681 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
1683 if (out->rect_float) {
1684 do_wipe_effect_float(seq, facf0, facf1, context->rectx, context->recty, ibuf1->rect_float,
1685 ibuf2->rect_float, out->rect_float);
1688 do_wipe_effect_byte(seq, facf0, facf1, context->rectx, context->recty, (unsigned char *) ibuf1->rect,
1689 (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
1695 /*********************** Transform *************************/
1697 static void init_transform_effect(Sequence *seq)
1699 TransformVars *transform;
1701 if (seq->effectdata)
1702 MEM_freeN(seq->effectdata);
1704 seq->effectdata = MEM_callocN(sizeof(TransformVars), "transformvars");
1706 transform = (TransformVars *) seq->effectdata;
1708 transform->ScalexIni = 1.0f;
1709 transform->ScaleyIni = 1.0f;
1711 transform->xIni = 0.0f;
1712 transform->yIni = 0.0f;
1714 transform->rotIni = 0.0f;
1716 transform->interpolation = 1;
1717 transform->percent = 1;
1718 transform->uniform_scale = 0;
1721 static int num_inputs_transform(void)
1726 static void free_transform_effect(Sequence *seq)
1728 if (seq->effectdata) MEM_freeN(seq->effectdata);
1729 seq->effectdata = NULL;
1732 static void copy_transform_effect(Sequence *dst, Sequence *src)
1734 dst->effectdata = MEM_dupallocN(src->effectdata);
1737 static void transform_image(int x, int y, ImBuf *ibuf1, ImBuf *out, float scale_x, float scale_y,
1738 float translate_x, float translate_y, float rotate, int interpolation)
1741 float xt, yt, xr, yr;
1751 for (yi = 0; yi < yo; yi++) {
1752 for (xi = 0; xi < xo; xi++) {
1753 /* translate point */
1754 xt = xi - translate_x;
1755 yt = yi - translate_y;
1757 /* rotate point with center ref */
1758 xr = c * xt + s * yt;
1759 yr = -s * xt + c * yt;
1761 /* scale point with center ref */
1765 /* undo reference center point */
1770 switch (interpolation) {
1772 nearest_interpolation(ibuf1, out, xt, yt, xi, yi);
1775 bilinear_interpolation(ibuf1, out, xt, yt, xi, yi);
1778 bicubic_interpolation(ibuf1, out, xt, yt, xi, yi);
1785 static void do_transform(Scene *scene, Sequence *seq, float UNUSED(facf0), int x, int y, ImBuf *ibuf1, ImBuf *out)
1787 TransformVars *transform = (TransformVars *) seq->effectdata;
1788 float scale_x, scale_y, translate_x, translate_y, rotate_radians;
1791 if (transform->uniform_scale) {
1792 scale_x = scale_y = transform->ScalexIni;
1795 scale_x = transform->ScalexIni;
1796 scale_y = transform->ScaleyIni;
1800 if (!transform->percent) {
1801 float rd_s = (scene->r.size / 100.0f);
1803 translate_x = transform->xIni * rd_s + (x / 2.0f);
1804 translate_y = transform->yIni * rd_s + (y / 2.0f);
1807 translate_x = x * (transform->xIni / 100.0f) + (x / 2.0f);
1808 translate_y = y * (transform->yIni / 100.0f) + (y / 2.0f);
1812 rotate_radians = DEG2RADF(transform->rotIni);
1814 transform_image(x, y, ibuf1, out, scale_x, scale_y, translate_x, translate_y, rotate_radians, transform->interpolation);
1818 static ImBuf *do_transform_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float facf0,
1819 float UNUSED(facf1), ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
1821 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
1823 do_transform(context->scene, seq, facf0, context->rectx, context->recty, ibuf1, out);
1828 /*********************** Glow *************************/
1830 static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality)
1831 /* MUUUCCH better than the previous blur. */
1832 /* We do the blurring in two passes which is a whole lot faster. */
1833 /* I changed the math arount to implement an actual Gaussian */
1836 /* Watch out though, it tends to misbehaven with large blur values on */
1837 /* a small bitmap. Avoid avoid avoid. */
1838 /*=============================== */
1840 float *temp = NULL, *swap;
1841 float *filter = NULL;
1842 int x, y, i, fx, fy;
1843 int index, ix, halfWidth;
1844 float fval, k, curColor[3], curColor2[3], weight = 0;
1846 /* If we're not really blurring, bail out */
1850 /* Allocate memory for the tempmap and the blur filter matrix */
1851 temp = MEM_mallocN((width * height * 4 * sizeof(float)), "blurbitmaptemp");
1855 /* Allocate memory for the filter elements */
1856 halfWidth = ((quality + 1) * blur);
1857 filter = (float *)MEM_mallocN(sizeof(float) * halfWidth * 2, "blurbitmapfilter");
1863 /* Apparently we're calculating a bell curve based on the standard deviation (or radius)
1864 * This code is based on an example posted to comp.graphics.algorithms by
1865 * Blancmange (bmange@airdmhor.gen.nz)
1868 k = -1.0f / (2.0f * (float)M_PI * blur * blur);
1870 for (ix = 0; ix < halfWidth; ix++) {
1871 weight = (float)exp(k * (ix * ix));
1872 filter[halfWidth - ix] = weight;
1873 filter[halfWidth + ix] = weight;
1877 /* Normalize the array */
1879 for (ix = 0; ix < halfWidth * 2; ix++)
1882 for (ix = 0; ix < halfWidth * 2; ix++)
1886 for (y = 0; y < height; y++) {
1887 /* Do the left & right strips */
1888 for (x = 0; x < halfWidth; x++) {
1889 index = (x + y * width) * 4;
1891 curColor[0] = curColor[1] = curColor[2] = 0.0f;
1892 curColor2[0] = curColor2[1] = curColor2[2] = 0.0f;
1894 for (i = x - halfWidth; i < x + halfWidth; i++) {
1895 if ((i >= 0) && (i < width)) {
1896 curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx];
1897 curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx];
1898 curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx];
1900 curColor2[0] += map[(width - 1 - i + y * width) * 4 + GlowR] * filter[fx];
1901 curColor2[1] += map[(width - 1 - i + y * width) * 4 + GlowG] * filter[fx];
1902 curColor2[2] += map[(width - 1 - i + y * width) * 4 + GlowB] * filter[fx];
1906 temp[index + GlowR] = curColor[0];
1907 temp[index + GlowG] = curColor[1];
1908 temp[index + GlowB] = curColor[2];
1910 temp[((width - 1 - x + y * width) * 4) + GlowR] = curColor2[0];
1911 temp[((width - 1 - x + y * width) * 4) + GlowG] = curColor2[1];
1912 temp[((width - 1 - x + y * width) * 4) + GlowB] = curColor2[2];
1916 /* Do the main body */
1917 for (x = halfWidth; x < width - halfWidth; x++) {
1918 index = (x + y * width) * 4;
1921 for (i = x - halfWidth; i < x + halfWidth; i++) {
1922 curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx];
1923 curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx];
1924 curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx];
1927 temp[index + GlowR] = curColor[0];
1928 temp[index + GlowG] = curColor[1];
1929 temp[index + GlowB] = curColor[2];
1934 swap = temp; temp = map; map = swap;
1936 /* Blur the columns */
1937 for (x = 0; x < width; x++) {
1938 /* Do the top & bottom strips */
1939 for (y = 0; y < halfWidth; y++) {
1940 index = (x + y * width) * 4;
1944 for (i = y - halfWidth; i < y + halfWidth; i++) {
1945 if ((i >= 0) && (i < height)) {
1947 curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy];
1948 curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy];
1949 curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy];
1952 curColor2[0] += map[(x + (height - 1 - i) * width) * 4 + GlowR] * filter[fy];
1953 curColor2[1] += map[(x + (height - 1 - i) * width) * 4 + GlowG] * filter[fy];
1954 curColor2[2] += map[(x + (height - 1 - i) * width) * 4 + GlowB] * filter[fy];
1958 temp[index + GlowR] = curColor[0];
1959 temp[index + GlowG] = curColor[1];
1960 temp[index + GlowB] = curColor[2];
1961 temp[((x + (height - 1 - y) * width) * 4) + GlowR] = curColor2[0];
1962 temp[((x + (height - 1 - y) * width) * 4) + GlowG] = curColor2[1];
1963 temp[((x + (height - 1 - y) * width) * 4) + GlowB] = curColor2[2];
1966 /* Do the main body */
1967 for (y = halfWidth; y < height - halfWidth; y++) {
1968 index = (x + y * width) * 4;
1971 for (i = y - halfWidth; i < y + halfWidth; i++) {
1972 curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy];
1973 curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy];
1974 curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy];
1977 temp[index + GlowR] = curColor[0];
1978 temp[index + GlowG] = curColor[1];
1979 temp[index + GlowB] = curColor[2];
1984 swap = temp; temp = map; /* map = swap; */ /* UNUSED */
1991 static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int height)
1995 for (y = 0; y < height; y++) {
1996 for (x = 0; x < width; x++) {
1997 index = (x + y * width) * 4;
1998 c[index + GlowR] = MIN2(1.0f, a[index + GlowR] + b[index + GlowR]);
1999 c[index + GlowG] = MIN2(1.0f, a[index + GlowG] + b[index + GlowG]);
2000 c[index + GlowB] = MIN2(1.0f, a[index + GlowB] + b[index + GlowB]);
2001 c[index + GlowA] = MIN2(1.0f, a[index + GlowA] + b[index + GlowA]);
2006 static void RVIsolateHighlights_float(float *in, float *out, int width, int height, float threshold, float boost, float clamp)
2011 for (y = 0; y < height; y++) {
2012 for (x = 0; x < width; x++) {
2013 index = (x + y * width) * 4;
2015 /* Isolate the intensity */
2016 intensity = (in[index + GlowR] + in[index + GlowG] + in[index + GlowB] - threshold);
2017 if (intensity > 0) {
2018 out[index + GlowR] = MIN2(clamp, (in[index + GlowR] * boost * intensity));
2019 out[index + GlowG] = MIN2(clamp, (in[index + GlowG] * boost * intensity));
2020 out[index + GlowB] = MIN2(clamp, (in[index + GlowB] * boost * intensity));
2021 out[index + GlowA] = MIN2(clamp, (in[index + GlowA] * boost * intensity));
2024 out[index + GlowR] = 0;
2025 out[index + GlowG] = 0;
2026 out[index + GlowB] = 0;
2027 out[index + GlowA] = 0;
2033 static void init_glow_effect(Sequence *seq)
2037 if (seq->effectdata)
2038 MEM_freeN(seq->effectdata);
2040 seq->effectdata = MEM_callocN(sizeof(GlowVars), "glowvars");
2042 glow = (GlowVars *)seq->effectdata;
2051 static int num_inputs_glow(void)
2056 static void free_glow_effect(Sequence *seq)
2058 if (seq->effectdata)
2059 MEM_freeN(seq->effectdata);
2061 seq->effectdata = NULL;
2064 static void copy_glow_effect(Sequence *dst, Sequence *src)
2066 dst->effectdata = MEM_dupallocN(src->effectdata);
2069 static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y,
2070 unsigned char *rect1, unsigned char *UNUSED(rect2), unsigned char *out)
2072 float *outbuf, *inbuf;
2073 GlowVars *glow = (GlowVars *)seq->effectdata;
2075 inbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect input");
2076 outbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect output");
2078 IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, x, y, x, x);
2079 IMB_buffer_float_premultiply(inbuf, x, y);
2081 RVIsolateHighlights_float(inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
2082 RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
2084 RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
2086 IMB_buffer_float_unpremultiply(outbuf, x, y);
2087 IMB_buffer_byte_from_float(out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, x, y, x, x);
2093 static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y,
2094 float *rect1, float *UNUSED(rect2), float *out)
2096 float *outbuf = out;
2097 float *inbuf = rect1;
2098 GlowVars *glow = (GlowVars *)seq->effectdata;
2100 RVIsolateHighlights_float(inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
2101 RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
2103 RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
2106 static ImBuf *do_glow_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float facf0, float facf1,
2107 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
2109 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2111 int render_size = 100 * context->rectx / context->scene->r.xsch;
2113 if (out->rect_float) {
2114 do_glow_effect_float(seq, render_size, facf0, facf1, context->rectx, context->recty,
2115 ibuf1->rect_float, ibuf2->rect_float, out->rect_float);
2118 do_glow_effect_byte(seq, render_size, facf0, facf1, context->rectx, context->recty,
2119 (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
2125 /*********************** Solid color *************************/
2127 static void init_solid_color(Sequence *seq)
2131 if (seq->effectdata)
2132 MEM_freeN(seq->effectdata);
2134 seq->effectdata = MEM_callocN(sizeof(SolidColorVars), "solidcolor");
2136 cv = (SolidColorVars *)seq->effectdata;
2137 cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
2140 static int num_inputs_color(void)
2145 static void free_solid_color(Sequence *seq)
2147 if (seq->effectdata)
2148 MEM_freeN(seq->effectdata);
2150 seq->effectdata = NULL;
2153 static void copy_solid_color(Sequence *dst, Sequence *src)
2155 dst->effectdata = MEM_dupallocN(src->effectdata);
2158 static int early_out_color(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2160 return EARLY_NO_INPUT;
2163 static ImBuf *do_solid_color(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float facf0, float facf1,
2164 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
2166 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2168 SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
2170 unsigned char *rect;
2172 int x; /*= context->rectx;*/ /*UNUSED*/
2173 int y; /*= context->recty;*/ /*UNUSED*/
2176 unsigned char col0[3];
2177 unsigned char col1[3];
2179 col0[0] = facf0 * cv->col[0] * 255;
2180 col0[1] = facf0 * cv->col[1] * 255;
2181 col0[2] = facf0 * cv->col[2] * 255;
2183 col1[0] = facf1 * cv->col[0] * 255;
2184 col1[1] = facf1 * cv->col[1] * 255;
2185 col1[2] = facf1 * cv->col[2] * 255;
2187 rect = (unsigned char *)out->rect;
2189 for (y = 0; y < out->y; y++) {
2190 for (x = 0; x < out->x; x++, rect += 4) {
2198 for (x = 0; x < out->x; x++, rect += 4) {
2208 else if (out->rect_float) {
2212 col0[0] = facf0 * cv->col[0];
2213 col0[1] = facf0 * cv->col[1];
2214 col0[2] = facf0 * cv->col[2];
2216 col1[0] = facf1 * cv->col[0];
2217 col1[1] = facf1 * cv->col[1];
2218 col1[2] = facf1 * cv->col[2];
2220 rect_float = out->rect_float;
2222 for (y = 0; y < out->y; y++) {
2223 for (x = 0; x < out->x; x++, rect_float += 4) {
2224 rect_float[0] = col0[0];
2225 rect_float[1] = col0[1];
2226 rect_float[2] = col0[2];
2227 rect_float[3] = 1.0;
2231 for (x = 0; x < out->x; x++, rect_float += 4) {
2232 rect_float[0] = col1[0];
2233 rect_float[1] = col1[1];
2234 rect_float[2] = col1[2];
2235 rect_float[3] = 1.0;
2243 /*********************** Mulitcam *************************/
2245 /* no effect inputs for multicam, we use give_ibuf_seq */
2246 static int num_inputs_multicam(void)
2251 static int early_out_multicam(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2253 return EARLY_NO_INPUT;
2256 static ImBuf *do_multicam(const SeqRenderData *context, Sequence *seq, float cfra, float UNUSED(facf0), float UNUSED(facf1),
2257 ImBuf *UNUSED(ibuf1), ImBuf *UNUSED(ibuf2), ImBuf *UNUSED(ibuf3))
2264 if (seq->multicam_source == 0 || seq->multicam_source >= seq->machine) {
2268 ed = context->scene->ed;
2272 seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq);
2277 i = BKE_sequencer_give_ibuf_seqbase(context, cfra, seq->multicam_source, seqbasep);
2282 if (BKE_sequencer_input_have_to_preprocess(context, seq, cfra)) {
2283 out = IMB_dupImBuf(i);
2293 /*********************** Adjustment *************************/
2295 /* no effect inputs for adjustment, we use give_ibuf_seq */
2296 static int num_inputs_adjustment(void)
2301 static int early_out_adjustment(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2303 return EARLY_NO_INPUT;
2306 static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, float cfra)
2312 ed = context->scene->ed;
2314 seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq);
2316 if (seq->machine > 1) {
2317 i = BKE_sequencer_give_ibuf_seqbase(context, cfra, seq->machine - 1, seqbasep);
2320 /* found nothing? so let's work the way up the metastrip stack, so
2321 * that it is possible to group a bunch of adjustment strips into
2322 * a metastrip and have that work on everything below the metastrip
2328 meta = BKE_sequence_metastrip(&ed->seqbase, NULL, seq);
2331 i = do_adjustment_impl(context, meta, cfra);
2338 static ImBuf *do_adjustment(const SeqRenderData *context, Sequence *seq, float cfra, float UNUSED(facf0), float UNUSED(facf1),
2339 ImBuf *UNUSED(ibuf1), ImBuf *UNUSED(ibuf2), ImBuf *UNUSED(ibuf3))
2345 ed = context->scene->ed;
2351 i = do_adjustment_impl(context, seq, cfra);
2353 if (BKE_sequencer_input_have_to_preprocess(context, seq, cfra)) {
2354 out = IMB_dupImBuf(i);
2364 /*********************** Speed *************************/
2366 static void init_speed_effect(Sequence *seq)
2368 SpeedControlVars *v;
2370 if (seq->effectdata)
2371 MEM_freeN(seq->effectdata);
2373 seq->effectdata = MEM_callocN(sizeof(SpeedControlVars), "speedcontrolvars");
2375 v = (SpeedControlVars *)seq->effectdata;
2376 v->globalSpeed = 1.0;
2378 v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */
2382 static void load_speed_effect(Sequence *seq)
2384 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
2390 static int num_inputs_speed(void)
2395 static void free_speed_effect(Sequence *seq)
2397 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
2399 MEM_freeN(v->frameMap);
2400 if (seq->effectdata)
2401 MEM_freeN(seq->effectdata);
2402 seq->effectdata = NULL;
2405 static void copy_speed_effect(Sequence *dst, Sequence *src)
2407 SpeedControlVars *v;
2408 dst->effectdata = MEM_dupallocN(src->effectdata);
2409 v = (SpeedControlVars *)dst->effectdata;
2414 static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2416 return EARLY_USE_INPUT_1;
2419 static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float *ymin, float *ymax)
2421 SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
2423 /* if not already done, load / initialize data */
2424 BKE_sequence_get_effect(seq);
2426 if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
2431 if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
2442 void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force)
2445 float fallback_fac = 1.0f;
2446 SpeedControlVars *v = (SpeedControlVars *) seq->effectdata;
2448 int flags = v->flags;
2450 /* if not already done, load / initialize data */
2451 BKE_sequence_get_effect(seq);
2453 if ((force == false) &&
2454 (seq->len == v->length) &&
2455 (v->frameMap != NULL))
2459 if ((seq->seq1 == NULL) || (seq->len < 1)) {
2460 /* make coverity happy and check for (CID 598) input strip ... */
2464 /* XXX - new in 2.5x. should we use the animation system this way?
2465 * The fcurve is needed because many frames need evaluating at once - campbell */
2466 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
2469 if (!v->frameMap || v->length != seq->len) {
2470 if (v->frameMap) MEM_freeN(v->frameMap);
2472 v->length = seq->len;
2474 v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap");
2479 if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
2480 if ((seq->seq1->enddisp != seq->seq1->start) &&
2481 (seq->seq1->len != 0))
2483 fallback_fac = 1.0f;
2484 flags = SEQ_SPEED_INTEGRATE;
2489 /* if there is no fcurve, use value as simple multiplier */
2491 fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/
2495 if (flags & SEQ_SPEED_INTEGRATE) {
2500 v->lastValidFrame = 0;
2502 for (cfra = 1; cfra < v->length; cfra++) {
2504 facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
2507 facf = fallback_fac;
2509 facf *= v->globalSpeed;
2513 if (cursor >= seq->seq1->len) {
2514 v->frameMap[cfra] = seq->seq1->len - 1;
2517 v->frameMap[cfra] = cursor;
2518 v->lastValidFrame = cfra;
2525 v->lastValidFrame = 0;
2526 for (cfra = 0; cfra < v->length; cfra++) {
2529 facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
2532 facf = fallback_fac;
2535 if (flags & SEQ_SPEED_COMPRESS_IPO_Y) {
2536 facf *= seq->seq1->len;
2538 facf *= v->globalSpeed;
2540 if (facf >= seq->seq1->len) {
2541 facf = seq->seq1->len - 1;
2544 v->lastValidFrame = cfra;
2546 v->frameMap[cfra] = facf;
2551 static ImBuf *do_speed_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra),
2552 float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
2554 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2556 if (out->rect_float) {
2557 do_cross_effect_float(facf0, facf1, context->rectx, context->recty,
2558 ibuf1->rect_float, ibuf2->rect_float, out->rect_float);
2561 do_cross_effect_byte(facf0, facf1, context->rectx, context->recty,
2562 (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
2567 /*********************** overdrop *************************/
2569 static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
2570 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
2572 int x = context->rectx;
2573 int y = total_lines;
2575 if (out->rect_float) {
2576 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
2578 slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
2580 do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
2581 do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
2584 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
2586 slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
2588 do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
2589 do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
2593 /*********************** Gaussian Blur *************************/
2595 /* NOTE: This gaussian blur implementation accumulates values in the square
2596 * kernel rather that doing X direction and then Y direction because of the
2597 * lack of using multiple-staged filters.
2599 * Once we can we'll implement a way to apply filter as multiple stages we
2600 * can optimize hell of a lot in here.
2603 static void init_gaussian_blur_effect(Sequence *seq)
2605 if (seq->effectdata)
2606 MEM_freeN(seq->effectdata);
2608 seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
2611 static int num_inputs_gaussian_blur(void)
2616 static void free_gaussian_blur_effect(Sequence *seq)
2618 if (seq->effectdata)
2619 MEM_freeN(seq->effectdata);
2621 seq->effectdata = NULL;
2624 static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src)
2626 dst->effectdata = MEM_dupallocN(src->effectdata);
2629 static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
2631 GaussianBlurVars *data = seq->effectdata;
2632 if (data->size_x == 0.0f && data->size_y == 0) {
2633 return EARLY_USE_INPUT_1;
2635 return EARLY_DO_EFFECT;
2638 /* TODO(sergey): De-duplicate with compositor. */
2639 static float *make_gaussian_blur_kernel(float rad, int size)
2641 float *gausstab, sum, val;
2647 gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
2650 fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
2651 for (i = -size; i <= size; i++) {
2652 val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
2654 gausstab[i + size] = val;
2658 for (i = 0; i < n; i++)
2664 static void do_gaussian_blur_effect_byte(Sequence *seq,
2667 int frame_width, int frame_height,
2668 unsigned char *rect,
2671 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
2672 GaussianBlurVars *data = seq->effectdata;
2673 const int size_x = (int) (data->size_x + 0.5f);
2674 const int size_y = (int) (data->size_y + 0.5f);
2677 /* Make gaussian weight tabke. */
2678 float *gausstab_x, *gausstab_y;
2679 gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
2680 if (data->size_x == data->size_y) {
2681 gausstab_y = gausstab_x;
2684 gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
2687 for (i = 0; i < y; ++i) {
2688 for (j = 0; j < x; ++j) {
2689 int out_index = INDEX(j, i);
2690 int current_x, current_y;
2691 float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2692 float accum_weight = 0.0f;
2693 for (current_y = i - size_y;
2694 current_y <= i + size_y;
2697 if (current_y < -start_line ||
2698 current_y + start_line >= frame_height)
2700 /* Out of bounds. */
2704 for (current_x = j - size_x;
2705 current_x <= j + size_x;
2709 int index = INDEX(current_x, current_y + start_line);
2710 if (current_x < 0 || current_x >= frame_width) {
2711 /* Out of bounds. */
2714 BLI_assert(index >= 0);
2715 BLI_assert(index < frame_width * frame_height * 4);
2717 if (size_x != 0 && size_y != 0) {
2718 weight = gausstab_x[current_x - j + size_x] *
2719 gausstab_y[current_y - i + size_y];
2721 else if (size_x == 0) {
2722 weight = gausstab_y[current_y - i + size_y];
2725 weight = gausstab_x[current_x - j + size_x];
2727 accum[0] += rect[index] * weight;
2728 accum[1] += rect[index + 1] * weight;
2729 accum[2] += rect[index + 2] * weight;
2730 accum[3] += rect[index + 3] * weight;
2731 accum_weight += weight;
2734 out[out_index + 0] = accum[0] / accum_weight;
2735 out[out_index + 1] = accum[1] / accum_weight;
2736 out[out_index + 2] = accum[2] / accum_weight;
2737 out[out_index + 3] = accum[3] / accum_weight;
2741 MEM_freeN(gausstab_x);
2742 if (gausstab_x != gausstab_y) {
2743 MEM_freeN(gausstab_y);
2748 static void do_gaussian_blur_effect_float(Sequence *seq,
2751 int frame_width, int frame_height,
2755 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
2756 GaussianBlurVars *data = seq->effectdata;
2757 const int size_x = (int) (data->size_x + 0.5f);
2758 const int size_y = (int) (data->size_y + 0.5f);
2761 /* Make gaussian weight tabke. */
2762 float *gausstab_x, *gausstab_y;
2763 gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
2764 if (data->size_x == data->size_y) {
2765 gausstab_y = gausstab_x;
2768 gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
2771 for (i = 0; i < y; ++i) {
2772 for (j = 0; j < x; ++j) {
2773 int out_index = INDEX(j, i);
2774 int current_x, current_y;
2775 float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2776 float accum_weight = 0.0f;
2777 for (current_y = i - size_y;
2778 current_y <= i + size_y;
2782 if (current_y < -start_line ||
2783 current_y + start_line >= frame_height)
2785 /* Out of bounds. */
2789 for (current_x = j - size_x;
2790 current_x <= j + size_x;
2793 int index = INDEX(current_x, current_y + start_line);
2794 if (current_x < 0 || current_x >= frame_width) {
2795 /* Out of bounds. */
2799 if (size_x != 0 && size_y != 0) {
2800 weight = gausstab_x[current_x - j + size_x] *
2801 gausstab_y[current_y - i + size_y];
2803 else if (size_x == 0) {
2804 weight = gausstab_y[current_y - i + size_y];
2807 weight = gausstab_x[current_x - j + size_x];
2809 madd_v4_v4fl(accum, &rect[index], weight);
2810 accum_weight += weight;
2813 mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
2817 MEM_freeN(gausstab_x);
2818 if (gausstab_x != gausstab_y) {
2819 MEM_freeN(gausstab_y);
2824 static void do_gaussian_blur_effect(const SeqRenderData *context,
2827 float UNUSED(facf0),
2828 float UNUSED(facf1),
2831 ImBuf *UNUSED(ibuf3),
2836 if (out->rect_float) {
2837 float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
2839 slice_get_float_buffers(context,
2849 do_gaussian_blur_effect_float(seq,
2859 unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
2861 slice_get_byte_buffers(context,
2871 do_gaussian_blur_effect_byte(seq,
2877 (unsigned char *) ibuf1->rect,
2882 /*********************** text *************************/
2883 static void init_text_effect(Sequence *seq)
2887 if (seq->effectdata)
2888 MEM_freeN(seq->effectdata);
2890 data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
2891 data->text_size = U.pixelsize * 30;
2892 BLI_strncpy(data->text, "Text", sizeof(data->text));
2895 static int num_inputs_text(void)
2900 static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
2902 TextVars *data = seq->effectdata;
2903 if (data->text[0] == 0 || data->text_size < 1) {
2904 return EARLY_USE_INPUT_1;
2906 return EARLY_NO_INPUT;
2909 static ImBuf *do_text_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float UNUSED(facf0), float UNUSED(facf1),
2910 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
2912 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2913 TextVars *data = seq->effectdata;
2915 int height = out->y;
2916 struct ColorManagedDisplay *display;
2917 const char *display_device;
2918 const int mono = blf_mono_font_render; // XXX
2921 display_device = context->scene->display_settings.display_device;
2922 display = IMB_colormanagement_display_get_named(display_device);
2924 /* set before return */
2925 BLF_size(mono, (context->scene->r.size / 100.0f) * data->text_size, 72);
2927 BLF_buffer(mono, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display);
2929 y_ofs = -BLF_descender(mono);
2931 w = BLF_width(mono, data->text, sizeof(data->text));
2933 if (data->flags & TEXT_SEQ_AUTO_CENTER)
2934 x = width / 2 - w / 2;
2936 x = (context->scene->r.size / 100.0f) * data->xpos;
2938 y = y_ofs + (context->scene->r.size / 100.0f) * data->ypos;
2940 /* BLF_SHADOW won't work with buffers, instead use cheap shadow trick */
2941 if (data->flags & TEXT_SEQ_SHADOW) {
2943 fontx = BLF_width_max(mono);
2944 fonty = BLF_height_max(mono);
2945 BLF_position(mono, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0);
2946 BLF_buffer_col(mono, 0.0f, 0.0f, 0.0f, 1.0);
2947 BLF_draw_buffer(mono, data->text);
2949 BLF_position(mono, x, y, 0.0);
2950 BLF_buffer_col(mono, 1.0f, 1.0f, 1.0f, 1.0);
2951 BLF_draw_buffer(mono, data->text);
2953 BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
2958 /*********************** sequence effect factory *************************/
2960 static void init_noop(Sequence *UNUSED(seq))
2965 static void load_noop(Sequence *UNUSED(seq))
2970 static void free_noop(Sequence *UNUSED(seq))
2975 static int num_inputs_default(void)
2980 static void copy_effect_default(Sequence *dst, Sequence *src)
2982 dst->effectdata = MEM_dupallocN(src->effectdata);
2985 static void free_effect_default(Sequence *seq)
2987 if (seq->effectdata)
2988 MEM_freeN(seq->effectdata);
2990 seq->effectdata = NULL;
2993 static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2995 return EARLY_DO_EFFECT;
2998 static int early_out_fade(Sequence *UNUSED(seq), float facf0, float facf1)
3000 if (facf0 == 0.0f && facf1 == 0.0f) {
3001 return EARLY_USE_INPUT_1;
3003 else if (facf0 == 1.0f && facf1 == 1.0f) {
3004 return EARLY_USE_INPUT_2;
3006 return EARLY_DO_EFFECT;
3009 static int early_out_mul_input2(Sequence *UNUSED(seq), float facf0, float facf1)
3011 if (facf0 == 0.0f && facf1 == 0.0f) {
3012 return EARLY_USE_INPUT_1;
3014 return EARLY_DO_EFFECT;
3017 static void store_icu_yrange_noop(Sequence *UNUSED(seq), short UNUSED(adrcode), float *UNUSED(ymin), float *UNUSED(ymax))
3019 /* defaults are fine */
3022 static void get_default_fac_noop(Sequence *UNUSED(seq), float UNUSED(cfra), float *facf0, float *facf1)
3024 *facf0 = *facf1 = 1.0;
3027 static void get_default_fac_fade(Sequence *seq, float cfra, float *facf0, float *facf1)
3029 *facf0 = (float)(cfra - seq->startdisp);
3030 *facf1 = (float)(*facf0 + 0.5f);
3035 static struct ImBuf *init_execution(const SeqRenderData *context, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
3037 ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
3042 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
3044 struct SeqEffectHandle rval;
3045 int sequence_type = seq_type;
3047 rval.multithreaded = false;
3048 rval.supports_mask = false;
3049 rval.init = init_noop;
3050 rval.num_inputs = num_inputs_default;
3051 rval.load = load_noop;
3052 rval.free = free_noop;
3053 rval.early_out = early_out_noop;
3054 rval.get_default_fac = get_default_fac_noop;
3055 rval.store_icu_yrange = store_icu_yrange_noop;
3056 rval.execute = NULL;
3057 rval.init_execution = init_execution;
3058 rval.execute_slice = NULL;
3061 switch (sequence_type) {
3062 case SEQ_TYPE_CROSS:
3063 rval.multithreaded = true;
3064 rval.execute_slice = do_cross_effect;
3065 rval.early_out = early_out_fade;
3066 rval.get_default_fac = get_default_fac_fade;
3068 case SEQ_TYPE_GAMCROSS:
3069 rval.multithreaded = true;
3070 rval.init = init_gammacross;
3071 rval.load = load_gammacross;
3072 rval.free = free_gammacross;
3073 rval.early_out = early_out_fade;
3074 rval.get_default_fac = get_default_fac_fade;
3075 rval.init_execution = gammacross_init_execution;
3076 rval.execute_slice = do_gammacross_effect;
3079 rval.multithreaded = true;
3080 rval.execute_slice = do_add_effect;
3081 rval.early_out = early_out_mul_input2;
3084 rval.multithreaded = true;
3085 rval.execute_slice = do_sub_effect;
3086 rval.early_out = early_out_mul_input2;
3089 rval.multithreaded = true;
3090 rval.execute_slice = do_mul_effect;
3091 rval.early_out = early_out_mul_input2;