[gegl] Issue #38 - gegl-sampler sometimes crashes for absurd coordinates.
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Issue #38 - gegl-sampler sometimes crashes for absurd coordinates.
- Date: Wed, 27 Feb 2019 21:45:55 +0000 (UTC)
commit 15a61d51869527b1c875d87db698fb9784c9cf9d
Author: Ell <ell_se yahoo com>
Date: Wed Feb 27 16:30:30 2019 -0500
Issue #38 - gegl-sampler sometimes crashes for absurd coordinates.
In gegl_sampler_get_ptr(), clamp/wrap the input coordinates based
on the buffer's abyss and the sampler's context rect, so that the
coordinates are never farther away from the abyss than necessary,
avoiding overflowing in gegl_buffer_get() due to extreme coordinate
values.
gegl/buffer/gegl-sampler.c | 14 ++++++++++
gegl/buffer/gegl-sampler.h | 68 +++++++++++++++++++++++++---------------------
2 files changed, 51 insertions(+), 31 deletions(-)
---
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index 394da9bf6..23b60454d 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -147,6 +147,20 @@ constructed (GObject *self)
sampler->get = klass->get;
sampler->interpolate = klass->interpolate;
+
+ if (sampler->buffer)
+ {
+ GeglSamplerLevel *level = &sampler->level[0];
+
+ level->abyss_rect = sampler->buffer->abyss;
+
+ level->abyss_rect.x -= level->context_rect.x +
+ level->context_rect.width;
+ level->abyss_rect.y -= level->context_rect.y +
+ level->context_rect.height;
+ level->abyss_rect.width += level->context_rect.width + 1;
+ level->abyss_rect.height += level->context_rect.height + 1;
+ }
}
void
diff --git a/gegl/buffer/gegl-sampler.h b/gegl/buffer/gegl-sampler.h
index 132a03faa..d562df9a6 100644
--- a/gegl/buffer/gegl-sampler.h
+++ b/gegl/buffer/gegl-sampler.h
@@ -22,6 +22,8 @@
#include <babl/babl.h>
#include <stdio.h>
+#include "gegl-buffer-private.h"
+
G_BEGIN_DECLS
#define GEGL_TYPE_SAMPLER (gegl_sampler_get_type ())
@@ -31,17 +33,6 @@ G_BEGIN_DECLS
#define GEGL_IS_SAMPLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEGL_TYPE_SAMPLER))
#define GEGL_SAMPLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEGL_TYPE_SAMPLER,
GeglSamplerClass))
-/* empirically derived bound on limit, derived using fractal trace offsetting the mandelbrot to
- * make it converge on infinity in loop mode.
- */
-#define GEGL_BUFFER_MAX_COORDINATE 2000000000.0
-#define GEGL_BUFFER_VALID_COORDINATE(v) \
- ((v)*(v) < GEGL_BUFFER_MAX_COORDINATE * GEGL_BUFFER_MAX_COORDINATE)
-#if 0
- /* the above is equivalent to the following, but presumably faster */
- ((v)>-GEGL_BUFFER_MAX_COORDINATE && (v)< GEGL_BUFFER_MAX_COORDINATE)
-#endif
-
/*
* This should be set to the largest number of mipmap levels (counted
@@ -73,6 +64,7 @@ typedef struct _GeglSamplerClass GeglSamplerClass;
typedef struct GeglSamplerLevel
{
GeglRectangle context_rect;
+ GeglRectangle abyss_rect;
gpointer sampler_buffer;
GeglRectangle sampler_rectangle;
gint last_x;
@@ -206,6 +198,24 @@ gegl_sampler_get_ptr (GeglSampler *sampler,
guchar *buffer_ptr;
GeglSamplerLevel *level = &sampler->level[0];
+
+ if (repeat_mode != GEGL_ABYSS_LOOP)
+ {
+ x = CLAMP (x, level->abyss_rect.x,
+ level->abyss_rect.x + level->abyss_rect.width - 1);
+ y = CLAMP (y, level->abyss_rect.y,
+ level->abyss_rect.y + level->abyss_rect.height - 1);
+ }
+ else
+ {
+ x = sampler->buffer->abyss.x +
+ GEGL_REMAINDER (x - sampler->buffer->abyss.x,
+ sampler->buffer->abyss.width);
+ y = sampler->buffer->abyss.y +
+ GEGL_REMAINDER (y - sampler->buffer->abyss.y,
+ sampler->buffer->abyss.height);
+ }
+
if ((x + level->context_rect.x < level->sampler_rectangle.x) ||
(y + level->context_rect.y < level->sampler_rectangle.y) ||
(x + level->context_rect.x + level->context_rect.width >
@@ -336,29 +346,25 @@ _gegl_sampler_box_get (GeglSampler* restrict self,
uv_samples_inv = u_samples_inv * v_samples_inv;
- if (GEGL_BUFFER_VALID_COORDINATE(x0) &&
- GEGL_BUFFER_VALID_COORDINATE(y0))
+ for (v = 0; v < v_samples; v++)
{
- for (v = 0; v < v_samples; v++)
+ gdouble x = x0;
+ gdouble y = y0;
+
+ for (u = 0; u < u_samples; u++)
{
- gdouble x = x0;
- gdouble y = y0;
-
- for (u = 0; u < u_samples; u++)
- {
- int c;
- gfloat input[channels];
- self->interpolate (self, x, y, input, repeat_mode);
- for (c = 0; c < channels; c++)
- result[c] += input[c];
-
- x += u_dx;
- y += u_dy;
- }
-
- x0 += v_dx;
- y0 += v_dy;
+ int c;
+ gfloat input[channels];
+ self->interpolate (self, x, y, input, repeat_mode);
+ for (c = 0; c < channels; c++)
+ result[c] += input[c];
+
+ x += u_dx;
+ y += u_dy;
}
+
+ x0 += v_dx;
+ y0 += v_dy;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]