[gegl] transform_generic: stupid bug gone (but code still needs refactoring)
- From: Nicolas Robidoux <nrobidoux src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] transform_generic: stupid bug gone (but code still needs refactoring)
- Date: Tue, 18 Dec 2012 17:10:12 +0000 (UTC)
commit b0cce2596a55100c5ab782296852d4346b07d302
Author: Nicolas Robidoux <nrobidoux git gnome org>
Date: Tue Dec 18 11:40:57 2012 -0500
transform_generic: stupid bug gone (but code still needs refactoring)
operations/transform/transform-core.c | 339 +++++++++++++++------------------
1 files changed, 154 insertions(+), 185 deletions(-)
---
diff --git a/operations/transform/transform-core.c b/operations/transform/transform-core.c
index 1cc2b0f..47f5480 100644
--- a/operations/transform/transform-core.c
+++ b/operations/transform/transform-core.c
@@ -573,29 +573,6 @@ gegl_transform_get_bounding_box (GeglOperation *op)
gegl_transform_bounding_box (have_points, 4, &have_rect);
- /* /\* */
- /* * 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;
}
@@ -692,22 +669,6 @@ 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,
@@ -1047,6 +1008,7 @@ transform_affine (GeglBuffer *dest,
}
}
+#if 0
static void
transform_generic (GeglBuffer *dest,
GeglBuffer *src,
@@ -1140,8 +1102,8 @@ transform_generic (GeglBuffer *dest,
}
}
}
+#endif
-#if 0
static void
transform_generic (GeglBuffer *dest,
GeglBuffer *src,
@@ -1153,7 +1115,6 @@ transform_generic (GeglBuffer *dest,
const GeglRectangle *dest_extent;
gint x,
y;
- gfloat * restrict dest_buf;
GeglMatrix3 inverse;
gdouble u_start,
@@ -1165,7 +1126,6 @@ transform_generic (GeglBuffer *dest,
const Babl *format = babl_format ("RaGaBaA float");
gint dest_pixels,
- file13 = 1,
flip_x = 1,
flip_y = 1;
@@ -1173,30 +1133,55 @@ transform_generic (GeglBuffer *dest,
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.
+ * We determine whether tile access should be "flipped".
*/
- gegl_matrix3_copy_into (&inverse, matrix);
- gegl_matrix3_invert (&inverse);
+ u_start = inverse.coeff [0][0] * ((*dest_extent).x + (gdouble) 0.5) +
+ inverse.coeff [0][1] * ((*dest_extent).y + (gdouble) 0.5) +
+ inverse.coeff [0][2];
+ v_start = inverse.coeff [1][0] * ((*dest_extent).x + (gdouble) 0.5) +
+ inverse.coeff [1][1] * ((*dest_extent).y + (gdouble) 0.5) +
+ inverse.coeff [1][2];
+ w_start = inverse.coeff [2][0] * ((*dest_extent).x + (gdouble) 0.5) +
+ inverse.coeff [2][1] * ((*dest_extent).y + (gdouble) 0.5) +
+ inverse.coeff [2][2];
+
+ u_float = u_start + inverse.coeff [0][1] * ((*dest_extent).height - (gint) 1);
+ v_float = v_start + inverse.coeff [1][1] * ((*dest_extent).height - (gint) 1);
+ w_float = w_start + inverse.coeff [2][1] * ((*dest_extent).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;
+ u_start = u_float;
+ v_start = v_float;
+ w_start = w_float;
+ }
+
+ /*
+ * Repeat in the horizontal direction.
+ */
+ u_float = u_start + inverse.coeff [0][0] * ((*dest_extent).width - (gint) 1);
+ v_float = v_start + inverse.coeff [1][0] * ((*dest_extent).width - (gint) 1);
+ w_float = w_start + inverse.coeff [2][0] * ((*dest_extent).width - (gint) 1);
- 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) )
+ if ((u_float + v_float)/w_float < (u_start + v_start)/w_start)
{
- file13 = (gint) 1;
+ flip_x = (gint) -1;
+ /*
+ * Move the start to the previously last pixel of the
+ * scanline.
+ */
+ u_start = u_float;
+ v_start = v_float;
+ w_start = w_float;
}
+ gegl_matrix3_copy_into (&inverse, matrix);
+ gegl_matrix3_invert (&inverse);
+
i = gegl_buffer_iterator_new (dest,
dest_extent,
level,
@@ -1208,145 +1193,129 @@ transform_generic (GeglBuffer *dest,
{
GeglRectangle *roi = &i->roi[0];
- dest_buf = (gfloat *)i->data[0];
+ gfloat * restrict dest_buf = (gfloat *)i->data[0];
+
+ /* /\* */
+ /* * 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. */
+ /* *\/ */
+ /* if (file13) */
+ /* { */
+ /* memset (dest_buf, '\0', sizeof(dest_buf)); */
+ /* } */
+ /* else */
+ /* { */
+ gfloat * restrict dest_ptr = dest_buf;
/*
- * 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.
+ * 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.
*/
- if (file13)
- {
- memset (dest_buf, '\0', sizeof(dest_buf));
- }
- else
- {
- gfloat * restrict dest_ptr = dest_buf;
+ /*
+ * 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 (flip_y - (gint) 1)
+ {
/*
- * 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.
+ * Move the start to the previously last scanline.
*/
- 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;
- }
+ 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);
+ 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;
- }
+ if (flip_x - (gint) 1)
+ {
+ 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 (y = roi->height; y--;)
+ for (x = roi->width; x--;)
{
- u_float = u_start;
- v_float = v_start;
- w_float = w_start;
+ GeglMatrix2 inverse_jacobian;
- 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;
+ 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;
- u_start += flip_y * inverse.coeff [0][1];
- v_start += flip_y * inverse.coeff [1][1];
- w_start += flip_y * inverse.coeff [2][1];
+ 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];
+ }
}
}
-#endif
/*
* Use to determine if key transform matrix coefficients are close
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]