[gimp/soc-2011-warp] gimpoperationwarp: add a hardness property, and use it to compute influence with a gaussian like cur



commit 7273faf7dee68a5bc8d3914b5efd1ae2e0b95a7a
Author: Michael Murà <batolettre gmail com>
Date:   Tue Jul 5 16:35:32 2011 +0200

    gimpoperationwarp: add a hardness property, and use it to compute influence with a gaussian like curve
    implementation use a lookup table to speed things
    gimpwarpoptions: add a hardness property and UI

 app/gegl/gimpoperationwarp.c |   75 ++++++++++++++++++++++++++++++++++++++++-
 app/gegl/gimpoperationwarp.h |    3 ++
 app/tools/gimpwarpoptions.c  |   28 +++++++++++++--
 app/tools/gimpwarpoptions.h  |    1 +
 app/tools/gimpwarptool.c     |    1 +
 5 files changed, 102 insertions(+), 6 deletions(-)
---
diff --git a/app/gegl/gimpoperationwarp.c b/app/gegl/gimpoperationwarp.c
index e19c2da..ed95e0a 100644
--- a/app/gegl/gimpoperationwarp.c
+++ b/app/gegl/gimpoperationwarp.c
@@ -36,6 +36,7 @@ enum
   PROP_0,
   PROP_STRENGTH,
   PROP_SIZE,
+  PROP_HARDNESS,
   PROP_STROKE,
   PROP_BEHAVIOR
 };
@@ -60,6 +61,8 @@ static void         gimp_operation_warp_stamp           (GimpOperationWarp   *ow
 static gdouble      gimp_operation_warp_get_influence   (GimpOperationWarp   *ow,
                                                          gdouble              x,
                                                          gdouble              y);
+static void         gimp_operation_warp_calc_lut        (GimpOperationWarp   *ow);
+static gdouble      gauss                               (gdouble              f);
 
 G_DEFINE_TYPE (GimpOperationWarp, gimp_operation_warp,
                       GEGL_TYPE_OPERATION_FILTER)
@@ -98,6 +101,11 @@ gimp_operation_warp_class_init (GimpOperationWarpClass *klass)
                                    1.0, 10000.0, 40.0,
                                    GIMP_PARAM_STATIC_STRINGS);
 
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_HARDNESS,
+                                   "hardness", _("Effect Harness"),
+                                   0.0, 1.0, 0.5,
+                                   GIMP_PARAM_STATIC_STRINGS);
+
   GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, PROP_STROKE,
                                    "stroke", _("Stroke"),
                                    GEGL_TYPE_PATH,
@@ -128,6 +136,12 @@ gimp_operation_warp_finalize (GObject *object)
       self->stroke = NULL;
     }
 
+  if (self->lookup)
+    {
+      g_free (self->lookup);
+      self->lookup = NULL;
+    }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -147,6 +161,9 @@ gimp_operation_warp_get_property (GObject    *object,
     case PROP_SIZE:
       g_value_set_double (value, self->size);
       break;
+    case PROP_HARDNESS:
+      g_value_set_double (value, self->hardness);
+      break;
     case PROP_STROKE:
       g_value_set_object (value, self->stroke);
       break;
@@ -176,6 +193,9 @@ gimp_operation_warp_set_property (GObject      *object,
     case PROP_SIZE:
       self->size = g_value_get_double (value);
       break;
+    case PROP_HARDNESS:
+      self->hardness = g_value_get_double (value);
+      break;
     case PROP_STROKE:
       if (self->stroke)
         g_object_unref (self->stroke);
@@ -367,7 +387,58 @@ gimp_operation_warp_get_influence (GimpOperationWarp *ow,
                                    gdouble            x,
                                    gdouble            y)
 {
-  gfloat radius = sqrt(x*x+y*y);
+  gfloat radius;
+
+  if (!ow->lookup)
+    {
+      gimp_operation_warp_calc_lut (ow);
+    }
+
+  radius = sqrt(x*x+y*y);
+
+  if (radius < 0.5 * ow->size + 1)
+    return ow->strength * ow->lookup[(gint) RINT (radius)];
+  else
+    return 0.0;
+}
+
+/* set up lookup table */
+static void
+gimp_operation_warp_calc_lut (GimpOperationWarp  *ow)
+{
+  gint     length;
+  gint     x;
+  gdouble  exponent;
+
+  length = ceil (0.5 * ow->size + 1.0);
+
+  ow->lookup = g_malloc (length * sizeof (gfloat));
+
+  if ((1.0 - ow->hardness) < 0.0000004)
+    exponent = 1000000.0;
+  else
+    exponent = 0.4 / (1.0 - ow->hardness);
+
+  for (x = 0; x < length; x++)
+    {
+      ow->lookup[x] = gauss (pow (2.0 * x / ow->size, exponent));
+    }
+}
+
+static gdouble
+gauss (gdouble f)
+{
+  /* This is not a real gauss function. */
+  /* Approximation is valid if -1 < f < 1 */
+  if (f < -0.5)
+    {
+      f = -1.0 - f;
+      return (2.0 * f*f);
+    }
+
+  if (f < 0.5)
+    return (1.0 - 2.0 * f*f);
 
-  return (radius < ow->size / 2.0) ? ow->strength : 0.0;
+  f = 1.0 - f;
+  return (2.0 * f*f);
 }
diff --git a/app/gegl/gimpoperationwarp.h b/app/gegl/gimpoperationwarp.h
index f34aa96..f581a33 100644
--- a/app/gegl/gimpoperationwarp.h
+++ b/app/gegl/gimpoperationwarp.h
@@ -41,6 +41,7 @@ struct _GimpOperationWarp
   /* Properties of the operation */
   gdouble              strength;
   gdouble              size;
+  gdouble              hardness;
   GeglPath            *stroke;
   GimpWarpBehavior     behavior;
 
@@ -51,6 +52,8 @@ struct _GimpOperationWarp
 
   /* used to pass the temporary buffer to the function called by gegl_path_foreach */
   GeglBuffer          *buffer;
+
+  gfloat              *lookup;
 };
 
 struct _GimpOperationWarpClass
diff --git a/app/tools/gimpwarpoptions.c b/app/tools/gimpwarpoptions.c
index 0ee2b96..c9bb508 100644
--- a/app/tools/gimpwarpoptions.c
+++ b/app/tools/gimpwarpoptions.c
@@ -41,6 +41,7 @@ enum
   PROP_0,
   PROP_EFFECT_STRENGTH,
   PROP_EFFECT_SIZE,
+  PROP_EFFECT_HARDNESS,
   PROP_BEHAVIOR
 };
 
