[gegl/soc-2013-n-point-deformation: 4/28] add part of n-point deformation library



commit ca0fb347c0d288e7dfe045dcc18bd448e65d51c3
Author: Marek Dvoroznak <dvoromar gmail com>
Date:   Sun Jul 21 19:47:58 2013 +0200

    add part of n-point deformation library

 configure.ac                    |   14 ++
 libs/Makefile.am                |    2 +-
 libs/npd/.gitignore             |    6 +
 libs/npd/Makefile.am            |   16 ++
 libs/npd/graphics.c             |  355 +++++++++++++++++++++++++++++++++++++++
 libs/npd/graphics.h             |   93 ++++++++++
 libs/npd/npd.h                  |   29 ++++
 libs/npd/npd_common.c           |    7 +
 libs/npd/npd_common.h           |   21 ++-
 libs/npd/npd_gegl.c             |    2 +-
 libs/npd/npd_gegl.h             |    2 +-
 operations/external/Makefile.am |    6 +
 operations/external/npd.c       |  173 +++++++++++++++++++-
 13 files changed, 714 insertions(+), 12 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f567090..d75d11d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -246,6 +246,7 @@ case "$target_or_host" in
     ;;
   x86_64-*-*)
     have_x86=yes
+    have_64_bit=yes
     AC_DEFINE(ARCH_X86, 1, [Define to 1 if you are compiling for ix86.])
     AC_DEFINE(ARCH_X86_64, 1, [Define to 1 if you are compiling for amd64.])
     ;;
@@ -255,6 +256,7 @@ case "$target_or_host" in
     ;;
   ppc64-*-* | powerpc64-*)
     have_ppc=yes
+    have_64_bit=yes
     AC_DEFINE(ARCH_PPC, 1, [Define to 1 if you are compiling for PowerPC.])
     AC_DEFINE(ARCH_PPC64, 1, [Define to 1 if you are compiling for PowerPC64.])
     ;;
@@ -262,6 +264,8 @@ case "$target_or_host" in
     ;;
 esac
 
+AM_CONDITIONAL(HAVE_64_BIT, test "x$have_64_bit" = "xyes")  
+
 
 ####################################################
 # Check how to generate plug-ins (with gcc at least)
@@ -1074,6 +1078,14 @@ if test "x$have_p2tc" != "xyes"; then
   AC_SUBST(P2TC_LIBS, "-L\$(top_builddir)/libs/poly2tri-c/poly2tri-c -lpoly2tri-c")
 fi
 
+##################
+# Check for libnpd
+##################
+have_libnpd="yes (internal)"
+
+AC_SUBST(NPD_CFLAGS, "-I\$(top_srcdir)/libs/npd")
+AC_SUBST(NPD_LIBS, "-L\$(top_builddir)/libs/npd -lnpd")
+
 #######################
 # Check for other items
 #######################
@@ -1139,6 +1151,7 @@ gegl/property-types/Makefile
 gegl/opencl/Makefile
 libs/Makefile
 libs/rgbe/Makefile
+libs/npd/Makefile
 libs/poly2tri-c/Makefile
 libs/poly2tri-c/poly2tri-c/Makefile
 libs/poly2tri-c/poly2tri-c/render/Makefile
@@ -1225,4 +1238,5 @@ Optional dependencies:
   umfpack:         $have_umfpack
   webp:            $have_webp
   poly2tri-c:      $have_p2tc
+  libnpd:          $have_libnpd
 ]);
