[gegl] put 0s in transform_generic's output



commit b7970825df887eedb89d0212551c2ced9f286ff7
Author: Nicolas Robidoux <nrobidoux git gnome org>
Date:   Mon Dec 17 21:29:58 2012 -0500

    put 0s in transform_generic's output

 operations/transform/transform-core.c |  375 ++++++++++++++++++---------------
 1 files changed, 207 insertions(+), 168 deletions(-)
---
diff --git a/operations/transform/transform-core.c b/operations/transform/transform-core.c
index 6b8115a..2d254e8 100644
--- a/operations/transform/transform-core.c
+++ b/operations/transform/transform-core.c
@@ -197,9 +197,6 @@ op_transform_class_init (OpTransformClass *klass)
                                      0.,
                                      G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
   g_object_class_install_property (gobject_class, PROP_FILTER,
-  /*
-   * Lanczos is gone.
-   */
                                    g_param_spec_string (
                                      "filter",
                                      _("Filter"),
@@ -213,6 +210,9 @@ op_transform_class_init (OpTransformClass *klass)
                                      _("Hard edges"),
                                      FALSE,
                                      G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+  /*
+   * Lanczos is gone. This is lint.
+   */
   g_object_class_install_property (gobject_class, PROP_LANCZOS_WIDTH,
                                    g_param_spec_int (
                                      "lanczos-width",
@@ -432,8 +432,8 @@ gegl_transform_is_composite_node (OpTransform *transform)
   GeglOperation *op = GEGL_OPERATION (transform);
   GeglOperation *source;
 
-  connections = gegl_pad_get_connections (gegl_node_get_pad (op->node,
-                                                             "input"));
+  connections = gegl_pad_get_connections (gegl_node_get_pad (op->node,"input"));
+
   if (! connections)
     return FALSE;
 
@@ -466,8 +466,7 @@ static GeglRectangle
 gegl_transform_get_bounding_box (GeglOperation *op)
 {
   OpTransform  *transform = OP_TRANSFORM (op);
-  GeglMatrix3   matrix,
-                inverse;
+  GeglMatrix3   matrix;
   GeglRectangle in_rect   = {0,0,0,0},
                 have_rect;
   gdouble       have_points [8];
@@ -530,8 +529,20 @@ gegl_transform_get_bounding_box (GeglOperation *op)
       /*
        * Does "- (gint) 1" interact badly with {*,*,0,0}?
        */
-      in_rect.width  += context_rect.width  - (gint) 1;
-      in_rect.height += context_rect.height - (gint) 1;
+      in_rect.width  +=	(
+	 		  context_rect.width  - (gint) 1 > (gint) 0
+			  ?
+			  context_rect.width  - (gint) 1
+			  :
+			  (gint) 0
+			);
+      in_rect.height += (
+			  context_rect.height - (gint) 1 > (gint) 0
+			  ?
+			  context_rect.height - (gint) 1
+			  :
+			  (gint) 0
+			);
     }
 #endif
 
@@ -562,28 +573,28 @@ gegl_transform_get_bounding_box (GeglOperation *op)
 
   gegl_transform_bounding_box (have_points, 4, &have_rect);
 
-  gegl_transform_create_composite_matrix (transform, &inverse);
-  gegl_matrix3_invert (&inverse);
-
-  /*
-   * If there are vanishing or negative denominators within the area
-   * of the have_rect, return a null rectangle.
-   */
-  if ( (inverse.coeff [2][0] * have_rect.x +
-	inverse.coeff [2][1] * have_rect.y +
-	inverse.coeff [2][2] <= (gdouble) 1.e-4) ||
-       (inverse.coeff [2][0] * (have_rect.x + have_rect.width) +
-	inverse.coeff [2][1] * have_rect.y +
-	inverse.coeff [2][2] <= (gdouble) 1.e-4) ||
-       (inverse.coeff [2][0] * have_rect.x +
-	inverse.coeff [2][1] * (have_rect.y + have_rect.height) +
-	inverse.coeff [2][2] <= (gdouble) 1.e-4) ||
-       (inverse.coeff [2][0] * (have_rect.x + have_rect.width) +
-	inverse.coeff [2][1] * (have_rect.y + have_rect.height) +
-	inverse.coeff [2][2] <= (gdouble) 1.e-4) )
-    {
-      return (GeglRectangle) {0,0,0,0};
-    }
+  /* /\* */
+  /*  * If there are vanishing or negative denominators within the area */
+  /*  * of the have_rect, return a null rectangle. */
+  /*  *\/ */
+  /* gegl_transform_create_composite_matrix (transform, &inverse); */
+  /* gegl_matrix3_invert (&inverse); */
+
+  /* if ( (inverse.coeff [2][0] * have_rect.x + */
+  /* 	inverse.coeff [2][1] * have_rect.y + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) || */
+  /*      (inverse.coeff [2][0] * (have_rect.x + have_rect.width) + */
+  /* 	inverse.coeff [2][1] * have_rect.y + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) || */
+  /*      (inverse.coeff [2][0] * have_rect.x + */
+  /* 	inverse.coeff [2][1] * (have_rect.y + have_rect.height) + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) || */
+  /*      (inverse.coeff [2][0] * (have_rect.x + have_rect.width) + */
+  /* 	inverse.coeff [2][1] * (have_rect.y + have_rect.height) + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) ) */
+  /*   { */
+  /*     return (GeglRectangle) {0,0,0,0}; */
+  /*   } */
 
   return have_rect;
 }
@@ -681,6 +692,22 @@ gegl_transform_get_required_for_output (GeglOperation       *op,
   need_points [6] = need_points [0];
   need_points [7] = need_points [5];
 
+  /* if ( (inverse.coeff [2][0] *  requested_rect.x + */
+  /* 	inverse.coeff [2][1] *  requested_rect.y + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) || */
+  /*      (inverse.coeff [2][0] * (requested_rect.x + requested_rect.width) + */
+  /* 	inverse.coeff [2][1] *  requested_rect.y + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) || */
+  /*      (inverse.coeff [2][0] *  requested_rect.x + */
+  /* 	inverse.coeff [2][1] * (requested_rect.y + requested_rect.height) + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) || */
+  /*      (inverse.coeff [2][0] * (requested_rect.x + requested_rect.width) + */
+  /* 	inverse.coeff [2][1] * (requested_rect.y + requested_rect.height) + */
+  /* 	inverse.coeff [2][2] <= (gdouble) 1.e-2) ) */
+  /*   { */
+  /*     return (GeglRectangle) {0,0,0,0}; */
+  /*   } */
+
   for (i = 0; i < 8; i += 2)
     gegl_matrix3_transform_point (&inverse,
                                   need_points + i,
@@ -1043,12 +1070,38 @@ transform_generic (GeglBuffer  *dest,
 
   const Babl          *format = babl_format ("RaGaBaA float");
   gint                 dest_pixels,
+                       file13 = 1,
                        flip_x = 1,
                        flip_y = 1;
 
   g_object_get (dest, "pixels", &dest_pixels, NULL);
   dest_extent = gegl_buffer_get_extent (dest);
 
+  /*
+   * First, determine if there are vanishing or negative denominators
+   * anywhere within the four outer corners of the corner pixels. If
+   * these locations themselves are "safe", the whole thing is
+   * safe. If unsafe, fill the whole thing with transparent black.
+   */
+  gegl_matrix3_copy_into (&inverse, matrix);
+  gegl_matrix3_invert (&inverse);
+
+  if ( (inverse.coeff [2][0] * (*dest_extent).x +
+	inverse.coeff [2][1] * (*dest_extent).y +
+	inverse.coeff [2][2] < (gdouble) 0.9) ||
+       (inverse.coeff [2][0] * ((*dest_extent).x + (*dest_extent).width) +
+	inverse.coeff [2][1] * (*dest_extent).y +
+	inverse.coeff [2][2] < (gdouble) 0.9) ||
+       (inverse.coeff [2][0] * (*dest_extent).x +
+	inverse.coeff [2][1] * ((*dest_extent).y + (*dest_extent).height) +
+	inverse.coeff [2][2] < (gdouble) 0.9) ||
+       (inverse.coeff [2][0] * ((*dest_extent).x + (*dest_extent).width) +
+	inverse.coeff [2][1] * ((*dest_extent).y + (*dest_extent).height) +
+	inverse.coeff [2][2] < (gdouble) 0.9) )
+    {
+      file13 = (gint) 1;
+    }
+
   i = gegl_buffer_iterator_new (dest,
                                 dest_extent,
                                 level,
@@ -1056,15 +1109,10 @@ transform_generic (GeglBuffer  *dest,
                                 GEGL_BUFFER_WRITE,
                                 GEGL_ABYSS_NONE);
 
-  gegl_matrix3_copy_into (&inverse, matrix);
-  gegl_matrix3_invert (&inverse);
-
   while (gegl_buffer_iterator_next (i))
     {
       GeglRectangle *roi = &i->roi[0];
 
-      gfloat *dest_ptr;
-
       dest_buf = (gfloat *)i->data[0];
 
       /*
@@ -1074,141 +1122,132 @@ transform_generic (GeglBuffer  *dest,
        * 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) 1.e-2) ||
-	   (inverse.coeff [2][0] * (roi->x + roi->width) +
-	    inverse.coeff [2][1] * roi->y +
-	    inverse.coeff [2][2] <= (gdouble) 1.e-2) ||
-	   (inverse.coeff [2][0] * roi->x +
-	    inverse.coeff [2][1] * (roi->y + roi->height) +
-	    inverse.coeff [2][2] <= (gdouble) 1.e-2) ||
-	   (inverse.coeff [2][0] * (roi->x + roi->width) +
-	    inverse.coeff [2][1] * (roi->y + roi->height) +
-	    inverse.coeff [2][2] <= (gdouble) 1.e-2) )
+      if (file13)
 	{
 	  memset (dest_buf, '\0', sizeof(dest_buf));
-	  return;
 	}
-
-      dest_ptr = dest_buf;
-
-      /*
-       * 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
-       * there is more elbow room at the bottom and right than at the
-       * top and left, explained in the transform_affine function. It
-       * is not as foolproof because perspective transformations
-       * change the orientation of scanlines, and consequently what's
-       * good at the bottom may not be best at the top. On the other
-       * hand, the ROIs are generally small, so it's likely that
-       * what's good for the goose is good for the gander.
-       */
-      /*
-       * Find out if we should flip things in the vertical
-       * direction. Flipping in the horizontal direction at the end
-       * ensures that the very first filled scanline will be done in
-       * the optimal order, even though the last one may not be. So,
-       * "fixing" the horizontal direction last can be seen as a form
-       * of greediness.
-       */
-      /*
-       * Compute the positions of the pre-images of the top left and
-       * bottom left pixels of the ROI.
-       */
-      u_start = inverse.coeff [0][0] * (roi->x + (gdouble) 0.5) +
-                inverse.coeff [0][1] * (roi->y + (gdouble) 0.5) +
-                inverse.coeff [0][2];
-      v_start = inverse.coeff [1][0] * (roi->x + (gdouble) 0.5)  +
-                inverse.coeff [1][1] * (roi->y + (gdouble) 0.5)  +
-                inverse.coeff [1][2];
-      w_start = inverse.coeff [2][0] * (roi->x + (gdouble) 0.5)  +
-                inverse.coeff [2][1] * (roi->y + (gdouble) 0.5)  +
-                inverse.coeff [2][2];
-
-      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);
-
-      if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
-        {
-          /*
-           * Set the "change of direction" sign.
-           */
-          flip_y = (gint) -1;
-          /*
-           * Move the start to the previously last scanline.
-           */
-          dest_ptr += (gint) 4 * (roi->height - (gint) 1) * roi->width;
-          u_start = u_float;
-          v_start = v_float;
-          w_start = w_float;
-        }
-
-      /*
-       * Repeat in the horizontal direction, using the first scanline
-       * selected by the vertical flip.
-       */
-      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);
-
-      if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
-        {
-          flip_x = (gint) -1;
-          /*
-           * Move the start to the previously last pixel of the
-           * scanline.
-           */
-          dest_ptr += (gint) 4 * (roi->width  - (gint) 1);
-          u_start = u_float;
-          v_start = v_float;
-          w_start = w_float;
-        }
-
-      for (y = roi->height; y--;)
-        {
-          u_float = u_start;
-          v_float = v_start;
-          w_float = w_start;
-
-          for (x = roi->width; x--;)
-            {
-              GeglMatrix2 inverse_jacobian;
-
-              gdouble w_recip = (gdouble) 1.0 / w_float;
-              gdouble u = u_float * w_recip;
-              gdouble v = v_float * w_recip;
-
-              inverse_jacobian.coeff [0][0] =
-                (inverse.coeff [0][0] - inverse.coeff [2][0] * u) * w_recip;
-              inverse_jacobian.coeff [0][1] =
-                (inverse.coeff [0][1] - inverse.coeff [2][1] * u) * w_recip;
-              inverse_jacobian.coeff [1][0] =
-                (inverse.coeff [1][0] - inverse.coeff [2][0] * v) * w_recip;
-              inverse_jacobian.coeff [1][1] =
-                (inverse.coeff [1][1] - inverse.coeff [2][1] * v) * w_recip;
-
-              gegl_sampler_get (sampler,
-                                u,
-                                v,
-                                &inverse_jacobian,
-                                dest_ptr,
-                                GEGL_ABYSS_NONE);
-
-              dest_ptr += flip_x * (gint) 4;
-
-              u_float += flip_x * inverse.coeff [0][0];
-              v_float += flip_x * inverse.coeff [1][0];
-              w_float += flip_x * inverse.coeff [2][0];
-            }
-
-          dest_ptr += (gint) 4 * (flip_y - flip_x) * roi->width;
-
-          u_start += flip_y * inverse.coeff [0][1];
-          v_start += flip_y * inverse.coeff [1][1];
-          w_start += flip_y * inverse.coeff [2][1];
+      else
+	{
+	  gfloat * restrict dest_ptr = dest_buf;
+
+	  /*
+	   * 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 there is more elbow room at the bottom and
+	   * right than at the top and left, explained in the
+	   * transform_affine function. It is not as foolproof because
+	   * perspective transformations change the orientation of
+	   * scanlines, and consequently what's good at the bottom may
+	   * not be best at the top. On the other hand, the ROIs are
+	   * generally small, so it's likely that what's good for the
+	   * goose is good for the gander.
+	   */
+	  /*
+	   * Find out if we should flip things in the vertical
+	   * direction. Flipping in the horizontal direction at the
+	   * end ensures that the very first filled scanline will be
+	   * done in the optimal order, even though the last one may
+	   * not be. So, "fixing" the horizontal direction last can be
+	   * seen as a form of greediness.
+	   */
+	  /*
+	   * Compute the positions of the pre-images of the top left and
+	   * bottom left pixels of the ROI.
+	   */
+	  u_start = inverse.coeff [0][0] * (roi->x + (gdouble) 0.5) +
+	            inverse.coeff [0][1] * (roi->y + (gdouble) 0.5) +
+                    inverse.coeff [0][2];
+	  v_start = inverse.coeff [1][0] * (roi->x + (gdouble) 0.5)  +
+                    inverse.coeff [1][1] * (roi->y + (gdouble) 0.5)  +
+                    inverse.coeff [1][2];
+	  w_start = inverse.coeff [2][0] * (roi->x + (gdouble) 0.5)  +
+	            inverse.coeff [2][1] * (roi->y + (gdouble) 0.5)  +
+	            inverse.coeff [2][2];
+
+	  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);
+
+	  if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
+	    {
+	      /*
+	       * Set the "change of direction" sign.
+	       */
+	      flip_y = (gint) -1;
+	      /*
+	       * Move the start to the previously last scanline.
+	       */
+	      dest_ptr += (gint) 4 * (roi->height - (gint) 1) * roi->width;
+	      u_start = u_float;
+	      v_start = v_float;
+	      w_start = w_float;
+	    }
+
+	  /*
+	   * Repeat in the horizontal direction, using the first
+	   * scanline selected by the vertical flip.
+	   */
+	  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);
+
+	  if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
+	    {
+	      flip_x = (gint) -1;
+	      /*
+	       * Move the start to the previously last pixel of the
+	       * scanline.
+	       */
+	      dest_ptr += (gint) 4 * (roi->width  - (gint) 1);
+	      u_start = u_float;
+	      v_start = v_float;
+	      w_start = w_float;
+	    }
+	  
+	  for (y = roi->height; y--;)
+	    {
+	      u_float = u_start;
+	      v_float = v_start;
+	      w_float = w_start;
+	      
+	      for (x = roi->width; x--;)
+		{
+		  GeglMatrix2 inverse_jacobian;
+
+		  gdouble w_recip = (gdouble) 1.0 / w_float;
+		  gdouble u = u_float * w_recip;
+		  gdouble v = v_float * w_recip;
+		  
+		  inverse_jacobian.coeff [0][0] =
+		    (inverse.coeff [0][0] - inverse.coeff [2][0] * u) * w_recip;
+		  inverse_jacobian.coeff [0][1] =
+		    (inverse.coeff [0][1] - inverse.coeff [2][1] * u) * w_recip;
+		  inverse_jacobian.coeff [1][0] =
+		    (inverse.coeff [1][0] - inverse.coeff [2][0] * v) * w_recip;
+		  inverse_jacobian.coeff [1][1] =
+		    (inverse.coeff [1][1] - inverse.coeff [2][1] * v) * w_recip;
+		  
+		  gegl_sampler_get (sampler,
+				    u,
+				    v,
+				    &inverse_jacobian,
+				    dest_ptr,
+				    GEGL_ABYSS_NONE);
+
+		  dest_ptr += flip_x * (gint) 4;
+		  
+		  u_float += flip_x * inverse.coeff [0][0];
+		  v_float += flip_x * inverse.coeff [1][0];
+		  w_float += flip_x * inverse.coeff [2][0];
+		}
+
+	      dest_ptr += (gint) 4 * (flip_y - flip_x) * roi->width;
+	      
+	      u_start += flip_y * inverse.coeff [0][1];
+	      v_start += flip_y * inverse.coeff [1][1];
+	      w_start += flip_y * inverse.coeff [2][1];
+	    }
         }
     }
 }



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