[gegl] transform-core: general transform performed left to right and top to bottom in input space (most of
- From: Nicolas Robidoux <nrobidoux src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] transform-core: general transform performed left to right and top to bottom in input space (most of
- Date: Wed, 12 Dec 2012 20:40:33 +0000 (UTC)
commit 700650ec7363bf3881cb1bf7b27f42752c329338
Author: Nicolas Robidoux <nrobidoux git gnome org>
Date: Wed Dec 12 14:42:08 2012 -0500
transform-core: general transform performed left to right and top to bottom in input space (most of the time)
operations/transform/transform-core.c | 90 ++++++++++++++++++++++++++++----
1 files changed, 78 insertions(+), 12 deletions(-)
---
diff --git a/operations/transform/transform-core.c b/operations/transform/transform-core.c
index 1fae30c..31d2ce7 100644
--- a/operations/transform/transform-core.c
+++ b/operations/transform/transform-core.c
@@ -1014,7 +1014,9 @@ transform_generic (GeglBuffer *dest,
v_float,
w_float;
const Babl *format = babl_format ("RaGaBaA float");
- gint dest_pixels;
+ gint dest_pixels,
+ flip_x = 1,
+ flip_y = 1;
g_object_get (dest, "pixels", &dest_pixels, NULL);
dest_extent = gegl_buffer_get_extent (dest);
@@ -1026,17 +1028,42 @@ 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];
dest_buf = (gfloat *)i->data[0];
- gegl_matrix3_copy_into (&inverse, matrix);
- gegl_matrix3_invert (&inverse);
-
+ /*
+ * 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 the "what's good for
+ * the gander is not good for the goose" is unlikely to happen
+ * very often.
+ */
+ /*
+ * 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][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) +
@@ -1045,6 +1072,44 @@ transform_generic (GeglBuffer *dest,
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":
+ */
+ flip_y = (gint) -1;
+ /*
+ * Move the start to the previously last scanline.
+ */
+ 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.
+ */
+ u_start = u_float;
+ v_start = v_float;
+ w_start = w_float;
+ }
+
for (dest_ptr = dest_buf, y = roi->height; y--;)
{
u_float = u_start;
@@ -1073,16 +1138,17 @@ transform_generic (GeglBuffer *dest,
&inverse_jacobian,
dest_ptr,
GEGL_ABYSS_NONE);
- dest_ptr+=4;
- u_float += inverse.coeff [0][0];
- v_float += inverse.coeff [1][0];
- w_float += inverse.coeff [2][0];
+ dest_ptr += 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];
}
- u_start += inverse.coeff [0][1];
- v_start += inverse.coeff [1][1];
- w_start += inverse.coeff [2][1];
+ 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]