[gegl] npd: NPD operation uses GEGL sampler and operates in RGBA float



commit c33fb4516553b1c68b61139b92286b4d55e8ef72
Author: Marek Dvoroznak <dvoromar gmail com>
Date:   Wed Dec 11 06:08:15 2013 +0100

    npd: NPD operation uses GEGL sampler and operates in RGBA float

 libs/npd/graphics.c       |  101 ++++++++++++++++++++----------------
 libs/npd/graphics.h       |   94 +++++++++++++++++++--------------
 libs/npd/npd_common.h     |    3 +-
 libs/npd/npd_gegl.c       |    7 ++-
 libs/npd/npd_gegl.h       |   24 +++++----
 libs/npd/npd_math.c       |    4 +-
 libs/npd/npd_math.h       |   14 +++---
 operations/external/npd.c |  128 +++++++++++++++++++++++++++++++--------------
 8 files changed, 229 insertions(+), 146 deletions(-)
---
diff --git a/libs/npd/graphics.c b/libs/npd/graphics.c
index 8ca26a3..1cb8897 100644
--- a/libs/npd/graphics.c
+++ b/libs/npd/graphics.c
@@ -54,7 +54,7 @@ npd_bilinear_color_interpolation (NPDColor *I0,
   out->a = npd_bilinear_interpolation (I0->a, I1->a, I2->a, I3->a, dx, dy);
 }
 
