[gegl] transform-core: If there is a vanishing or negative denominator within a buffer tile, fill with tran



commit 50b0d57db9a257d75b9d7be0b1f296b360901713
Author: Nicolas Robidoux <nrobidoux git gnome org>
Date:   Sun Dec 16 23:40:11 2012 -0500

    transform-core: If there is a vanishing or negative denominator within a buffer tile, fill with transparent black

 gegl/gegl-matrix.c                    |   14 +--------
 operations/transform/transform-core.c |   49 ++++++++++++++++++---------------
 2 files changed, 29 insertions(+), 34 deletions(-)
---
diff --git a/gegl/gegl-matrix.c b/gegl/gegl-matrix.c
index e813391..48a455e 100644
--- a/gegl/gegl-matrix.c
+++ b/gegl/gegl-matrix.c
@@ -219,18 +219,8 @@ gegl_matrix3_transform_point (GeglMatrix3 *matrix,
   
   w = (*x * matrix->coeff [2][0] + *y * matrix->coeff [2][1] + matrix->coeff [2][2]);
 
-  /*
-   * Attempt at making near degenerate cases be handled somewhat
-   * gracefully: Set a floor, above 0, for w.
-   */
-#define PERSPECTIVE_TRANSFORM_EPSILON ((gdouble) 1.e-4)
-#define CLAMP_PERSPECTIVE_TRANSFORM(w) \
-  ( (w) > PERSPECTIVE_TRANSFORM_EPSILON ? (w) : PERSPECTIVE_TRANSFORM_EPSILON )
-
-  cw = CLAMP_PERSPECTIVE_TRANSFORM(w);
-
-  xp = (*x * matrix->coeff [0][0] + *y * matrix->coeff [0][1] + matrix->coeff [0][2]) / cw;
-  yp = (*x * matrix->coeff [1][0] + *y * matrix->coeff [1][1] + matrix->coeff [1][2]) / cw;
+  xp = (*x * matrix->coeff [0][0] + *y * matrix->coeff [0][1] + matrix->coeff [0][2]) / w;
+  yp = (*x * matrix->coeff [1][0] + *y * matrix->coeff [1][1] + matrix->coeff [1][2]) / w;
 
   *x = xp;
   *y = yp;
diff --git a/operations/transform/transform-core.c b/operations/transform/transform-core.c
index 1240a64..899645c 100644
--- a/operations/transform/transform-core.c
+++ b/operations/transform/transform-core.c
@@ -1012,11 +1012,9 @@ transform_generic (GeglBuffer  *dest,
   gdouble              u_start,
                        v_start,
                        w_start,
-                       cw_start,
                        u_float,
                        v_float,
-                       w_float,
-                       cw_float;
+                       w_float;
 
   const Babl          *format = babl_format ("RaGaBaA float");
   gint                 dest_pixels,
@@ -1045,6 +1043,29 @@ transform_generic (GeglBuffer  *dest,
       dest_ptr = dest_buf;
 
       /*
+       * First, determine if there are vanishing denominators anywhere
+       * within the four corners of the corner pixels. If the four
+       * corners themselves are "safe", the whole thing is safe. If
+       * unsafe, fill the whole thing with transparent black.
+       */
+      if ( (inverse.coeff [2][0] * roi->x +
+	    inverse.coeff [2][1] * roi->y +
+	    inverse.coeff [2][2] <= (gdouble) 0.) ||
+	   (inverse.coeff [2][0] * (roi->x + roi->width) +
+	    inverse.coeff [2][1] * roi->y +
+	    inverse.coeff [2][2] <= (gdouble) 0.) ||
+	   (inverse.coeff [2][0] * roi->x +
+	    inverse.coeff [2][1] * (roi->y + roi->height) +
+	    inverse.coeff [2][2] <= (gdouble) 0.) ||
+	   (inverse.coeff [2][0] * (roi->x + roi->width) +
+	    inverse.coeff [2][1] * (roi->y + roi->height) +
+	    inverse.coeff [2][2] <= (gdouble) 0.) )
+	{
+	  memset (dest_buf, 0x00, (gint) 4 * roi->width * roi->height);
+	  return;
+	}
+
+      /*
        * This code uses a variant of the (novel?) method of ensuring
        * that scanlines stay, as much as possible, within an input
        * "tile", given that these square "tiles" are biased so that
@@ -1078,21 +1099,11 @@ transform_generic (GeglBuffer  *dest,
                 inverse.coeff [2][1] * (roi->y + (gdouble) 0.5)  +
                 inverse.coeff [2][2];
 
-/*
- * Attempt at making near degenerate cases be handled somewhat
- * gracefully: Set a floor, above 0, for w.
- */
-#define PERSPECTIVE_TRANSFORM_EPSILON ((gdouble) 1.e-5)
-#define CLAMP_PERSPECTIVE_TRANSFORM(w) \
-  ( (w) > PERSPECTIVE_TRANSFORM_EPSILON ? (w) : PERSPECTIVE_TRANSFORM_EPSILON )
-
-      cw_start = CLAMP_PERSPECTIVE_TRANSFORM( w_start );
       u_float = u_start + inverse.coeff [0][1] * (roi->height - (gint) 1);
       v_float = v_start + inverse.coeff [1][1] * (roi->height - (gint) 1);
       w_float = w_start + inverse.coeff [2][1] * (roi->height - (gint) 1);
-      cw_float = CLAMP_PERSPECTIVE_TRANSFORM( w_float );
 
-      if ((u_float + v_float)/cw_float < (u_start + v_start)/cw_start)
+      if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
         {
           /*
            * Set the "change of direction" sign.
@@ -1105,7 +1116,6 @@ transform_generic (GeglBuffer  *dest,
           u_start = u_float;
           v_start = v_float;
           w_start = w_float;
-	  cw_start = cw_float;
         }
 
       /*
@@ -1115,9 +1125,8 @@ transform_generic (GeglBuffer  *dest,
       u_float = u_start + inverse.coeff [0][0] * (roi->width  - (gint) 1);
       v_float = v_start + inverse.coeff [1][0] * (roi->width  - (gint) 1);
       w_float = w_start + inverse.coeff [2][0] * (roi->width  - (gint) 1);
-      cw_float = CLAMP_PERSPECTIVE_TRANSFORM( w_float );
 
-      if ((u_float + v_float)/cw_float < (u_start + v_start)/cw_start)
+      if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
         {
           flip_x = (gint) -1;
           /*
@@ -1128,7 +1137,6 @@ transform_generic (GeglBuffer  *dest,
           u_start = u_float;
           v_start = v_float;
           w_start = w_float;
-	  cw_start = cw_float;
         }
 
       for (y = roi->height; y--;)
@@ -1136,13 +1144,12 @@ transform_generic (GeglBuffer  *dest,
           u_float = u_start;
           v_float = v_start;
           w_float = w_start;
-	  cw_float = cw_start;
 
           for (x = roi->width; x--;)
             {
               GeglMatrix2 inverse_jacobian;
 
-              gdouble w_recip = (gdouble) 1.0 / cw_float;
+              gdouble w_recip = (gdouble) 1.0 / w_float;
               gdouble u = u_float * w_recip;
               gdouble v = v_float * w_recip;
 
@@ -1167,7 +1174,6 @@ transform_generic (GeglBuffer  *dest,
               u_float += flip_x * inverse.coeff [0][0];
               v_float += flip_x * inverse.coeff [1][0];
               w_float += flip_x * inverse.coeff [2][0];
-	      cw_float = CLAMP_PERSPECTIVE_TRANSFORM( w_float );
             }
 
           dest_ptr += (gint) 4 * (flip_y - flip_x) * roi->width;
@@ -1175,7 +1181,6 @@ transform_generic (GeglBuffer  *dest,
           u_start += flip_y * inverse.coeff [0][1];
           v_start += flip_y * inverse.coeff [1][1];
           w_start += flip_y * inverse.coeff [2][1];
-	  cw_start = CLAMP_PERSPECTIVE_TRANSFORM( w_start );
         }
     }
 }



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