diff --git a/libs/Makefile.am b/libs/Makefile.am
index 176d347..334cf56 100644
--- a/libs/Makefile.am
+++ b/libs/Makefile.am
@@ -1 +1 @@
-SUBDIRS = rgbe poly2tri-c
+SUBDIRS = rgbe poly2tri-c npd
diff --git a/libs/npd/.gitignore b/libs/npd/.gitignore
new file mode 100644
index 0000000..4e0b01c
--- /dev/null
+++ b/libs/npd/.gitignore
@@ -0,0 +1,6 @@
+/Makefile
+/Makefile.in
+/.deps/
+/.libs/
+/*.lo
+/*.la
\ No newline at end of file
diff --git a/libs/npd/Makefile.am b/libs/npd/Makefile.am
new file mode 100644
index 0000000..ffc55f9
--- /dev/null
+++ b/libs/npd/Makefile.am
@@ -0,0 +1,16 @@
+noinst_LTLIBRARIES = libnpd.la
+
+AM_CFLAGS = $(GLIB_CFLAGS) $(NPD_CFLAGS) -I$(top_builddir)/gegl -I$(top_srcdir)/gegl
+AM_LDFLAGS = $(GLIB_LIBS) $(NPD_LIBS)
+
+libnpd_la_SOURCES = \
+    npd_common.h    \
+    npd_common.c    \
+    deformation.h   \
+    deformation.c   \
+    npd_math.h      \
+    npd_math.c      \
+    graphics.h      \
+    graphics.c      \
+    npd_gegl.h      \
+    npd_gegl.c
diff --git a/libs/npd/graphics.c b/libs/npd/graphics.c
new file mode 100644
index 0000000..e4f0878
--- /dev/null
+++ b/libs/npd/graphics.c
@@ -0,0 +1,355 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#include "graphics.h"
+#include "glib.h"
+#include <math.h>
+#include "npd_math.h"
+
+void
+npd_create_mesh_from_image (NPDModel *model,
+                            gint      width,
+                            gint      height,
+                            gint      position_x,
+                            gint      position_y)
+{
+  gint square_size = model->mesh_square_size;
+  NPDHiddenModel *hidden_model = model->hidden_model;
+  NPDImage *image = model->reference_image;
+  gint i, cy, cx, y, x;
+  NPDColor transparent = { 0, 0, 0, 0 };
+  NPDColor pixel_color = { 0, 0, 0, 0 };
+  GPtrArray *current_bones, *reference_bones;
+
+  /* create quadrilaterals above the image */
+  width  = ceil ((gfloat) width  / square_size);
+  height = ceil ((gfloat) height / square_size);
+
+  current_bones   = g_ptr_array_new ();
+  reference_bones = g_ptr_array_new ();
+
+  for (cy = 0; cy < height; cy++)
+    {
+      for (cx = 0; cx < width; cx++)
+        {
+          gboolean is_empty = TRUE;
+
+          for (y = cy * square_size; y < (cy + 1) * square_size; y++)
+            {
+              for (x = cx * square_size; x < (cx + 1) * square_size; x++)
+                {
+                  npd_get_pixel_color (image, x, y, &pixel_color);
+
+                  if (!npd_compare_colors (&pixel_color, &transparent))
+                    {
+                      is_empty = FALSE;
+                      goto not_empty;
+                    }
+                }
+            }
+
+          not_empty:
+          if (!is_empty)
+            {
+              NPDBone *current_bone, *reference_bone;
+              NPDPoint *current_points, *ref_points;
+              gfloat *weights;
+              gint coords[8] = {cx, cx + 1, cx + 1, cx,
+                                cy, cy,     cy + 1, cy + 1};
+
+              current_bone   = g_new (NPDBone,  1);
+              reference_bone = g_new (NPDBone,  1);
+              current_points = g_new (NPDPoint, 4);
+              ref_points     = g_new (NPDPoint, 4);
+              weights        = g_new (gfloat,   4);
+              
+              for (i = 0; i < 4; i++)
+                {
+                  weights[i] = 1.0;
+                
+                  current_points[i].x = position_x + (coords[i] * square_size);
+                  current_points[i].y = position_y + (coords[i + 4] * square_size);
+                  current_points[i].weight = &weights[i];
+                  current_points[i].fixed = FALSE;
+                  current_points[i].current_bone = current_bone;
+                  current_points[i].reference_bone = reference_bone;
+                  current_points[i].index = i;
+
+                  ref_points[i].x = current_points[i].x - position_x;
+                  ref_points[i].y = current_points[i].y - position_y;
+                  ref_points[i].weight = &weights[i];
+                  ref_points[i].fixed = current_points[i].fixed;
+                  ref_points[i].current_bone = current_bone;
+                  ref_points[i].reference_bone = reference_bone;
+                  ref_points[i].index = i;
+                  
+                  current_points[i].counterpart = &ref_points[i];
+                  ref_points[i].counterpart = &current_points[i];
+                }
+
+              current_bone->points = current_points;
+              current_bone->num_of_points = 4;
+              current_bone->weights = weights;
+              g_ptr_array_add (current_bones, current_bone);
+
+              reference_bone->points = ref_points;
+              reference_bone->num_of_points = 4;
+              reference_bone->weights = weights;
+              g_ptr_array_add (reference_bones, reference_bone);
+
+              hidden_model->num_of_bones++;
+            }
+        }
+    }
+  
+  hidden_model->current_bones = g_new (NPDBone, current_bones->len);
+  hidden_model->reference_bones = g_new (NPDBone, reference_bones->len);
+  
+  for (i = 0; i < current_bones->len; i++)
+    {
+      hidden_model->current_bones[i] = *(NPDBone*) g_ptr_array_index (current_bones, i);
+      hidden_model->reference_bones[i] = *(NPDBone*) g_ptr_array_index (reference_bones, i);
+    }
+
+  g_ptr_array_free(current_bones, TRUE);
+  g_ptr_array_free(reference_bones, TRUE);
+}
+
+gboolean
+npd_compare_colors (NPDColor *c1,
+                    NPDColor *c2)
+{
+  if (c1->r == c2->r &&
+      c1->g == c2->g &&
+      c1->b == c2->b &&
+      c1->a == c2->a)
+    return TRUE;
+
+  return FALSE;
+}
+
+gboolean
+npd_is_color_transparent (NPDColor *color)
+{
+  if (color->a == 0 &&
+      color->b == 0 &&
+      color->g == 0 &&
+      color->r == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+gint
+npd_bilinear_interpolation (gint   I0,
+                            gint   I1,
+                            gint   I2,
+                            gint   I3,
+                            gfloat dx,
+                            gfloat dy)
+{
+  return floor ((I0 * (1 - dx) + I1 * dx) * (1 - dy)
+              + (I2 * (1 - dx) + I3 * dx) * dy);
+}
+
+void
+npd_bilinear_color_interpolation (NPDColor *I0,
+                                  NPDColor *I1,
+                                  NPDColor *I2,
+                                  NPDColor *I3,
+                                  gfloat    dx,
+                                  gfloat    dy,
+                                  NPDColor *out)
+{
+  out->r = npd_bilinear_interpolation (I0->r, I1->r, I2->r, I3->r, dx, dy);
+  out->g = npd_bilinear_interpolation (I0->g, I1->g, I2->g, I3->g, dx, dy);
+  out->b = npd_bilinear_interpolation (I0->b, I1->b, I2->b, I3->b, dx, dy);
+  out->a = npd_bilinear_interpolation (I0->a, I1->a, I2->a, I3->a, dx, dy);
+}
+
+void
+npd_texture_fill_triangle (gint x1,
+                           gint y1,
+                           gint x2,
+                           gint y2,
+                           gint x3,
+                           gint y3,
+                           NPDMatrix *A,
+                           NPDImage *input_image,
+                           NPDImage *output_image)
+{
+  gint yA, yB, yC, xA, xB, xC;
+  gint tmp, y;
+  gint deltaXAB, deltaYAB;
+  gint deltaXBC, deltaYBC;
+  gint deltaXAC, deltaYAC;
+
+  gfloat slopeAB;
+  gfloat slopeBC;
+  gfloat slopeAC;
+
+  gfloat k, l;
+  gfloat slope1, slope2, slope3, slope4;
+
+  if (y1 == y2 && x1 > x2) {
+      tmp = y1;y1 = y2;y2 = tmp;
+      tmp = x1;x1 = x2;x2 = tmp;
+  }
+  if (y1 == y3 && x1 > x3) {
+      tmp = y1;y1 = y3;y3 = tmp;
+      tmp = x1;x1 = x3;x3 = tmp;
+  }
+  if (y2 == y3 && x2 > x3) {
+      tmp = y2;y2 = y3;y3 = tmp;
+      tmp = x2;x2 = x3;x3 = tmp;
+  }
+
+  if (y1 <= y2) {
+      if (y2 <= y3) {
+          // y1 <= y2 <= y3
+          yA=y1;yB=y2;yC=y3;
+          xA=x1;xB=x2;xC=x3;
+      } else if (y1 <= y3) {
+          // y1 <= y3 < y2
+          yA=y1;yB=y3;yC=y2;
+          xA=x1;xB=x3;xC=x2;
+      } else {
+          // y3 < y1 < y2
+          yA=y3;yB=y1;yC=y2;
+          xA=x3;xB=x1;xC=x2;
+      }
+  } else {
+      if (y1 <= y3) {
+          // y2 < y1 <= y3
+          yA=y2;yB=y1;yC=y3;
+          xA=x2;xB=x1;xC=x3;
+      } else if (y2 <= y3) {
+          // y2 <= y3 < y1
+          yA=y2;yB=y3;yC=y1;
+          xA=x2;xB=x3;xC=x1;
+      } else {
+          // y3 < y2 < y1
+          yA=y3;yB=y2;yC=y1;
+          xA=x3;xB=x2;xC=x1;
+      }
+  }
+
+  deltaXAB = xB-xA, deltaYAB = yB-yA;
+  deltaXBC = xC-xB, deltaYBC = yC-yB;
+  deltaXAC = xC-xA, deltaYAC = yC-yA;
+
+  slopeBC = (deltaYBC == 0 ? 0 : (gfloat) deltaXBC/deltaYBC);
+  slopeAC = (deltaYAC == 0 ? 0 : (gfloat) deltaXAC/deltaYAC);
+
+  if (deltaYAB == 0) {
+      slopeAB = 0;
+      k = xA;
+      l = xB;
+
+      slope1 = slopeAB;
+      slope2 = slopeAC;
+      slope3 = slopeAC;
+      slope4 = slopeBC;
+  } else {
+      slopeAB = (gfloat) deltaXAB/deltaYAB;
+      k = xA;
+      l = xA;
+
+      if (slopeAB > slopeAC) {
+          slope1 = slopeAC;
+          slope2 = slopeAB;
+          slope3 = slopeAC;
+          slope4 = slopeBC;
+      } else {
+          slope1 = slopeAB;
+          slope2 = slopeAC;
+          slope3 = slopeBC;
+          slope4 = slopeAC;
+      }
+  }
+
+  for (y=yA; y<yB; ++y) {
+     npd_draw_texture_line((gint)round(k), (gint)round(l), y, A, input_image, output_image);
+     k += slope1;
+     l += slope2;
+  }
+
+  for (y=yB; y<=yC; ++y) {
+     npd_draw_texture_line((gint)round(k), (gint)round(l), y, A, input_image, output_image);
+     k += slope3;
+     l += slope4;
+  }
+}
+
+void
+npd_texture_quadrilateral (NPDBone  *reference_bone,
+                           NPDBone  *current_bone,
+                           NPDImage *input_image,
+                           NPDImage *output_image)
+{
+  /* p1 are points of domain, p2 are points of codomain */
+  NPDPoint *p1 = current_bone->points;
+  NPDPoint *p2 = reference_bone->points;
+
+  NPDMatrix *A = NULL;
+  npd_new_matrix(&A);
+
+  npd_compute_affinity(&p1[0], &p1[1], &p1[2], &p2[0], &p2[1], &p2[2], A);
+  npd_texture_fill_triangle((int)p1[0].x, (int)p1[0].y, (int)p1[1].x, (int)p1[1].y, (int)p1[2].x, 
(int)p1[2].y, A, input_image, output_image);
+
+  npd_compute_affinity(&p1[0], &p1[2], &p1[3], &p2[0], &p2[2], &p2[3], A);
+  npd_texture_fill_triangle((int)p1[0].x, (int)p1[0].y, (int)p1[2].x, (int)p1[2].y, (int)p1[3].x, 
(int)p1[3].y, A, input_image, output_image);
+
+  npd_destroy_matrix(&A);
+}
+
+void
+npd_draw_texture_line (gint        x1,
+                       gint        x2,
+                       gint        y,
+                       NPDMatrix  *A,
+                       NPDImage   *input_image,
+                       NPDImage   *output_image)
+{
+  gint x, fx, fy;
+  gfloat dx, dy;
+  
+  for (x = x1; x <= x2; x++)
+    {
+      NPDPoint p, q;
+      NPDColor I0, I1, I2, I3, interpolated;
+
+      q.x = x; q.y = y;
+      npd_apply_transformation(A, &q, &p);
+
+      fx = (gint) floor(p.x);
+      fy = (gint) floor(p.y);
+      dx = p.x - floor(p.x);
+      dy = p.y - floor(p.y);
+
+      /* bilinear interpolation */
+      npd_get_pixel_color(input_image, fx, fy, &I0);
+      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);
+
+      npd_set_pixel_color (output_image, x, y, &interpolated);
+    }
+}
diff --git a/libs/npd/graphics.h b/libs/npd/graphics.h
new file mode 100644
index 0000000..d27cd5f
--- /dev/null
+++ b/libs/npd/graphics.h
@@ -0,0 +1,93 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#ifndef __NPD_GRAPHICS_H__
+#define        __NPD_GRAPHICS_H__
+
+#include "npd_common.h"
+
+struct _NPDColor {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+    unsigned char a;
+};
+
+void        npd_create_model_from_image       (NPDModel *model,
+                                               NPDImage *image,
+                                               gint      square_size);
+void        npd_create_mesh_from_image        (NPDModel *model,
+                                               gint      width,
+                                               gint      height,
+                                               gint      position_x,
+                                               gint      position_y);
+void        npd_draw_model                    (NPDModel *model,
+                                               NPDDisplay *display);
+
+gboolean    npd_load_image                    (NPDImage *image,
+                                               const char *path);
+void        npd_destroy_image                 (NPDImage *image);
+void        npd_draw_image                    (NPDImage *image);
+void        npd_texture_fill_triangle         (gint      x1,
+                                               gint      y1,
+                                               gint      x2,
+                                               gint      y2,
+                                               gint      x3,
+                                               gint      y3,
+                                               NPDMatrix *A,
+                                               NPDImage *input_image,
+                                               NPDImage *output_image);
+void        npd_texture_quadrilateral         (NPDBone  *reference_bone,
+                                               NPDBone  *current_bone,
+                                               NPDImage *input_image,
+                                               NPDImage *output_image);
+void        npd_draw_texture_line             (gint       x1,
+                                               gint       x2,
+                                               gint       y,
+                                               NPDMatrix *A,
+                                               NPDImage   *input_image,
+                                               NPDImage   *output_image);
+gint        npd_bilinear_interpolation        (gint      I0,
+                                               gint      I1,
+                                               gint      I2,
+                                               gint      I3,
+                                               gfloat    dx,
+                                               gfloat    dy);
+void        npd_bilinear_color_interpolation  (NPDColor *I0,
+                                               NPDColor *I1,
+                                               NPDColor *I2,
+                                               NPDColor *I3,
+                                               gfloat    dx,
+                                               gfloat    dy,
+                                               NPDColor *out);
+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);
+gboolean    npd_compare_colors                (NPDColor *c1,
+                                               NPDColor *c2);
+gboolean    npd_is_color_transparent          (NPDColor *color);
+gboolean    npd_init_display                  (NPDDisplay *display);
+void        npd_destroy_display               (NPDDisplay *display);
+
+#endif /*__NPD_GRAPHICS_H__ */
\ No newline at end of file
diff --git a/libs/npd/npd.h b/libs/npd/npd.h
new file mode 100644
index 0000000..ae70e59
--- /dev/null
+++ b/libs/npd/npd.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of n-point image deformation library.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2013 Marek Dvoroznak <dvoromar gmail com>
+ */
+
+#ifndef __NPD_H__
+#define        __NPD_H__
+
+#include "npd_common.h"
+#include "graphics.h"
+#include "deformation.h"
+#include "npd_math.h"
+
+#endif /* __NPD_H__ */
+
diff --git a/libs/npd/npd_common.c b/libs/npd/npd_common.c
index a79fb1a..1991491 100644
--- a/libs/npd/npd_common.c
+++ b/libs/npd/npd_common.c
@@ -236,6 +236,13 @@ npd_create_list_of_overlapping_points (NPDHiddenModel *hm)
       hm->list_of_overlapping_points[i].num_of_points = op->len;
       hm->list_of_overlapping_points[i].representative =
               hm->list_of_overlapping_points[i].points[0];
