Commit: 3b2f6dbf9847476f9491218cbed948c1c0aa6c7d
Author: Sergey Sharybin
Date:   Sat Jul 19 22:16:10 2014 +0600
https://developer.blender.org/rB3b2f6dbf9847476f9491218cbed948c1c0aa6c7d

Sequencer: Add gaussian blur effect

Currently this gaussian blur implementation accumulates values in the
square kernel rather that doing X direction and then Y direction because
of the lack of using multiple-staged filters.

Once we can we'll implement a way to apply filter as multiple stages we
can optimize hell of a lot in here.

Another thing we can do is to use SSE2 instructions here.

===================================================================

M       release/scripts/startup/bl_ui/space_sequencer.py
M       source/blender/blenkernel/intern/seqeffects.c
M       source/blender/blenkernel/intern/sequencer.c
M       source/blender/blenloader/intern/writefile.c
M       source/blender/editors/space_sequencer/sequencer_draw.c
M       source/blender/editors/space_sequencer/sequencer_edit.c
M       source/blender/makesdna/DNA_sequence_types.h
M       source/blender/makesrna/intern/rna_sequencer.c
M       source/blender/makesrna/intern/rna_sequencer_api.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_sequencer.py 
b/release/scripts/startup/bl_ui/space_sequencer.py
index b77078b..978c326 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -284,6 +284,7 @@ class SEQUENCER_MT_add_effect(Menu):
         layout.operator("sequencer.effect_strip_add", text="Alpha Under").type 
= 'ALPHA_UNDER'
         layout.operator("sequencer.effect_strip_add", text="Cross").type = 
'CROSS'
         layout.operator("sequencer.effect_strip_add", text="Gamma Cross").type 
= 'GAMMA_CROSS'
+        layout.operator("sequencer.effect_strip_add", text="Gaussian 
Blur").type = 'GAUSSIAN_BLUR'
         layout.operator("sequencer.effect_strip_add", text="Multiply").type = 
'MULTIPLY'
         layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 
'OVER_DROP'
         layout.operator("sequencer.effect_strip_add", text="Wipe").type = 
'WIPE'
@@ -490,7 +491,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
         return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
                               'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
-                              'MULTICAM'}
+                              'MULTICAM', 'GAUSSIAN_BLUR'}
 
     def draw(self, context):
         layout = self.layout
@@ -588,6 +589,9 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
             col.prop(strip, "use_default_fade", "Default fade")
             if not strip.use_default_fade:
                 col.prop(strip, "effect_fader", text="Effect fader")
+        elif strip.type == 'GAUSSIAN_BLUR':
+            col.prop(strip, "size_x")
+            col.prop(strip, "size_y")
 
 
 class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
diff --git a/source/blender/blenkernel/intern/seqeffects.c 
b/source/blender/blenkernel/intern/seqeffects.c
index 2b14b92..4c02b1b 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,11 @@
 
 #include "RNA_access.h"
 
+/* TODO(sergey): Could be considered a bad level call, but
+ * need this for gaussian table.
+ */
+#include "RE_pipeline.h"
+
 static void 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)
@@ -2579,6 +2584,275 @@ static void do_overdrop_effect(const SeqRenderData 
*context, Sequence *UNUSED(se
        }
 }
 
