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:
Diffstat (limited to 'source/blender/sequencer/intern/modifier.c')
-rw-r--r--source/blender/sequencer/intern/modifier.c373
1 files changed, 364 insertions, 9 deletions
diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c
index 6ddbbc6a8e9..4a922e9ce9f 100644
--- a/source/blender/sequencer/intern/modifier.c
+++ b/source/blender/sequencer/intern/modifier.c
@@ -46,6 +46,7 @@
#include "SEQ_sequencer.h"
+#include "render.h"
#include "sequencer.h"
static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES];
@@ -82,19 +83,58 @@ typedef struct ModifierThread {
modifier_apply_threaded_cb apply_callback;
} ModifierThread;
+/**
+ * \a cfra is offset by \a fra_offset only in case we are using a real mask.
+ */
+static ImBuf *modifier_render_mask_input(const SeqRenderData *context,
+ int mask_input_type,
+ Sequence *mask_sequence,
+ Mask *mask_id,
+ int cfra,
+ int fra_offset,
+ bool make_float)
+{
+ ImBuf *mask_input = NULL;
+
+ if (mask_input_type == SEQUENCE_MASK_INPUT_STRIP) {
+ if (mask_sequence) {
+ SeqRenderState state;
+ seq_render_state_init(&state);
+
+ mask_input = seq_render_strip(context, &state, mask_sequence, cfra);
+
+ if (make_float) {
+ if (!mask_input->rect_float) {
+ IMB_float_from_rect(mask_input);
+ }
+ }
+ else {
+ if (!mask_input->rect) {
+ IMB_rect_from_float(mask_input);
+ }
+ }
+ }
+ }
+ else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) {
+ mask_input = seq_render_mask(context, mask_id, cfra - fra_offset, make_float);
+ }
+
+ return mask_input;
+}
+
static ImBuf *modifier_mask_get(SequenceModifierData *smd,
const SeqRenderData *context,
int cfra,
int fra_offset,
bool make_float)
{
- return BKE_sequencer_render_mask_input(context,
- smd->mask_input_type,
- smd->mask_sequence,
- smd->mask_id,
- cfra,
- fra_offset,
- make_float);
+ return modifier_render_mask_input(context,
+ smd->mask_input_type,
+ smd->mask_sequence,
+ smd->mask_id,
+ cfra,
+ fra_offset,
+ make_float);
}
static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -174,6 +214,291 @@ static void modifier_apply_threaded(ImBuf *ibuf,
/** \name Color Balance Modifier
* \{ */
+static StripColorBalance calc_cb(StripColorBalance *cb_)
+{
+ StripColorBalance cb = *cb_;
+ int c;
+
+ for (c = 0; c < 3; c++) {
+ cb.lift[c] = 2.0f - cb.lift[c];
+ }
+
+ if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
+ for (c = 0; c < 3; c++) {
+ /* tweak to give more subtle results
+ * values above 1.0 are scaled */
+ if (cb.lift[c] > 1.0f) {
+ cb.lift[c] = pow(cb.lift[c] - 1.0f, 2.0) + 1.0;
+ }
+
+ cb.lift[c] = 2.0f - cb.lift[c];
+ }
+ }
+
+ if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
+ for (c = 0; c < 3; c++) {
+ if (cb.gain[c] != 0.0f) {
+ cb.gain[c] = 1.0f / cb.gain[c];
+ }
+ else {
+ cb.gain[c] = 1000000; /* should be enough :) */
+ }
+ }
+ }
+
+ if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) {
+ for (c = 0; c < 3; c++) {
+ if (cb.gamma[c] != 0.0f) {
+ cb.gamma[c] = 1.0f / cb.gamma[c];
+ }
+ else {
+ cb.gamma[c] = 1000000; /* should be enough :) */
+ }
+ }
+ }
+
+ return cb;
+}
+
+/* note: lift is actually 2-lift */
+MINLINE float color_balance_fl(
+ float in, const float lift, const float gain, const float gamma, const float mul)
+{
+ float x = (((in - 1.0f) * lift) + 1.0f) * gain;
+
+ /* prevent NaN */
+ if (x < 0.f) {
+ x = 0.f;
+ }
+
+ x = powf(x, gamma) * mul;
+ CLAMP(x, FLT_MIN, FLT_MAX);
+ return x;
+}
+
+static void make_cb_table_float(float lift, float gain, float gamma, float *table, float mul)
+{
+ int y;
+
+ for (y = 0; y < 256; y++) {
+ float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
+
+ table[y] = v;
+ }
+}
+
+static void color_balance_byte_byte(StripColorBalance *cb_,
+ unsigned char *rect,
+ unsigned char *mask_rect,
+ int width,
+ int height,
+ float mul)
+{
+ // unsigned char cb_tab[3][256];
+ unsigned char *cp = rect;
+ unsigned char *e = cp + width * 4 * height;
+ unsigned char *m = mask_rect;
+
+ StripColorBalance cb = calc_cb(cb_);
+
+ while (cp < e) {
+ float p[4];
+ int c;
+
+ straight_uchar_to_premul_float(p, cp);
+
+ for (c = 0; c < 3; c++) {
+ float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+
+ if (m) {
+ float m_normal = (float)m[c] / 255.0f;
+
+ p[c] = p[c] * (1.0f - m_normal) + t * m_normal;
+ }
+ else {
+ p[c] = t;
+ }
+ }
+
+ premul_float_to_straight_uchar(cp, p);
+
+ cp += 4;
+ if (m) {
+ m += 4;
+ }
+ }
+}
+
+static void color_balance_byte_float(StripColorBalance *cb_,
+ unsigned char *rect,
+ float *rect_float,
+ unsigned char *mask_rect,
+ int width,
+ int height,
+ float mul)
+{
+ float cb_tab[4][256];
+ int c, i;
+ unsigned char *p = rect;
+ unsigned char *e = p + width * 4 * height;
+ unsigned char *m = mask_rect;
+ float *o;
+ StripColorBalance cb;
+
+ o = rect_float;
+
+ cb = calc_cb(cb_);
+
+ for (c = 0; c < 3; c++) {
+ make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
+ }
+
+ for (i = 0; i < 256; i++) {
+ cb_tab[3][i] = ((float)i) * (1.0f / 255.0f);
+ }
+
+ while (p < e) {
+ if (m) {
+ const float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f};
+
+ p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]];
+ p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]];
+ p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]];
+
+ m += 4;
+ }
+ else {
+ o[0] = cb_tab[0][p[0]];
+ o[1] = cb_tab[1][p[1]];
+ o[2] = cb_tab[2][p[2]];
+ }
+
+ o[3] = cb_tab[3][p[3]];
+
+ p += 4;
+ o += 4;
+ }
+}
+
+static void color_balance_float_float(StripColorBalance *cb_,
+ float *rect_float,
+ const float *mask_rect_float,
+ int width,
+ int height,
+ float mul)
+{
+ float *p = rect_float;
+ const float *e = rect_float + width * 4 * height;
+ const float *m = mask_rect_float;
+ StripColorBalance cb = calc_cb(cb_);
+
+ while (p < e) {
+ int c;
+ for (c = 0; c < 3; c++) {
+ float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+
+ if (m) {
+ p[c] = p[c] * (1.0f - m[c]) + t * m[c];
+ }
+ else {
+ p[c] = t;
+ }
+ }
+
+ p += 4;
+ if (m) {
+ m += 4;
+ }
+ }
+}
+
+typedef struct ColorBalanceInitData {
+ StripColorBalance *cb;
+ ImBuf *ibuf;
+ float mul;
+ ImBuf *mask;
+ bool make_float;
+} ColorBalanceInitData;
+
+typedef struct ColorBalanceThread {
+ StripColorBalance *cb;
+ float mul;
+
+ int width, height;
+
+ unsigned char *rect, *mask_rect;
+ float *rect_float, *mask_rect_float;
+
+ bool make_float;
+} ColorBalanceThread;
+
+static void color_balance_init_handle(void *handle_v,
+ int start_line,
+ int tot_line,
+ void *init_data_v)
+{
+ ColorBalanceThread *handle = (ColorBalanceThread *)handle_v;
+ ColorBalanceInitData *init_data = (ColorBalanceInitData *)init_data_v;
+ ImBuf *ibuf = init_data->ibuf;
+ ImBuf *mask = init_data->mask;
+
+ int offset = 4 * start_line * ibuf->x;
+
+ memset(handle, 0, sizeof(ColorBalanceThread));
+
+ handle->cb = init_data->cb;
+ handle->mul = init_data->mul;
+ handle->width = ibuf->x;
+ handle->height = tot_line;
+ handle->make_float = init_data->make_float;
+
+ if (ibuf->rect) {
+ handle->rect = (unsigned char *)ibuf->rect + offset;
+ }
+
+ if (ibuf->rect_float) {
+ handle->rect_float = ibuf->rect_float + offset;
+ }
+
+ if (mask) {
+ if (mask->rect) {
+ handle->mask_rect = (unsigned char *)mask->rect + offset;
+ }
+
+ if (mask->rect_float) {
+ handle->mask_rect_float = mask->rect_float + offset;
+ }
+ }
+ else {
+ handle->mask_rect = NULL;
+ handle->mask_rect_float = NULL;
+ }
+}
+
+static void *color_balance_do_thread(void *thread_data_v)
+{
+ ColorBalanceThread *thread_data = (ColorBalanceThread *)thread_data_v;
+ StripColorBalance *cb = thread_data->cb;
+ int width = thread_data->width, height = thread_data->height;
+ unsigned char *rect = thread_data->rect;
+ unsigned char *mask_rect = thread_data->mask_rect;
+ float *rect_float = thread_data->rect_float;
+ float *mask_rect_float = thread_data->mask_rect_float;
+ float mul = thread_data->mul;
+
+ if (rect_float) {
+ color_balance_float_float(cb, rect_float, mask_rect_float, width, height, mul);
+ }
+ else if (thread_data->make_float) {
+ color_balance_byte_float(cb, rect, rect_float, mask_rect, width, height, mul);
+ }
+ else {
+ color_balance_byte_byte(cb, rect, mask_rect, width, height, mul);
+ }
+
+ return NULL;
+}
+
static void colorBalance_init_data(SequenceModifierData *smd)
{
ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *)smd;
@@ -188,11 +513,41 @@ static void colorBalance_init_data(SequenceModifierData *smd)
}
}
+static void modifier_color_balance_apply(
+ StripColorBalance *cb, ImBuf *ibuf, float mul, bool make_float, ImBuf *mask_input)
+{
+ ColorBalanceInitData init_data;
+
+ if (!ibuf->rect_float && make_float) {
+ imb_addrectfloatImBuf(ibuf);
+ }
+
+ init_data.cb = cb;
+ init_data.ibuf = ibuf;
+ init_data.mul = mul;
+ init_data.make_float = make_float;
+ init_data.mask = mask_input;
+
+ IMB_processor_apply_threaded(ibuf->y,
+ sizeof(ColorBalanceThread),
+ &init_data,
+ color_balance_init_handle,
+ color_balance_do_thread);
+
+ /* color balance either happens on float buffer or byte buffer, but never on both,
+ * free byte buffer if there's float buffer since float buffer would be used for
+ * color balance in favor of byte buffer
+ */
+ if (ibuf->rect_float && ibuf->rect) {
+ imb_freerectImBuf(ibuf);
+ }
+}
+
static void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
{
ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *)smd;
- BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf, cbmd->color_multiply, false, mask);
+ modifier_color_balance_apply(&cbmd->color_balance, ibuf, cbmd->color_multiply, false, mask);
}
static SequenceModifierTypeInfo seqModifier_ColorBalance = {
@@ -1100,7 +1455,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context,
}
if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
- BKE_sequencer_imbuf_to_sequencer_space(context->scene, processed_ibuf, false);
+ seq_imbuf_to_sequencer_space(context->scene, processed_ibuf, false);
}
return processed_ibuf;