-static gfloat
+gfloat
 npd_blend_band (gfloat src,
                 gfloat dst,
                 gfloat src_alpha,
@@ -70,24 +70,60 @@ npd_blend_colors (NPDColor *src,
                   NPDColor *dst,
                   NPDColor *out_color)
 {
-#ifdef NPD_RGBA_FLOAT
-  gfloat src_A = src->a,
-         dst_A = dst->a;
-#else
   gfloat src_A = src->a / 255.0,
          dst_A = dst->a / 255.0;
-#endif
   gfloat out_alpha = src_A + dst_A * (1 - src_A);
   gfloat out_alpha_recip = 1 / out_alpha;
 
   out_color->r = npd_blend_band (src->r, dst->r, src_A, dst_A, out_alpha_recip);
   out_color->g = npd_blend_band (src->g, dst->g, src_A, dst_A, out_alpha_recip);
   out_color->b = npd_blend_band (src->b, dst->b, src_A, dst_A, out_alpha_recip);
-#ifdef NPD_RGBA_FLOAT
-  out_color->a = out_alpha;
-#else
   out_color->a = out_alpha * 255;
-#endif
+}
+
+void
+npd_process_pixel_bilinear (NPDImage   *input_image,
+                            gfloat      ix,
+                            gfloat      iy,
+                            NPDImage   *output_image,
+                            gfloat      ox,
+                            gfloat      oy,
+                            NPDSettings settings)
+{
+  gint fx, fy;
+  gfloat dx, dy;
+  NPDColor I0, interpolated, *final_color;
+
+  fx = floor (ix);
+  fy = floor (iy);
+
+  npd_get_pixel_color (input_image, fx, fy, &I0);
+  final_color = &I0;
+
+  /* bilinear interpolation */
+  if (settings & NPD_BILINEAR_INTERPOLATION)
+    {
+      NPDColor I1, I2, I3;
+
+      dx =  ix - fx;
+      dy =  iy - fy;
+
+      npd_get_pixel_color (input_image, fx + 1, fy,     &I1);
+      npd_get_pixel_color (input_image, fx,     fy + 1, &I2);
+      npd_get_pixel_color (input_image, fx + 1, fy + 1, &I3);
+      npd_bilinear_color_interpolation (&I0, &I1, &I2, &I3, dx, dy, &interpolated);
+      final_color = &interpolated;
+    }
+
+  /* alpha blending */
+  if (settings & NPD_ALPHA_BLENDING)
+    {
+      NPDColor dest;
+      npd_get_pixel_color (output_image, ox, oy, &dest);
+      npd_blend_colors (final_color, &dest, final_color);
+    }
+
+  npd_set_pixel_color (output_image, ox, oy, final_color);
 }
 
 static void
@@ -99,47 +135,18 @@ npd_draw_texture_line (gint        x1,
                        NPDImage   *output_image,
                        NPDSettings settings)
 {
-  gint x, fx, fy;
-  gfloat dx, dy;
+  gint x;
 
   for (x = x1; x <= x2; x++)
     {
       NPDPoint p, q;
-      NPDColor I0, interpolated, *final;
 
       q.x = x; q.y = y;
       npd_apply_transformation (A, &q, &p);
 
-      fx = floor (p.x);
-      fy = floor (p.y);
-
-      npd_get_pixel_color (input_image, fx, fy, &I0);
-      final = &I0;
-
-      /* bilinear interpolation */
-      if (settings & NPD_BILINEAR_INTERPOLATION)
-        {
-          NPDColor I1, I2, I3;
-
-          dx =  p.x - fx;
-          dy =  p.y - fy;
-
-          npd_get_pixel_color (input_image, fx + 1, fy,     &I1);
-          npd_get_pixel_color (input_image, fx,     fy + 1, &I2);
-          npd_get_pixel_color (input_image, fx + 1, fy + 1, &I3);
-          npd_bilinear_color_interpolation (&I0, &I1, &I2, &I3, dx, dy, &interpolated);
-          final = &interpolated;
-        }
-
-      /* alpha blending */
-      if (settings & NPD_ALPHA_BLENDING)
-        {
-          NPDColor dest;
-          npd_get_pixel_color (output_image, x, y, &dest);
-          npd_blend_colors (final, &dest, final);
-        }
-
-      npd_set_pixel_color (output_image, x, y, final);
+      npd_process_pixel (input_image, p.x, p.y,
+                         output_image, x, y,
+                         settings);
     }
 }
 
@@ -354,7 +361,7 @@ npd_create_mesh (NPDModel *model,
   gint      square_size = model->mesh_square_size;
   NPDImage *image = model->reference_image;
   gint      i, cy, cx, y, x, r, c, ow, oh;
-  NPDColor  pixel_color = { 0, 0, 0, 0 };
+  NPDColor  pixel_color;
   GArray   *squares;
   gint     *sq2id;
   gboolean *empty_squares;
@@ -549,7 +556,6 @@ npd_create_model_from_image (NPDModel  *model,
   npd_create_mesh (model, width, height, position_x, position_y);
 }
 
-
 void
 npd_draw_mesh (NPDModel   *model,
                NPDDisplay *display)
@@ -572,3 +578,8 @@ npd_draw_mesh (NPDModel   *model,
       npd_draw_line (display, p1->x, p1->y, first->x, first->y);
     }
 }
+
+void (*npd_process_pixel)   (NPDImage*, gfloat, gfloat, NPDImage*, gfloat, gfloat, NPDSettings) = NULL;
+void (*npd_draw_line)       (NPDDisplay*, gfloat, gfloat, gfloat, gfloat) = NULL;
+void (*npd_get_pixel_color) (NPDImage*, gint, gint, NPDColor*) = NULL;
+void (*npd_set_pixel_color) (NPDImage*, gint, gint, NPDColor*) = NULL;
diff --git a/libs/npd/graphics.h b/libs/npd/graphics.h
index 69c272d..89c1ab4 100644
--- a/libs/npd/graphics.h
+++ b/libs/npd/graphics.h
@@ -24,20 +24,17 @@
 
 #include "npd_common.h"
 
-//#define NPD_RGBA_FLOAT
-
-struct _NPDColor {
-#ifdef NPD_RGBA_FLOAT
-  gfloat r;
-  gfloat g;
-  gfloat b;
-  gfloat a;
-#else
-  guint8 r;
-  guint8 g;
-  guint8 b;
-  guint8 a;
-#endif
+struct _NPDColor
+{
+  union {
+    guint32 color;
+    struct {
+      guint8 r;
+      guint8 g;
+      guint8 b;
+      guint8 a;
+    };
+  };
 };
 
 typedef enum
@@ -46,30 +43,49 @@ typedef enum
   NPD_ALPHA_BLENDING         = 1 << 1
 } NPDSettings;
 
-void        npd_create_model_from_image       (NPDModel   *model,
-                                               NPDImage   *image,
-                                               gint        width,
-                                               gint        height,
-                                               gint        position_x,
-                                               gint        position_y,
-                                               gint        square_size);
-void        npd_draw_model_into_image         (NPDModel   *model,
-                                               NPDImage   *image);
-void        npd_draw_mesh                     (NPDModel   *model,
-                                               NPDDisplay *display);
-gboolean    npd_is_color_transparent          (NPDColor *color);
-void      (*npd_draw_line)                    (NPDDisplay *display,
-                                               gfloat      x0,
-                                               gfloat      y0,
-                                               gfloat      x1,
-                                               gfloat      y1);
-void      (*npd_get_pixel_color)              (NPDImage   *image,
-                                               gint        x,
-                                               gint        y,
-                                               NPDColor   *color);
-void      (*npd_set_pixel_color)              (NPDImage   *image,
-                                               gint        x,
-                                               gint        y,
-                                               NPDColor   *color);
+void            npd_create_model_from_image       (NPDModel   *model,
+                                                   NPDImage   *image,
+                                                   gint        width,
+                                                   gint        height,
+                                                   gint        position_x,
+                                                   gint        position_y,
+                                                   gint        square_size);
+void            npd_draw_model_into_image         (NPDModel   *model,
+                                                   NPDImage   *image);
+void            npd_draw_mesh                     (NPDModel   *model,
+                                                   NPDDisplay *display);
+gboolean        npd_is_color_transparent          (NPDColor   *color);
+gfloat          npd_blend_band                    (gfloat      src,
+                                                   gfloat      dst,
+                                                   gfloat      src_alpha,
+                                                   gfloat      dst_alpha,
+                                                   gfloat      out_alpha_recip);
+extern void   (*npd_draw_line)                    (NPDDisplay *display,
+                                                   gfloat      x0,
+                                                   gfloat      y0,
+                                                   gfloat      x1,
+                                                   gfloat      y1);
+extern void   (*npd_process_pixel)                (NPDImage   *input_image,
+                                                   gfloat      ix,
+                                                   gfloat      iy,
+                                                   NPDImage   *output_image,
+                                                   gfloat      ox,
+                                                   gfloat      oy,
+                                                   NPDSettings settings);
+void            npd_process_pixel_bilinear        (NPDImage   *input_image,
+                                                   gfloat      ix,
+                                                   gfloat      iy,
+                                                   NPDImage   *output_image,
+                                                   gfloat      ox,
+                                                   gfloat      oy,
+                                                   NPDSettings settings);
+extern void   (*npd_get_pixel_color)              (NPDImage   *image,
+                                                   gint        x,
+                                                   gint        y,
+                                                   NPDColor   *color);
+extern void   (*npd_set_pixel_color)              (NPDImage   *image,
+                                                   gint        x,
+                                                   gint        y,
+                                                   NPDColor   *color);
 
 #endif /*__NPD_GRAPHICS_H__ */
diff --git a/libs/npd/npd_common.h b/libs/npd/npd_common.h
index fe57697..40a05ed 100644
--- a/libs/npd/npd_common.h
+++ b/libs/npd/npd_common.h
@@ -94,9 +94,10 @@ typedef struct
 } NPDModel;
 
 #define npd_init(set_pixel, get_pixel,                                         \