+/*********************** Gaussian Blur *************************/
+
+/* NOTE: This gaussian blur implementation accumulates values in the square
+ * kernel rather that doing X direction and then Y direction because of the
+ * lack of using multiple-staged filters.
+ *
+ * Once we can we'll implement a way to apply filter as multiple stages we
+ * can optimize hell of a lot in here.
+ */
+
+static void init_gaussian_blur_effect(Sequence *seq)
+{
+       if (seq->effectdata)
+               MEM_freeN(seq->effectdata);
+
+       seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
+}
+
+static int num_inputs_gaussian_blur(void)
+{
+       return 1;
+}
+
+static void free_gaussian_blur_effect(Sequence *seq)
+{
+       if (seq->effectdata)
+               MEM_freeN(seq->effectdata);
+
+       seq->effectdata = NULL;
+}
+
+static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src)
+{
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_gaussian_blur(Sequence *UNUSED(seq), float UNUSED(facf0), 
float UNUSED(facf1))
+{
+       return EARLY_DO_EFFECT;
+}
+
+/* TODO(sergey): De-duplicate with compositor. */
+static float *make_gaussian_blur_kernel(float rad, int size)
+{
+       float *gausstab, sum, val;
+       float fac;
+       int i, n;
+
+       n = 2 * size + 1;
+
+       gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
+
+       sum = 0.0f;
+       fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
+       for (i = -size; i <= size; i++) {
+               val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
+               sum += val;
+               gausstab[i + size] = val;
+       }
+
+       sum = 1.0f / sum;
+       for (i = 0; i < n; i++)
+               gausstab[i] *= sum;
+
+       return gausstab;
+}
+
+static void do_gaussian_blur_effect_byte(Sequence *seq,
+                                         int start_line,
+                                         int x, int y,
+                                         int frame_width, int frame_height,
+                                         unsigned char *rect,
+                                         unsigned char *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+       GaussianBlurVars *data = seq->effectdata;
+       const int size_x = (int) (data->size_x + 0.5f),
+                 size_y = (int) (data->size_y + 0.5f);
+       int i, j;
+
+       /* Make gaussian weight tabke. */
+       float *gausstab_x, *gausstab_y;
+       gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+       if (data->size_x == data->size_y) {
+               gausstab_y = gausstab_x;
+       }
+       else {
+               gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+       }
+
+       for (i = 0; i < y; ++i) {
+               for (j = 0; j < x; ++j) {
+                       int out_index = INDEX(j, i);
+                       int current_x, current_y;
+                       float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+                       float accum_weight = 0.0f;
+                       for (current_y = i - size_y;
+                            current_y < i + size_y;
+                            ++current_y)
+                       {
+                               if (current_y < -start_line ||
+                                   current_y + start_line >= frame_height)
+                               {
+                                       /* Out of bounds. */
+                                       continue;
+                               }
+
+                               for (current_x = j - size_x;
+                                    current_x < j + size_x;
+                                    ++current_x)
+                               {
+                                       float weight;
+                                       int index = INDEX(current_x, current_y 
+ start_line);
+                                       if (current_x < 0 || current_x >= 
frame_width) {
+                                               /* Out of bounds. */
+                                               continue;
+                                       }
+                                       BLI_assert(index >= 0);
+                                       BLI_assert(index < frame_width * 
frame_height * 4);
+
+                                       weight = gausstab_x[current_x - j + 
size_x] *
+                                                gausstab_y[current_y - i + 
size_y];
+                                       accum[0] += rect[index] * weight;
+                                       accum[1] += rect[index + 1] * weight;
+                                       accum[2] += rect[index + 2] * weight;
+                                       accum[3] += rect[index + 3] * weight;
+                                       accum_weight += weight;
+                               }
+                       }
+                       out[out_index + 0] = accum[0] / accum_weight;
+                       out[out_index + 1] = accum[1] / accum_weight;
+                       out[out_index + 2] = accum[2] / accum_weight;
+                       out[out_index + 3] = accum[3] / accum_weight;
+               }
+       }
+
+       MEM_freeN(gausstab_x);
+       if (gausstab_x != gausstab_y) {
+               MEM_freeN(gausstab_y);
+       }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect_float(Sequence *seq,
+                                          int start_line,
+                                          int x, int y,
+                                          int frame_width, int frame_height,
+                                          float *rect,
+                                          float *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+       GaussianBlurVars *data = seq->effectdata;
+       const int size_x = (int) (data->size_x + 0.5f),
+                 size_y = (int) (data->size_y + 0.5f);
+       int i, j;
+
+       /* Make gaussian weight tabke. */
+       float *gausstab_x, *gausstab_y;
+       gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+       if (data->size_x == data->size_y) {
+               gausstab_y = gausstab_x;
+       }
+       else {
+               gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+       }
+
+       for (i = 0; i < y; ++i) {
+               for (j = 0; j < x; ++j) {
+                       int out_index = INDEX(j, i);
+                       int current_x, current_y;
+                       float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+                       float accum_weight = 0.0f;
+                       for (current_y = i - size_y;
+                            current_y < i + size_y;
+                            ++current_y)
+                       {
+                               float weight;
+                               if (current_y < -start_line ||
+                                   current_y + start_line >= frame_height)
+                               {
+                                       /* Out of bounds. */
+                                       continue;
+                               }
+
+                               for (current_x = j - size_x;
+                                    current_x < j + size_x;
+                                    ++current_x)
+                               {
+                                       int index = INDEX(current_x, current_y 
+ start_line);
+                                       if (current_x < 0 || current_x >= 
frame_width) {
+                                               /* Out of bounds. */
+                                               continue;
+                                       }
+
+                                       weight = gausstab_x[current_x - j + 
size_x] *
+                                                gausstab_y[current_y - i + 
size_y];
+                                       madd_v4_v4fl(accum, &rect[index], 
weight);
+                                       accum_weight += weight;
+                               }
+                       }
+                       mul_v4_v4fl(&out[out_index], accum, 1.0f / 
accum_weight);
+               }
+       }
+
+       MEM_freeN(gausstab_x);
+       if (gausstab_x != gausstab_y) {
+               MEM_freeN(gausstab_y);
+       }
+#undef INDEX
+}
+
+static void do_gaussian_blur_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)
+{
+       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_gaussian_blur_effect_float(seq,
+                                             start_line,
+                                             context->rectx,
+                                             total_lines,
+                                             context->rectx,
+                                             context->recty,
+                                             ibuf1->rect_float,
+                                             rect_out);
+       }
+       else {
+               unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+               slice_get_byte_buffers(context,
+                                      ibuf1, ibuf2,
+                                      NULL,
+                                      out,
+                                      start

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to