Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaikon Araujo <Nokiam>2017-11-28 01:33:08 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2017-11-29 20:11:36 +0300
commit4b4702ab8af6f74edc20ba6735d74f61aa15ce47 (patch)
tree521f4ab1e83633b26dc9e467c25fe2cc4fa0f02e /source/blender/blenkernel/intern/seqeffects.c
parent4f7280da404c5054da4061335fee1dac24d9c812 (diff)
Sequencer: add many more color blend modes, and a new color mix strip.
Differential Revision: https://developer.blender.org/D2872
Diffstat (limited to 'source/blender/blenkernel/intern/seqeffects.c')
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index a2c45057bf7..df21512a262 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -53,6 +53,8 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
+#include "BLI_math_color_blend.h"
+
#include "RNA_access.h"
#include "RE_pipeline.h"
@@ -1266,6 +1268,274 @@ static void do_mul_effect(const SeqRenderData *context, Sequence *UNUSED(seq), f
}
}
+/*********************** Blend Mode ***************************************/
+typedef void (*IMB_blend_func_byte)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2);
+typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
+
+BLI_INLINE void 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)
+{
+ int xo;
+ unsigned char *rt1, *rt2, *rt;
+ unsigned int achannel;
+ xo = x;
+ rt1 = rect1;
+ rt2 = rect2;
+ rt = out;
+ while (y--) {
+ for (x = xo; x > 0; x--) {
+ achannel = rt2[3];
+ rt2[3] = (unsigned int) achannel * facf0;
+ blend_function(rt, rt1, rt2);
+ rt2[3] = achannel;
+ rt[3] = rt2[3];
+ rt1 += 4;
+ rt2 += 4;
+ rt += 4;
+ }
+ if (y == 0) {
+ break;
+ }
+ y--;
+ for (x = xo; x > 0; x--) {
+ achannel = rt2[3];
+ rt2[3] = (unsigned int) achannel * facf1;
+ blend_function(rt, rt1, rt2);
+ rt2[3] = achannel;
+ rt[3] = rt2[3];
+ rt1 += 4;
+ rt2 += 4;
+ rt += 4;
+ }
+ }
+}
+
+BLI_INLINE void apply_blend_function_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out, IMB_blend_func_float blend_function)
+{
+ int xo;
+ float *rt1, *rt2, *rt;
+ float achannel;
+ xo = x;
+ rt1 = rect1;
+ rt2 = rect2;
+ rt = out;
+ while (y--) {
+ for (x = xo; x > 0; x--) {
+ achannel = rt2[3];
+ rt2[3] = achannel * facf0;
+ blend_function(rt, rt1, rt2);
+ rt2[3] = achannel;
+ rt[3] = rt2[3];
+ rt1 += 4;
+ rt2 += 4;
+ rt += 4;
+ }
+ if (y == 0) {
+ break;
+ }
+ y--;
+ for (x = xo; x > 0; x--) {
+ achannel = rt2[3];
+ rt2[3] = achannel * facf1;
+ blend_function(rt, rt1, rt2);
+ rt2[3] = achannel;
+ rt[3] = rt2[3];
+ rt1 += 4;
+ rt2 += 4;
+ rt += 4;
+ }
+ }
+}
+
+static void do_blend_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, int btype, float *out)
+{
+ switch (btype) {
+ case SEQ_TYPE_ADD:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_float);
+ break;
+ case SEQ_TYPE_SUB:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_float);
+ break;
+ case SEQ_TYPE_MUL:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_float);
+ break;
+ case SEQ_TYPE_DARKEN:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_float);
+ break;
+ case SEQ_TYPE_BURN:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_float);
+ break;
+ case SEQ_TYPE_LINEAR_BURN:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_float);
+ break;
+ case SEQ_TYPE_SCREEN:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_float);
+ break;
+ case SEQ_TYPE_LIGHTEN:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_float);
+ break;
+ case SEQ_TYPE_DODGE:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_float);
+ break;
+ case SEQ_TYPE_OVERLAY:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_float);
+ break;
+ case SEQ_TYPE_SOFT_LIGHT:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_float);
+ break;
+ case SEQ_TYPE_HARD_LIGHT:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_float);
+ break;
+ case SEQ_TYPE_PIN_LIGHT:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_float);
+ break;
+ case SEQ_TYPE_LIN_LIGHT:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_float);
+ break;
+ case SEQ_TYPE_VIVID_LIGHT:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_float);
+ break;
+ case SEQ_TYPE_BLEND_COLOR:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_float);
+ break;
+ case SEQ_TYPE_HUE:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_float);
+ break;
+ case SEQ_TYPE_SATURATION:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_float);
+ break;
+ case SEQ_TYPE_VALUE:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_float);
+ break;
+ case SEQ_TYPE_DIFFERENCE:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_float);
+ break;
+ case SEQ_TYPE_EXCLUSION:
+ apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_float);
+ break;
+ default:
+ break;
+ }
+}
+
+static void do_blend_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, int btype, unsigned char *out)
+{
+ switch (btype) {
+ case SEQ_TYPE_ADD:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_byte);
+ break;
+ case SEQ_TYPE_SUB:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_byte);
+ break;
+ case SEQ_TYPE_MUL:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_byte);
+ break;
+ case SEQ_TYPE_DARKEN:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_byte);
+ break;
+ case SEQ_TYPE_BURN:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_byte);
+ break;
+ case SEQ_TYPE_LINEAR_BURN:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_byte);
+ break;
+ case SEQ_TYPE_SCREEN:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_byte);
+ break;
+ case SEQ_TYPE_LIGHTEN:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_byte);
+ break;
+ case SEQ_TYPE_DODGE:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_byte);
+ break;
+ case SEQ_TYPE_OVERLAY:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_byte);
+ break;
+ case SEQ_TYPE_SOFT_LIGHT:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_byte);
+ break;
+ case SEQ_TYPE_HARD_LIGHT:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_byte);
+ break;
+ case SEQ_TYPE_PIN_LIGHT:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_byte);
+ break;
+ case SEQ_TYPE_LIN_LIGHT:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_byte);
+ break;
+ case SEQ_TYPE_VIVID_LIGHT:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_byte);
+ break;
+ case SEQ_TYPE_BLEND_COLOR:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_byte);
+ break;
+ case SEQ_TYPE_HUE:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_byte);
+ break;
+ case SEQ_TYPE_SATURATION:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_byte);
+ break;
+ case SEQ_TYPE_VALUE:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_byte);
+ break;
+ case SEQ_TYPE_DIFFERENCE:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_byte);
+ break;
+ case SEQ_TYPE_EXCLUSION:
+ apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_byte);
+ break;
+ default:
+ break;
+ }
+}
+
+static void 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)
+{
+ if (out->rect_float) {
+ float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+ slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+ do_blend_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
+ }
+ else {
+ unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+ slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+ do_blend_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
+ }
+}
+/*********************** Color Mix Effect *************************/
+static void init_colormix_effect(Sequence *seq)
+{
+ ColorMixVars *data;
+
+ if (seq->effectdata){
+ MEM_freeN(seq->effectdata);
+ }
+ seq->effectdata = MEM_callocN(sizeof(ColorMixVars), "colormixvars");
+ data = (ColorMixVars *) seq->effectdata;
+ data->blend_effect = SEQ_TYPE_OVERLAY;
+ data->factor = 1.0f;
+}
+
+static void 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)
+{
+ float facf;
+
+ ColorMixVars *data = seq->effectdata;
+ facf = data->factor;
+
+ if (out->rect_float) {
+ float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+ slice_get_float_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+ do_blend_effect_float(facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
+ }
+ else {
+ unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+ slice_get_byte_buffers(context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+ do_blend_effect_byte(facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
+ }
+}
+
/*********************** Wipe *************************/
typedef struct WipeZone {
@@ -3336,6 +3606,36 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.execute_slice = do_mul_effect;
rval.early_out = early_out_mul_input2;
break;
+ case SEQ_TYPE_SCREEN:
+ case SEQ_TYPE_OVERLAY:
+ case SEQ_TYPE_BURN:
+ case SEQ_TYPE_LINEAR_BURN:
+ case SEQ_TYPE_DARKEN:
+ case SEQ_TYPE_LIGHTEN:
+ case SEQ_TYPE_DODGE:
+ case SEQ_TYPE_SOFT_LIGHT:
+ case SEQ_TYPE_HARD_LIGHT:
+ case SEQ_TYPE_PIN_LIGHT:
+ case SEQ_TYPE_LIN_LIGHT:
+ case SEQ_TYPE_VIVID_LIGHT:
+ case SEQ_TYPE_BLEND_COLOR:
+ case SEQ_TYPE_HUE:
+ case SEQ_TYPE_SATURATION:
+ case SEQ_TYPE_VALUE:
+ case SEQ_TYPE_DIFFERENCE:
+ case SEQ_TYPE_EXCLUSION:
+ rval.multithreaded = true;
+ rval.execute_slice = do_blend_mode_effect;
+ rval.early_out = early_out_mul_input2;
+ break;
+ case SEQ_TYPE_COLORMIX:
+ rval.multithreaded = true;
+ rval.init = init_colormix_effect;
+ rval.free = free_effect_default;
+ rval.copy = copy_effect_default;
+ rval.execute_slice = do_colormix_effect;
+ rval.early_out = early_out_mul_input2;
+ break;
case SEQ_TYPE_ALPHAOVER:
rval.multithreaded = true;
rval.init = init_alpha_over_or_under;