[gegl] npd: preparation for transition to RGBA float color model



commit 4437848d971d0be406bf22a17742fbf267ea8598
Author: Marek Dvoroznak <dvoromar gmail com>
Date:   Thu Aug 22 16:35:04 2013 +0200

    npd: preparation for transition to RGBA float color model

 libs/npd/graphics.c       |  364 ++++++++++++++++++++++++++------------------
 libs/npd/graphics.h       |   46 ++++--
 libs/npd/npd_common.h     |    9 +-
 operations/external/npd.c |    3 +-
 4 files changed, 254 insertions(+), 168 deletions(-)
---
diff --git a/libs/npd/graphics.c b/libs/npd/graphics.c
index 57a580c..b590996 100644
--- a/libs/npd/graphics.c
+++ b/libs/npd/graphics.c
@@ -117,22 +117,23 @@ npd_create_mesh_from_image (NPDModel *model,
             }
         }
     }
-  
+
   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);
+  g_ptr_array_free (current_bones, TRUE);
+  g_ptr_array_free (reference_bones, TRUE);
 }
 
-void npd_draw_mesh (NPDModel   *model,
-                    NPDDisplay *display)
+void
+npd_draw_mesh (NPDModel   *model,
+               NPDDisplay *display)
 {
   NPDHiddenModel *hm = model->hidden_model;
   gint i, j;
@@ -141,7 +142,7 @@ void npd_draw_mesh (NPDModel   *model,
     {
       NPDBone  *bone  = &hm->current_bones[i];
       NPDPoint *first = &bone->points[0];
-      NPDPoint *p0, *p1;
+      NPDPoint *p0, *p1 = NULL;
 
       for (j = 1; j < bone->num_of_points; j++)
         {
@@ -153,41 +154,16 @@ void npd_draw_mesh (NPDModel   *model,
     }
 }
 
-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
+npd_bilinear_interpolation (gfloat I0,
+                            gfloat I1,
+                            gfloat I2,
+                            gfloat I3,
                             gfloat dx,
                             gfloat dy)
 {
-  return floor ((I0 * (1 - dx) + I1 * dx) * (1 - dy)
-              + (I2 * (1 - dx) + I3 * dx) * dy);
+  return (I0 * (1 - dx) + I1 * dx) * (1 - dy) +
+         (I2 * (1 - dx) + I3 * dx) *      dy;
 }
 
 void
@@ -205,15 +181,15 @@ npd_bilinear_color_interpolation (NPDColor *I0,
   out->a = npd_bilinear_interpolation (I0->a, I1->a, I2->a, I3->a, dx, dy);
 }
 
-gint
-npd_blend_band (gint   src,
-                gint   dst,
+gfloat
+npd_blend_band (gfloat src,
+                gfloat dst,
                 gfloat src_alpha,
                 gfloat dst_alpha,
                 gfloat out_alpha_recip)
 {
-  return floor ((src * src_alpha +
-                 dst * dst_alpha * (1 - src_alpha)) * out_alpha_recip);
+  return (src * src_alpha +
+          dst * dst_alpha * (1 - src_alpha)) * out_alpha_recip;
 }
 
 void
@@ -221,27 +197,37 @@ 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_texture_fill_triangle (gint x1,
-                           gint y1,
-                           gint x2,
-                           gint y2,
-                           gint x3,
-                           gint y3,
+npd_texture_fill_triangle (gint       x1,
+                           gint       y1,
+                           gint       x2,
+                           gint       y2,
+                           gint       x3,
+                           gint       y3,
                            NPDMatrix *A,
-                           NPDImage *input_image,
-                           NPDImage *output_image)
+                           NPDImage  *input_image,
+                           NPDImage  *output_image,
+                           NPDSettings settings)
 {
   gint yA, yB, yC, xA, xB, xC;
   gint tmp, y;
@@ -256,57 +242,74 @@ npd_texture_fill_triangle (gint x1,
   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) {
+  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;
@@ -315,57 +318,81 @@ npd_texture_fill_triangle (gint x1,
       slope2 = slopeAC;
       slope3 = slopeAC;
       slope4 = slopeBC;
-  } else {
-      slopeAB = (gfloat) deltaXAB/deltaYAB;
+    }
+  else
+    {
+      slopeAB = (gfloat) deltaXAB / deltaYAB;
       k = xA;
       l = xA;
 
-      if (slopeAB > slopeAC) {
+      if (slopeAB > slopeAC)
+        {
           slope1 = slopeAC;
           slope2 = slopeAB;
           slope3 = slopeAC;
           slope4 = slopeBC;
-      } else {
+        }
+      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;
-  }
+        }
+    }
+
+  for (y = yA; y < yB; y++)
+    {
+      npd_draw_texture_line ((gint) round (k), (gint) round (l),
+                             y, A,
+                             input_image, output_image,
+                             settings);
+      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,
+                             settings);
+      k += slope3;
+      l += slope4;
+    }
 }
 
 void
-npd_texture_quadrilateral (NPDBone  *reference_bone,
-                           NPDBone  *current_bone,
-                           NPDImage *input_image,
-                           NPDImage *output_image)
+npd_texture_quadrilateral (NPDBone    *reference_bone,
+                           NPDBone    *current_bone,
+                           NPDImage   *input_image,
+                           NPDImage   *output_image,
+                           NPDSettings settings)
 {
   /* 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);
+  npd_new_matrix (&A);
+
+  npd_compute_affinity (&p1[0], &p1[1], &p1[2],
+                        &p2[0], &p2[1], &p2[2], A);
+  npd_texture_fill_triangle ((gint) p1[0].x, (gint) p1[0].y,
+                             (gint) p1[1].x, (gint) p1[1].y,
+                             (gint) p1[2].x, (gint) p1[2].y,
+                             A, input_image, output_image,
+                             settings);
+
+  npd_compute_affinity (&p1[0], &p1[2], &p1[3],
+                        &p2[0], &p2[2], &p2[3], A);
+  npd_texture_fill_triangle ((gint) p1[0].x, (gint) p1[0].y,
+                             (gint) p1[2].x, (gint) p1[2].y,
+                             (gint) p1[3].x, (gint) p1[3].y,
+                             A, input_image, output_image,
+                             settings);
+
+  npd_destroy_matrix (&A);
 }
 
 void
@@ -374,7 +401,8 @@ npd_draw_texture_line (gint        x1,
                        gint        y,
                        NPDMatrix  *A,
                        NPDImage   *input_image,
-                       NPDImage   *output_image)
+                       NPDImage   *output_image,
+                       NPDSettings settings)
 {
   gint x, fx, fy;
   gfloat dx, dy;
@@ -382,27 +410,65 @@ npd_draw_texture_line (gint        x1,
   for (x = x1; x <= x2; x++)
     {
       NPDPoint p, q;
-      NPDColor I0, I1, I2, I3, interpolated, dest;
+      NPDColor I0, interpolated, *final;
 
       q.x = x; q.y = y;
-      npd_apply_transformation(A, &q, &p);
+      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);
+      fx = floor (p.x);
+      fy = floor (p.y);
+
+      npd_get_pixel_color (input_image, fx, fy, &I0);
+      final = &I0;
 
       /* 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);
+      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 */
-      npd_get_pixel_color (output_image, x, y, &dest);
-      npd_blend_colors (&interpolated, &dest, &interpolated);
+      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, &interpolated);
+      npd_set_pixel_color (output_image, x, y, final);
     }
 }
+
+gboolean
+npd_compare_colors (NPDColor *c1,
+                    NPDColor *c2)
+{
+  if (npd_equal_floats (c1->r, c2->r) &&
+      npd_equal_floats (c1->g, c2->g) &&
+      npd_equal_floats (c1->b, c2->b) &&
+      npd_equal_floats (c1->a, c2->a))
+    return TRUE;
+
+  return FALSE;
+}
+
+gboolean
+npd_is_color_transparent (NPDColor *color)
+{
+  if (npd_equal_floats (color->r, 0.0) &&
+      npd_equal_floats (color->g, 0.0) &&
+      npd_equal_floats (color->b, 0.0) &&
+      npd_equal_floats (color->a, 0.0))
+    return TRUE;
+
+  return FALSE;
+}
diff --git a/libs/npd/graphics.h b/libs/npd/graphics.h
index 02d2745..b180e1c 100644
--- a/libs/npd/graphics.h
+++ b/libs/npd/graphics.h
@@ -22,13 +22,28 @@
 
 #include "npd_common.h"
 
+//#define NPD_RGBA_FLOAT
+
 struct _NPDColor {
-    unsigned char r;
-    unsigned char g;
-    unsigned char b;
-    unsigned char a;
+#ifdef NPD_RGBA_FLOAT
+  gfloat r;
+  gfloat g;
+  gfloat b;
+  gfloat a;
+#else
+  guint8 r;
+  guint8 g;
+  guint8 b;
+  guint8 a;
+#endif
 };
 
+typedef enum
+{
+  NPD_BILINEAR_INTERPOLATION = 1,
+  NPD_ALPHA_BLENDING         = 1 << 1
+} NPDSettings;
+
 void        npd_create_model_from_image       (NPDModel   *model,
                                                NPDImage   *image,
                                                gint        square_size);
@@ -54,26 +69,29 @@ void        npd_texture_fill_triangle         (gint        x1,
                                                gint        y3,
                                                NPDMatrix  *A,
                                                NPDImage   *input_image,
-                                               NPDImage   *output_image);
+                                               NPDImage   *output_image,
+                                               NPDSettings settings);
 void        npd_texture_quadrilateral         (NPDBone    *reference_bone,
                                                NPDBone    *current_bone,
                                                NPDImage   *input_image,
-                                               NPDImage   *output_image);
+                                               NPDImage   *output_image,
+                                               NPDSettings settings);
 void        npd_draw_texture_line             (gint        x1,
                                                gint        x2,
                                                gint        y,
                                                NPDMatrix  *A,
                                                NPDImage   *input_image,
-                                               NPDImage   *output_image);
+                                               NPDImage   *output_image,
+                                               NPDSettings settings);
 void      (*npd_draw_line)                    (NPDDisplay *display,
                                                gfloat      x0,
                                                gfloat      y0,
                                                gfloat      x1,
                                                gfloat      y1);