+      
+      for (j = 0; j < op->len; j++)
+        {
+          NPDPoint *p = hm->list_of_overlapping_points[i].points[j];
+          p->overlapping_points = &hm->list_of_overlapping_points[i];
+          p->counterpart->overlapping_points = &hm->list_of_overlapping_points[i];
+        }
 
       g_ptr_array_free (op, FALSE); /* we want to preserve the underlying
                                        array */
diff --git a/libs/npd/npd_common.h b/libs/npd/npd_common.h
index 27731d1..5ccadad 100644
--- a/libs/npd/npd_common.h
+++ b/libs/npd/npd_common.h
@@ -28,29 +28,38 @@ typedef struct _NPDColor    NPDColor;
 typedef struct _NPDDisplay  NPDDisplay;
 typedef struct _NPDMatrix   NPDMatrix;
 
-typedef struct
+typedef struct _NPDPoint    NPDPoint;
+typedef struct _NPDBone     NPDBone;
+typedef struct _NPDOverlappingPoints NPDOverlappingPoints;
+
+struct _NPDPoint
 {
   gfloat                x;
   gfloat                y;
   gboolean              fixed;
   gfloat               *weight;            /* reference to weight in array
                                               of weights */
-} NPDPoint;
+  gint                  index;
+  NPDBone              *current_bone;
+  NPDBone              *reference_bone;
+  NPDPoint             *counterpart;
+  NPDOverlappingPoints *overlapping_points;
+};
 
