[gegl] warp: improve abyss sampling... again
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] warp: improve abyss sampling... again
- Date: Mon, 22 May 2017 20:06:07 +0000 (UTC)
commit a4e9fe8443313d0fb1b9bab4eb869e4113681dbc
Author: Ell <ell_se yahoo com>
Date: Mon May 22 14:51:46 2017 -0400
warp: improve abyss sampling... again
Instead of sampling out-of-bounds pixels as (0, 0) vectors, clamp
the sample coordinates to the input extent. This avoids
discontinuity in the displacement vector field.
operations/common/warp.c | 132 ++++++++++++++++++++--------------------------
1 files changed, 58 insertions(+), 74 deletions(-)
---
diff --git a/operations/common/warp.c b/operations/common/warp.c
index c7b9be8..ea3ddd1 100644
--- a/operations/common/warp.c
+++ b/operations/common/warp.c
@@ -379,7 +379,6 @@ stamp (GeglProperties *o,
gfloat *srcbuf,
gint srcbuf_stride,
const GeglRectangle *srcbuf_extent,
- const GeglRectangle *srcbuf_clip,
gfloat x,
gfloat y)
{
@@ -409,12 +408,6 @@ stamp (GeglProperties *o,
if (strength == 0.0f)
return; /* nop */
- /* Shift the coordiantes so that we work relative to the top-left corner of
- * the source buffer.
- */
- x -= srcbuf_extent->x;
- y -= srcbuf_extent->y;
-
area.x = floor (x - o->size / 2.0);
area.y = floor (y - o->size / 2.0);
area.width = ceil (x + o->size / 2.0);
@@ -422,28 +415,31 @@ stamp (GeglProperties *o,
area.width -= area.x;
area.height -= area.y;
- if (! gegl_rectangle_intersect (&area, &area, srcbuf_clip))
+ if (! gegl_rectangle_intersect (&area, &area, srcbuf_extent))
return;
- /* Shift the coordiantes so that we work relative to the top-left corner of
+ /* Shift the coordiantes so that they're relative to the top-left corner of
* the stamped area.
*/
x -= area.x;
y -= area.y;
+ /* Shift the stamped area so that it's relative to the top-left corner of the
+ * source buffer.
+ */
+ area.x -= srcbuf_extent->x;
+ area.y -= srcbuf_extent->y;
+
/* Align the source buffer with the stamped area */
srcbuf += srcbuf_stride * area.y + 2 * area.x;
/* Calculate the sample bounds. We clamp the coordinates of pixels sampled
- * from the source buffer to these limits. Note that the source buffer is
- * padded with a 2-pixel-wide border of (0, 0) vectors, so that out-of-bounds
- * pixels, and the pixels adjacent to them, if they're also out-of-bounds,
- * are sampled as (0, 0).
+ * from the source buffer to these limits.
*/
sample_min_x = -area.x;
- sample_max_x = -area.x + srcbuf_clip->x + srcbuf_clip->width;
+ sample_max_x = -area.x + srcbuf_extent->width - 1;
sample_min_y = -area.y;
- sample_max_y = -area.y + srcbuf_clip->y + srcbuf_clip->height;
+ sample_max_y = -area.y + srcbuf_extent->height - 1;
/* If needed, compute the mean deformation */
if (o->behavior == GEGL_WARP_BEHAVIOR_SMOOTH)
@@ -575,11 +571,32 @@ stamp (GeglProperties *o,
dx += x_iter;
dy += y_iter;
- /* clamp the sample coordinates to the sample bounds. this takes
- * care of sampling out-of-bounds pixels.
- */
- dx = CLAMP (dx, sample_min_x, sample_max_x);
- dy = CLAMP (dy, sample_min_y, sample_max_y);
+ /* clamp the sampled coordinates to the sample bounds */
+ if (dx < sample_min_x || dx >= sample_max_x ||
+ dy < sample_min_y || dy >= sample_max_y)
+ {
+ if (dx < sample_min_x)
+ {
+ dx = sample_min_x;
+ weight_x = 0.0f;
+ }
+ else if (dx >= sample_max_x)
+ {
+ dx = sample_max_x;
+ weight_x = 0.0f;
+ }
+
+ if (dy < sample_min_y)
+ {
+ dy = sample_min_y;
+ weight_y = 0.0f;
+ }
+ else if (dy >= sample_max_y)
+ {
+ dy = sample_max_y;
+ weight_y = 0.0f;
+ }
+ }
srcptr = srcbuf + srcbuf_stride * dy + 2 * dx;
@@ -643,10 +660,8 @@ process (GeglOperation *operation,
gfloat *srcbuf;
gint srcbuf_stride;
+ gint srcbuf_padding;
GeglRectangle srcbuf_extent;
- GeglRectangle srcbuf_clip;
-
- gfloat *srcbuf_ptr;
GeglPathPoint prev, next, lerp;
GeglPathList *event;
@@ -727,55 +742,31 @@ process (GeglOperation *operation,
&srcbuf_extent,
gegl_buffer_get_extent (priv->buffer)))
{
- /* we pad the source buffer with a 2-pixel-wide border of (0, 0) vectors,
- * to simplify abyss sampling in stamp().
+ /* we allocate a buffer, referred to as the source buffer, into which we
+ * read the necessary portion of the input buffer, and consecutively
+ * write the stroke results.
*/
- srcbuf_clip.x = 2;
- srcbuf_clip.y = 2;
- srcbuf_clip.width = srcbuf_extent.width;
- srcbuf_clip.height = srcbuf_extent.height;
-
- srcbuf_extent.x -= srcbuf_clip.x;
- srcbuf_extent.y -= srcbuf_clip.y;
- srcbuf_extent.width += 2 * srcbuf_clip.x;
- srcbuf_extent.height += 2 * srcbuf_clip.y;
srcbuf_stride = 2 * srcbuf_extent.width;
- /* that's our source buffer. we both read input data from it, and write
- * the result to it.
+ /* the source buffer is padded at the back by enough elements to make
+ * pointers to out-of-bounds pixels, adjacent to the right and bottom
+ * edges of the buffer, valid; such pointers may be formed as part of
+ * sampling. the value of these elements is irrelevant, as long as
+ * they're finite.
*/
- srcbuf = g_new (gfloat, srcbuf_stride * srcbuf_extent.height);
-
- /* fill the border with (0, 0) vectors. */
- srcbuf_ptr = srcbuf;
+ srcbuf_padding = srcbuf_stride + 2;
- memset (srcbuf_ptr, 0, sizeof (gfloat) * srcbuf_stride * srcbuf_clip.y);
- srcbuf_ptr += srcbuf_stride * srcbuf_clip.y;
-
- for (i = 0; i < srcbuf_clip.height; i++)
- {
- memset (srcbuf_ptr, 0, sizeof (gfloat) * 2 * srcbuf_clip.x);
- srcbuf_ptr += 2 * srcbuf_clip.x;
-
- srcbuf_ptr += 2 * srcbuf_clip.width;
-
- memset (srcbuf_ptr, 0, sizeof (gfloat) * 2 * srcbuf_clip.x);
- srcbuf_ptr += 2 * srcbuf_clip.x;
- }
+ srcbuf = g_new (gfloat, srcbuf_stride * srcbuf_extent.height +
+ srcbuf_padding);
- memset (srcbuf_ptr, 0, sizeof (gfloat) * srcbuf_stride * srcbuf_clip.y);
+ /* fill the padding with (0, 0) vectors */
+ memset (srcbuf + srcbuf_stride * srcbuf_extent.height,
+ 0, sizeof (gfloat) * srcbuf_padding);
/* read the input data from the cached buffer */
- gegl_buffer_get (priv->buffer,
- GEGL_RECTANGLE (srcbuf_extent.x + srcbuf_clip.x,
- srcbuf_extent.y + srcbuf_clip.y,
- srcbuf_clip.width,
- srcbuf_clip.height),
- 1.0, NULL,
- srcbuf + srcbuf_stride * srcbuf_clip.y +
- 2 * srcbuf_clip.x,
- sizeof (gfloat) * srcbuf_stride,
+ gegl_buffer_get (priv->buffer, &srcbuf_extent, 1.0, NULL,
+ srcbuf, sizeof (gfloat) * srcbuf_stride,
GEGL_ABYSS_NONE);
/* process the remaining stroke */
@@ -793,7 +784,7 @@ process (GeglOperation *operation,
if (stamps == 1)
{
stamp (o,
- srcbuf, srcbuf_stride, &srcbuf_extent, &srcbuf_clip,
+ srcbuf, srcbuf_stride, &srcbuf_extent,
next.x, next.y);
}
else
@@ -804,7 +795,7 @@ process (GeglOperation *operation,
gegl_path_point_lerp (&lerp, &prev, &next, t);
stamp (o,
- srcbuf, srcbuf_stride, &srcbuf_extent, &srcbuf_clip,
+ srcbuf, srcbuf_stride, &srcbuf_extent,
lerp.x, lerp.y);
}
}
@@ -820,15 +811,8 @@ process (GeglOperation *operation,
}
/* write the result back to the cached buffer */
- gegl_buffer_set (priv->buffer,
- GEGL_RECTANGLE (srcbuf_extent.x + srcbuf_clip.x,
- srcbuf_extent.y + srcbuf_clip.y,
- srcbuf_clip.width,
- srcbuf_clip.height),
- 0, NULL,
- srcbuf + srcbuf_stride * srcbuf_clip.y +
- 2 * srcbuf_clip.x,
- sizeof (gfloat) * srcbuf_stride);
+ gegl_buffer_set (priv->buffer, &srcbuf_extent, 0, NULL,
+ srcbuf, sizeof (gfloat) * srcbuf_stride);
g_free (srcbuf);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]