-gint        npd_bilinear_interpolation        (gint        I0,
-                                               gint        I1,
-                                               gint        I2,
-                                               gint        I3,
+gfloat      npd_bilinear_interpolation        (gfloat      I0,
+                                               gfloat      I1,
+                                               gfloat      I2,
+                                               gfloat      I3,
                                                gfloat      dx,
                                                gfloat      dy);
 void        npd_bilinear_color_interpolation  (NPDColor   *I0,
@@ -83,12 +101,12 @@ void        npd_bilinear_color_interpolation  (NPDColor   *I0,
                                                gfloat      dx,
                                                gfloat      dy,
                                                NPDColor   *out);
-gint        npd_blend_band                    (gint        src,
-                                               gint        dst,
+gfloat      npd_blend_band                    (gfloat      src,
+                                               gfloat      dst,
                                                gfloat      src_alpha,
                                                gfloat      dest_alpha,
                                                gfloat      out_alpha);
-void        npd_blend_colors                  (NPDColor   *src,
+void        npd_blend_colors                 (NPDColor   *src,
                                                NPDColor   *dst,
                                                NPDColor   *out_color);
 void      (*npd_get_pixel_color)              (NPDImage   *image,
diff --git a/libs/npd/npd_common.h b/libs/npd/npd_common.h
index bf1b20c..f4213a0 100644
--- a/libs/npd/npd_common.h
+++ b/libs/npd/npd_common.h
@@ -92,10 +92,11 @@ typedef struct
   NPDDisplay           *display;
 } NPDModel;
 
-#define npd_init(set_pixel, get_pixel, draw_line)\
-npd_set_pixel_color = set_pixel;\
-npd_get_pixel_color = get_pixel;\
-npd_draw_line       = draw_line
+#define npd_init(set_pixel, get_pixel,                                         \
+                 draw_line)                                                    \
+npd_set_pixel_color      = set_pixel;                                          \
+npd_get_pixel_color      = get_pixel;                                          \
+npd_draw_line            = draw_line;
 
 void             npd_init_model                 (NPDModel        *model);
 void             npd_destroy_hidden_model       (NPDHiddenModel  *model);
diff --git a/operations/external/npd.c b/operations/external/npd.c
index 1b700a8..c4bdec2 100644
--- a/operations/external/npd.c
+++ b/operations/external/npd.c
@@ -163,7 +163,8 @@ npd_draw_model (NPDModel   *model,
           npd_texture_quadrilateral(&hm->reference_bones[i],
                                     &hm->current_bones[i],
                                      image,
-                                    &display->image);
+                                    &display->image,
+                                     NPD_BILINEAR_INTERPOLATION | NPD_ALPHA_BLENDING);
         }
     }
   


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