@@ -79,6 +80,11 @@ gimp_warp_options_class_init (GimpWarpOptionsClass *klass)
                                    1.0, 10000.0, 40.0,
                                    GIMP_PARAM_STATIC_STRINGS);
 
+  GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_EFFECT_HARDNESS,
+                                   "effect-hardness", _("Effect Hardness"),
+                                   0.0, 1.0, 0.5,
+                                   GIMP_PARAM_STATIC_STRINGS);
+
   GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_BEHAVIOR,
                                  "behavior",
                                  N_("Behavior"),
@@ -108,6 +114,9 @@ gimp_warp_options_set_property (GObject      *object,
     case PROP_EFFECT_SIZE:
       options->effect_size = g_value_get_double (value);
       break;
+    case PROP_EFFECT_HARDNESS:
+      options->effect_hardness = g_value_get_double (value);
+      break;
     case PROP_BEHAVIOR:
       options->behavior = g_value_get_enum (value);
       break;
@@ -134,6 +143,9 @@ gimp_warp_options_get_property (GObject    *object,
     case PROP_EFFECT_SIZE:
       g_value_set_double (value, options->effect_size);
       break;
+    case PROP_EFFECT_HARDNESS:
+      g_value_set_double (value, options->effect_hardness);
+      break;
     case PROP_BEHAVIOR:
       g_value_set_enum (value, options->behavior);
       break;
@@ -152,24 +164,32 @@ gimp_warp_options_gui (GimpToolOptions *tool_options)
   GtkWidget *behavior;
   GtkWidget *strength;
   GtkWidget *size;
+  GtkWidget *hardness;
 
   behavior = gimp_prop_enum_combo_box_new (config, "behavior", 0, 0);
   gtk_box_pack_start (GTK_BOX (vbox), behavior, FALSE, FALSE, 0);
   gtk_widget_show (behavior);
 
   strength = gimp_prop_spin_scale_new (config, "effect-strength",
-                                        _("Strength"),
-                                        0.01, 1.0, 2);
+                                       _("Strength"),
+                                       0.01, 1.0, 2);
   gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (strength), 0.0, 1.0);
   gtk_box_pack_start (GTK_BOX (vbox), strength, FALSE, FALSE, 0);
   gtk_widget_show (strength);
 
   size = gimp_prop_spin_scale_new (config, "effect-size",
-                                        _("Size"),
-                                        0.01, 1.0, 2);
+                                   _("Size"),
+                                   0.01, 1.0, 2);
   gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (size), 1.0, 1000.0);
   gtk_box_pack_start (GTK_BOX (vbox),  size, FALSE, FALSE, 0);
   gtk_widget_show (size);
 
+  hardness = gimp_prop_spin_scale_new (config, "effect-hardness",
+                                       _("Hardness"),
+                                       0.01, 1.0, 2);
+  gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (hardness), 0.0, 1.0);
+  gtk_box_pack_start (GTK_BOX (vbox),  hardness, FALSE, FALSE, 0);
+  gtk_widget_show (hardness);
+
   return vbox;
 }
diff --git a/app/tools/gimpwarpoptions.h b/app/tools/gimpwarpoptions.h
index d5d07a4..926197f 100644
--- a/app/tools/gimpwarpoptions.h
+++ b/app/tools/gimpwarpoptions.h
@@ -41,6 +41,7 @@ struct _GimpWarpOptions
 
   gdouble          effect_strength;
   gdouble          effect_size;
+  gdouble          effect_hardness;
   GimpWarpBehavior behavior;
 };
 
diff --git a/app/tools/gimpwarptool.c b/app/tools/gimpwarptool.c
index 94f1a33..b2cc14c 100644
--- a/app/tools/gimpwarptool.c
+++ b/app/tools/gimpwarptool.c
@@ -561,6 +561,7 @@ gimp_warp_tool_add_op (GimpWarpTool *wt)
                                 "behavior", options->behavior,
                                 "strength", options->effect_strength,
                                 "size", options->effect_size,
+                                "hardness", options->effect_hardness,
                                 "stroke", wt->current_stroke,
                                 NULL);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]