-typedef struct
+struct _NPDBone
 {
   gint                  num_of_points;
   NPDPoint             *points;            /* array of points */
   gfloat               *weights;           /* array of weights */
-} NPDBone;
+};
 
-typedef struct
+struct _NPDOverlappingPoints
 {
   gint                  num_of_points;
   NPDPoint             *representative;    /* reference to representative
                                               of cluster */
   NPDPoint            **points;            /* array of references to points */
-} NPDOverlappingPoints;
+};
 
 typedef struct
 {
diff --git a/libs/npd/npd_gegl.c b/libs/npd/npd_gegl.c
index e4f7234..f95d5d9 100644
--- a/libs/npd/npd_gegl.c
+++ b/libs/npd/npd_gegl.c
@@ -61,6 +61,6 @@ npd_apply_transformation (NPDMatrix *T,
                           NPDPoint  *dest)
 {
   gdouble x = src->x, y = src->y;
-  gegl_matrix3_transform_point (T, &x, &y);
+  gegl_matrix3_transform_point (&T->matrix, &x, &y);
   dest->x = x; dest->y = y;
 }
diff --git a/libs/npd/npd_gegl.h b/libs/npd/npd_gegl.h
index 3bb61f0..e56dbfb 100644
--- a/libs/npd/npd_gegl.h
+++ b/libs/npd/npd_gegl.h
@@ -21,7 +21,7 @@
 #define        __NPD_GEGL_H__
 
 #include "npd_math.h"
-#include <gegl/gegl-matrix.h>
+#include <gegl-matrix.h>
 
 struct _NPDMatrix
 {
diff --git a/operations/external/Makefile.am b/operations/external/Makefile.am
index b929744..1de5fec 100644
--- a/operations/external/Makefile.am
+++ b/operations/external/Makefile.am
@@ -158,5 +158,11 @@ rgbe_save_la_SOURCES = rgbe-save.c
 rgbe_save_la_CFLAGS = $(AM_CFLAGS) -I $(top_srcdir)/libs
 rgbe_save_la_LIBADD = $(op_libs) $(top_builddir)/libs/rgbe/librgbe.la
 
+# Dependencies are in our source tree
+ops += npd.la
+npd_la_SOURCES = npd.c
+npd_la_CFLAGS = $(AM_CFLAGS) -I $(top_srcdir)/libs
+npd_la_LIBADD = $(op_libs) $(top_builddir)/libs/npd/libnpd.la
+
 opdir = $(libdir)/gegl- GEGL_API_VERSION@
 op_LTLIBRARIES = $(ops)
diff --git a/operations/external/npd.c b/operations/external/npd.c
index d343730..e41cf48 100644
--- a/operations/external/npd.c
+++ b/operations/external/npd.c
@@ -20,7 +20,6 @@
 #include <glib/gi18n-lib.h>
 
 #ifdef GEGL_CHANT_PROPERTIES
-
 #else
 
 #define GEGL_CHANT_TYPE_FILTER
@@ -29,11 +28,138 @@
 #include "gegl-chant.h"
 #include <stdio.h>
 #include <math.h>
-#include "npd/npd_common.h"
+#include "npd/npd.h"
+#include "npd/npd_gegl.h"
+
+struct _NPDImage
+{
+  gint     width;
+  gint     height;
+  NPDPoint position;
+  guchar  *buffer;
+};
+
+struct _NPDDisplay
+{
+  NPDImage image;
+};
+
+typedef struct
+{
+  gboolean first_run;
+  NPDModel model;
+} NPDProperties;
+
+void npd_create_image (NPDImage   *image,
+                       GeglBuffer *gegl_buffer,
+                       const Babl *format);
+
+void
+npd_set_pixel_color (NPDImage *image,
+                     gint      x,
+                     gint      y,
+                     NPDColor *color)
+{
+  gint position = 4 * (y * image->width + x);
+  gint max = 4 * image->width * image->height;
+  
+  if (position > 0 && position < max)
+    {
+      image->buffer[position + 0] = color->r;
+      image->buffer[position + 1] = color->g;
+      image->buffer[position + 2] = color->b;
+      image->buffer[position + 3] = color->a;
+    }
+}
+
+void
+npd_get_pixel_color (NPDImage *image,
+                     gint      x,
+                     gint      y,
+                     NPDColor *color)
+{
+  gint position = 4 * (y * image->width + x);
+  gint max = 4 * image->width * image->height;
+  
+  if (position > 0 && position < max)
+    {
+      color->r = image->buffer[position + 0];
+      color->g = image->buffer[position + 1];
+      color->b = image->buffer[position + 2];
+      color->a = image->buffer[position + 3];
+    }
+  else
+    {
+      color->r = color->g = color->b = color->a = 0;
+    }
+}
+
+void
+npd_draw_model (NPDModel *model,
+                NPDDisplay *display)
+{
+  NPDHiddenModel *hidden_model = model->hidden_model;
+  NPDImage *image = model->reference_image;
+  gint i;
+
+  /* draw texture */
+  if (model->texture_visible)
+    {
+      for (i = 0; i < hidden_model->num_of_bones; i++)
+        {
+          npd_texture_quadrilateral(&hidden_model->reference_bones[i],
+                                    &hidden_model->current_bones[i],
+                                     image,
+                                    &display->image);
+        }
+    }
+}
+
+void
+npd_create_model_from_image (NPDModel *model,
+                             NPDImage *image,
+                             gint      square_size)
+{
+  npd_init_model(model);
+  model->reference_image = image;
+  model->mesh_square_size = square_size;
+    
+  npd_create_mesh_from_image(model, image->width, image->height, 0, 0);
+}
+
+void
+npd_create_image (NPDImage   *image,
+                  GeglBuffer *gegl_buffer,
+                  const Babl *format)
+{
+  guchar *buffer;
+  buffer = g_new0 (guchar, gegl_buffer_get_pixel_count (gegl_buffer) * 4);
+  gegl_buffer_get (gegl_buffer, NULL, 1.0, format, buffer, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+  image->buffer = buffer;
+  image->width = gegl_buffer_get_width (gegl_buffer);
+  image->height = gegl_buffer_get_height (gegl_buffer);
+}
+
+void
+npd_destroy_image (NPDImage *image)
+{
+  g_free(image->buffer);
+}
 
 static void
 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;
+    }
+  
   gegl_operation_set_format (operation, "input",
                              babl_format ("RGBA float"));
   gegl_operation_set_format (operation, "output",
@@ -48,7 +174,48 @@ process (GeglOperation       *operation,
          gint                 level)
 {
   GeglChantO *o      = GEGL_CHANT_PROPERTIES (operation);
-  const Babl *format = babl_format ("RGBA float");
+  const Babl *format = babl_format ("RGBA u8");
+  NPDProperties *props = o->chant_data;
+  NPDModel *model = &props->model;
+  NPDControlPoint *cp;
+  NPDPoint coord, new_coord;
+  guchar *output_buffer;
+  
+  if (props->first_run)
+    {
+      gint width, height;
+      NPDImage input_image;
+      NPDDisplay display;
+
+      npd_create_image (&input_image, input, format);
+      width = input_image.width;
+      height = input_image.height;
+
+      output_buffer = g_new0 (guchar, gegl_buffer_get_pixel_count (input) * 4);
+      display.image.width = width;
+      display.image.height = height;
+      display.image.buffer = output_buffer;
+
+      npd_create_model_from_image(model, &input_image, 20);
+      npd_create_list_of_overlapping_points (model->hidden_model);
+
+      model->display = &display;
+    }
+  else
+    {
+      output_buffer = model->display->image.buffer;
+    }
+
+  coord.x = 20; coord.y = 200;
+  new_coord.x = 100; new_coord.y = 250;
+
+  cp = npd_add_control_point (model, &coord);
+  npd_set_point_coordinates (&cp->point, &new_coord);
+  
+  npd_deform_model (model, 1000);
+  npd_draw_model (model, model->display);
+  
+  gegl_buffer_set (output, NULL, 0, format, output_buffer, GEGL_AUTO_ROWSTRIDE);
 
   return  TRUE;
 }


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