-                 draw_line)                                                    \
+                 process_pixel, draw_line)                                     \
 npd_set_pixel_color      = set_pixel;                                          \
 npd_get_pixel_color      = get_pixel;                                          \
+npd_process_pixel        = process_pixel;                                      \
 npd_draw_line            = draw_line;
 
 void             npd_init_model                 (NPDModel        *model);
diff --git a/libs/npd/npd_gegl.c b/libs/npd/npd_gegl.c
index 0d5ea3a..31c31c4 100644
--- a/libs/npd/npd_gegl.c
+++ b/libs/npd/npd_gegl.c
@@ -65,7 +65,7 @@ npd_gegl_set_pixel_color (NPDImage *image,
   if (x > -1 && x < image->width &&
       y > -1 && y < image->height)
     {
-      gint position = y * image->rowstride + 4 * x;
+      gint position = 4 * (y * image->width + x);
 
       image->buffer[position + 0] = color->r;
       image->buffer[position + 1] = color->g;
@@ -83,7 +83,7 @@ npd_gegl_get_pixel_color (NPDImage *image,
   if (x > -1 && x < image->width &&
       y > -1 && y < image->height)
     {
-      gint position = y * image->rowstride + 4 * x;
+      gint position = 4 * (y * image->width + x);
 
       color->r = image->buffer[position + 0];
       color->g = image->buffer[position + 1];
@@ -116,6 +116,9 @@ npd_gegl_init_image (NPDImage   *image,
   image->gegl_buffer = gegl_buffer;
   image->width = gegl_buffer_get_width (gegl_buffer);
   image->rowstride = image->width * babl_format_get_bytes_per_pixel (format);
+  image->length = babl_format_get_n_components (format) * gegl_buffer_get_pixel_count (gegl_buffer);
   image->height = gegl_buffer_get_height (gegl_buffer);
   image->format = format;
+  image->buffer = NULL;
+  image->buffer_f = NULL;
 }
diff --git a/libs/npd/npd_gegl.h b/libs/npd/npd_gegl.h
index 855473e..edba11d 100644
--- a/libs/npd/npd_gegl.h
+++ b/libs/npd/npd_gegl.h
@@ -32,22 +32,24 @@ struct _NPDImage
   gint        height;
   NPDPoint    position;
   gint        rowstride;
+  gint        length;
   GeglBuffer *gegl_buffer;
   guchar     *buffer;
+  gfloat     *buffer_f;
   const Babl *format;
+  GeglSamplerType sampler_type;
 };
 
-void npd_gegl_set_pixel_color (NPDImage *image,
-                               gint      x,
-                               gint      y,
-                               NPDColor *color);
-
-void npd_gegl_get_pixel_color (NPDImage *image,
-                               gint      x,
-                               gint      y,
-                               NPDColor *color);
-void npd_gegl_open_buffer     (NPDImage *image);
-void npd_gegl_close_buffer    (NPDImage *image);
+void npd_gegl_set_pixel_color (NPDImage   *image,
+                               gint        x,
+                               gint        y,
+                               NPDColor   *color);
+void npd_gegl_get_pixel_color (NPDImage   *image,
+                               gint        x,
+                               gint        y,
+                               NPDColor   *color);
+void npd_gegl_open_buffer     (NPDImage   *image);
+void npd_gegl_close_buffer    (NPDImage   *image);
 void npd_gegl_init_image      (NPDImage   *image,
                                GeglBuffer *gegl_buffer,
                                const Babl *format);
diff --git a/libs/npd/npd_math.c b/libs/npd/npd_math.c
index b14f73f..b2dd1d5 100644
--- a/libs/npd/npd_math.c
+++ b/libs/npd/npd_math.c
@@ -41,7 +41,7 @@ gfloat
 npd_SED (NPDPoint *p1,
          NPDPoint *p2)
 {
-  gint dx = p1->x - p2->x;
-  gint dy = p1->y - p2->y;
+  gfloat dx = p1->x - p2->x;
+  gfloat dy = p1->y - p2->y;
   return dx * dx + dy * dy;
 }
diff --git a/libs/npd/npd_math.h b/libs/npd/npd_math.h
index 1b3e624..a48933f 100644
--- a/libs/npd/npd_math.h
+++ b/libs/npd/npd_math.h
@@ -39,12 +39,12 @@ void        npd_compute_affinity     (NPDPoint  *p11,
 void        npd_apply_transformation (NPDMatrix *T,
                                       NPDPoint  *src,
                                       NPDPoint  *dest);
-gboolean    npd_equal_floats_epsilon (gfloat a,
-                                      gfloat b,
-                                      gfloat epsilon);
-gboolean    npd_equal_floats         (gfloat a,
-                                      gfloat b);
-gfloat      npd_SED                  (NPDPoint *p1,
-                                      NPDPoint *p2);
+gboolean    npd_equal_floats_epsilon (gfloat     a,
+                                      gfloat     b,
+                                      gfloat     epsilon);
+gboolean    npd_equal_floats         (gfloat     a,
+                                      gfloat     b);
+gfloat      npd_SED                  (NPDPoint  *p1,
+                                      NPDPoint  *p2);
 
 #endif /* __NPD_MATH_H__ */
diff --git a/operations/external/npd.c b/operations/external/npd.c
index 12182fa..dda01d6 100644
--- a/operations/external/npd.c
+++ b/operations/external/npd.c
@@ -42,6 +42,15 @@ gegl_chant_boolean (MLS_weights, _("MLS weights"),
 gegl_chant_double  (MLS_weights_alpha, _("MLS weights alpha"),
                     0.1, 2.0, 1.0,
                     _("Alpha parameter of MLS weights"))
+
+gegl_chant_boolean (preserve_model, _("preserve model"),
+                    FALSE,
+                    _("When TRUE the model will not be freed"))
+
+gegl_chant_enum    (sampler_type, _("Sampler"),
+                    GeglSamplerType, gegl_sampler_type,
+                    GEGL_SAMPLER_CUBIC,
+                    _("Sampler used internally"))
 #else
 
 #define GEGL_CHANT_TYPE_FILTER
@@ -61,7 +70,7 @@ struct _NPDDisplay
 typedef struct
 {
   gboolean  first_run;
-  NPDModel  model;
+  NPDModel *model;
 } NPDProperties;
 
 static void
@@ -69,18 +78,45 @@ prepare (GeglOperation *operation)
 {
   GeglChantO    *o = GEGL_CHANT_PROPERTIES (operation);
   NPDProperties *props;
-
   if (o->chant_data == NULL)
     {
       props = g_new (NPDProperties, 1);
-      props->first_run = TRUE;
-      o->chant_data    = props;
+      props->first_run      = TRUE;
+      props->model          = o->model;
+      o->chant_data         = props;
+    }
+
+  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
+}
+
+static void
+npd_gegl_process_pixel (NPDImage *input_image,
+                        gfloat    ix,
+                        gfloat    iy,
+                        NPDImage *output_image,
+                        gfloat    ox,
+                        gfloat    oy,
+                        NPDSettings settings)
+{
+  if (ox > -1 && ox < output_image->width &&
+      oy > -1 && oy < output_image->height)
+    {
+      gint position = 4 * (((gint) oy) * output_image->width + ((gint) ox));
+      gegl_buffer_sample (input_image->gegl_buffer, ix, iy, NULL,
+                          &output_image->buffer_f[position], output_image->format,
+                          output_image->sampler_type, GEGL_ABYSS_NONE);
     }
+}
 
-  gegl_operation_set_format (operation, "input",
-                             babl_format ("RGBA float"));
-  gegl_operation_set_format (operation, "output",
-                             babl_format ("RGBA float"));
+static void
+npd_gegl_get_pixel_color_f (NPDImage *image,
+                          gint      x,
+                          gint      y,
+                          NPDColor *color)
+{
+  gegl_buffer_sample (image->gegl_buffer, x, y, NULL,
+                      &color->color, babl_format ("RGBA u8"),
+                      GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
 }
 
 static gboolean
@@ -90,41 +126,48 @@ process (GeglOperation       *operation,
          const GeglRectangle *roi,
          gint                 level)
 {
-  GeglChantO    *o       = GEGL_CHANT_PROPERTIES (operation);
-  const Babl    *format  = babl_format ("RGBA u8");
-  NPDProperties *props   = o->chant_data;
-  NPDModel      *model   = &props->model;
-  gint           length  = gegl_buffer_get_pixel_count (input) * 4;
-  NPDDisplay    *display = model->display;
+  GeglChantO    *o          = GEGL_CHANT_PROPERTIES (operation);
+  const Babl    *format_f   = babl_format ("RGBA float");
+  NPDProperties *props      = o->chant_data;
+  NPDModel      *model      = props->model;
+  gboolean       have_model = model != NULL;
+  NPDDisplay    *display    = NULL;
 
   if (props->first_run)
     {
       NPDImage *input_image = g_new (NPDImage, 1);
       display = g_new (NPDDisplay, 1);
 
-      npd_init (npd_gegl_set_pixel_color,
-                npd_gegl_get_pixel_color,
-                NULL);
+      npd_init (NULL,
+                npd_gegl_get_pixel_color_f,
+                npd_gegl_process_pixel, NULL);
 
-      npd_gegl_init_image (input_image, input, format);
-      input_image->buffer = g_new0 (guchar, gegl_buffer_get_pixel_count (input) * 4);
-      gegl_buffer_get (input, NULL, 1.0, format, input_image->buffer,
-                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+      npd_gegl_init_image (&display->image, output, format_f);
+      display->image.sampler_type = o->sampler_type;
+      npd_gegl_init_image (input_image, input, gegl_buffer_get_format (output));
 
-      npd_gegl_init_image (&display->image, output, format);
-      npd_gegl_open_buffer (&display->image);
+      if (!have_model)
+        {
+          model = props->model = o->model = g_new (NPDModel, 1);
+          gegl_buffer_copy (input, NULL, output, NULL);
+          display->image.buffer_f = (gfloat*) gegl_buffer_linear_open (display->image.gegl_buffer,
+                                                                       NULL,
+                                                                      &display->image.rowstride,
+                                                                       format_f);
+          npd_create_model_from_image (model, input_image,
+                                       input_image->width, input_image->height,
+                                       0, 0, o->square_size);
+        }
 
+      model->reference_image = input_image;
       model->display = display;
-      npd_create_model_from_image (model, input_image,
-                                   input_image->width, input_image->height,
-                                   0, 0, o->square_size);
-      o->model = model;
-      memcpy (display->image.buffer, input_image->buffer, length);
-
       props->first_run = FALSE;
     }
-  else
+
+  if (have_model)
     {
+      display = model->display;
+
       npd_set_deformation_type (model, o->ASAP_deformation, o->MLS_weights);
 
       if (o->MLS_weights &&
@@ -134,13 +177,17 @@ process (GeglOperation       *operation,
           npd_compute_MLS_weights (model);
         }
 
-      npd_gegl_open_buffer (&display->image);
-      memset (display->image.buffer, 0, length);
+      gegl_buffer_clear (display->image.gegl_buffer, NULL);
+      display->image.buffer_f = (gfloat*) gegl_buffer_linear_open (display->image.gegl_buffer,
+                                                                   NULL,
+                                                                  &display->image.rowstride,
+                                                                   format_f);
+
       npd_deform_model (model, o->rigidity);
       npd_draw_model_into_image (model, &display->image);
     }
 
-  npd_gegl_close_buffer (&display->image);
+  gegl_buffer_linear_close (display->image.gegl_buffer, display->image.buffer_f);
 
   return TRUE;
 }
@@ -152,14 +199,17 @@ finalize (GObject *object)
 
   if (o->chant_data)
     {
-      NPDProperties *props = o->chant_data;
-      NPDModel   *model = &props->model;
-      NPDDisplay *display = model->display;
+      NPDProperties *props   = o->chant_data;
+      NPDModel      *model   = props->model;
+      NPDDisplay    *display = model->display;
 
-      g_free (model->reference_image->buffer);
-      g_free (model->reference_image);
       g_free (display);
-      npd_destroy_model (model);
+      g_free (model->reference_image);
+      if (!o->preserve_model)
+        {
+          npd_destroy_model (model);
+          g_free (model);
+        }
 
       o->chant_data = NULL;
     }


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