[gimp/soc-2010-cage-2] Fix a memory allocation issue mid recursion and put a depth limit in place
- From: Alexia Death <alexiade src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2010-cage-2] Fix a memory allocation issue mid recursion and put a depth limit in place
- Date: Tue, 10 Aug 2010 19:03:12 +0000 (UTC)
commit f5935620553ce2979c90f5e5d35bac30bdf207ac
Author: Alexia Death <alexiadeath gmail com>
Date: Tue Aug 10 22:01:18 2010 +0300
Fix a memory allocation issue mid recursion and put a depth limit in place
The limit can be set to say 7 or 8 when bugs are out of the coef calc.
app/gegl/gimpoperationcagetransform.c | 204 +++++++++++++++++++--------------
1 files changed, 119 insertions(+), 85 deletions(-)
---
diff --git a/app/gegl/gimpoperationcagetransform.c b/app/gegl/gimpoperationcagetransform.c
index 8a24778..7f1ffbf 100644
--- a/app/gegl/gimpoperationcagetransform.c
+++ b/app/gegl/gimpoperationcagetransform.c
@@ -44,12 +44,18 @@ static gboolean gimp_operation_cage_transform_process (G
GeglBuffer *aux_buf,
GeglBuffer *out_buf,
const GeglRectangle *roi);
-static void gimp_operation_cage_transform_interpolate_source_coords_recurs (GimpOperationCageTransform *oct,
- GeglBuffer *out_buf,
- const GeglRectangle *roi,
- GimpCoords p1_s, GimpCoords p1_d,
- GimpCoords p2_s, GimpCoords p2_d,
- GimpCoords p3_s, GimpCoords p3_d);
+static void gimp_operation_cage_transform_interpolate_source_coords_recurs
+ (GimpOperationCageTransform *oct,
+ GeglBuffer *out_buf,
+ const GeglRectangle *roi,
+ GimpCoords p1_s,
+ GimpCoords p1_d,
+ GimpCoords p2_s,
+ GimpCoords p2_d,
+ GimpCoords p3_s,
+ GimpCoords p3_d,
+ gint recursion_depth,
+ gfloat *coords);
static GimpCoords gimp_cage_transform_compute_destination (GimpCageConfig *config,
GeglBuffer *coef_buf,
GimpCoords coords);
@@ -60,7 +66,7 @@ GeglRectangle gimp_operation_cage_transform_get_required_for_output (G
const GeglRectangle *roi);
GeglRectangle gimp_operation_cage_get_bounding_box (GeglOperation *operation);
-G_DEFINE_TYPE (GimpOperationCageTransform, gimp_operation_cage_transform,
+G_DEFINE_TYPE (GimpOperationCageTransform, gimp_operation_cage_transform,
GEGL_TYPE_OPERATION_COMPOSER)
#define parent_class gimp_operation_cage_transform_parent_class
@@ -85,14 +91,14 @@ gimp_operation_cage_transform_class_init (GimpOperationCageTransformClass *klass
operation_class->description = "GIMP cage reverse transform";
operation_class->prepare = gimp_operation_cage_transform_prepare;
-
+
operation_class->get_required_for_output = gimp_operation_cage_transform_get_required_for_output;
operation_class->get_cached_region = gimp_operation_cage_transform_get_cached_region;
operation_class->no_cache = FALSE;
operation_class->get_bounding_box = gimp_operation_cage_get_bounding_box;
-
+
filter_class->process = gimp_operation_cage_transform_process;
-
+
g_object_class_install_property (object_class,
GIMP_OPERATION_CAGE_TRANSFORM_PROP_CONFIG,
g_param_spec_object ("config", NULL, NULL,
@@ -117,7 +123,7 @@ gimp_operation_cage_transform_finalize (GObject *object)
g_object_unref (self->config);
self->config = NULL;
}
-
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -169,7 +175,7 @@ gimp_operation_cage_transform_prepare (GeglOperation *operation)
{
GimpOperationCageTransform *oct = GIMP_OPERATION_CAGE_TRANSFORM (operation);
GimpCageConfig *config = GIMP_CAGE_CONFIG (oct->config);
-
+
gegl_operation_set_format (operation, "input", babl_format_n (babl_type ("float"), 2 * config->cage_vertice_number));
gegl_operation_set_format (operation, "output", babl_format_n (babl_type ("float"), 2));
}
@@ -183,31 +189,31 @@ gimp_operation_cage_transform_process (GeglOperation *operation,
{
GimpOperationCageTransform *oct = GIMP_OPERATION_CAGE_TRANSFORM (operation);
GimpCageConfig *config = GIMP_CAGE_CONFIG (oct->config);
-
+
gint x, y;
GeglRectangle cage_bb = gimp_cage_config_get_bounding_box (config);
GeglRectangle buffer_bb = *gegl_operation_source_get_bounding_box (operation, "input");
-
-
+
+
/* pre-fill the out buffer with no-displacement coordinate */
GeglBufferIterator *it = gegl_buffer_iterator_new (out_buf, roi, NULL, GEGL_BUFFER_WRITE);
-
+
while (gegl_buffer_iterator_next (it))
{
/* iterate inside the roi */
gint n_pixels = it->length;
gint x = it->roi->x; /* initial x */
gint y = it->roi->y; /* and y coordinates */
-
+
gfloat *output = it->data[0];
-
+
while(n_pixels--)
{
output[0] = x;
output[1] = y;
output += 2;
-
+
/* update x and y coordinates */
x++;
if (x >= (it->roi->x + it->roi->width))
@@ -217,7 +223,7 @@ gimp_operation_cage_transform_process (GeglOperation *operation,
}
}
}
-
+
/* compute, reverse and interpolate the transformation */
for (x = cage_bb.x; x < cage_bb.x + cage_bb.width - 1; x++)
{
@@ -227,27 +233,35 @@ gimp_operation_cage_transform_process (GeglOperation *operation,
GimpCoords p2_s = {x+1, y, };
GimpCoords p3_s = {x+1, y+1, };
GimpCoords p4_s = {x, y+1, };
-
+
GimpCoords p1_d, p2_d, p3_d, p4_d;
-
+ gfloat *coords;
+
+ coords = g_malloc( 2 * sizeof (gfloat));
+
p1_d = gimp_cage_transform_compute_destination (config, aux_buf, p1_s);
p2_d = gimp_cage_transform_compute_destination (config, aux_buf, p2_s);
p3_d = gimp_cage_transform_compute_destination (config, aux_buf, p3_s);
p4_d = gimp_cage_transform_compute_destination (config, aux_buf, p4_s);
-
+
gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
out_buf,
&buffer_bb,
p1_s, p1_d,
p2_s, p2_d,
- p3_s, p3_d);
-
+ p3_s, p3_d,
+ 0,
+ coords);
+
gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
out_buf,
&buffer_bb,
p1_s, p1_d,
p3_s, p3_d,
- p4_s, p4_d);
+ p4_s, p4_d,
+ 0,
+ coords);
+ g_free (coords);
}
}
@@ -256,81 +270,91 @@ gimp_operation_cage_transform_process (GeglOperation *operation,
static void
-gimp_operation_cage_transform_interpolate_source_coords_recurs (GimpOperationCageTransform *oct,
+gimp_operation_cage_transform_interpolate_source_coords_recurs (GimpOperationCageTransform *oct,
GeglBuffer *out_buf,
const GeglRectangle *roi,
- GimpCoords p1_s, GimpCoords p1_d,
- GimpCoords p2_s, GimpCoords p2_d,
- GimpCoords p3_s, GimpCoords p3_d)
+ GimpCoords p1_s,
+ GimpCoords p1_d,
+ GimpCoords p2_s,
+ GimpCoords p2_d,
+ GimpCoords p3_s,
+ GimpCoords p3_d,
+ gint recursion_depth,
+ gfloat *coords)
{
gint xmin, xmax, ymin, ymax;
GeglRectangle rect = {0, 0, 1, 1};
- gfloat *coords;
-
- coords = g_malloc( 2 * sizeof (gfloat));
-
+
if (p1_d.x > roi->width) return;
if (p2_d.x > roi->width) return;
if (p3_d.x > roi->width) return;
- if (p1_d.x < 0) return;
- if (p2_d.x < 0) return;
- if (p3_d.x < 0) return;
if (p1_d.y > roi->height) return;
if (p2_d.y > roi->height) return;
if (p3_d.y > roi->height) return;
+
+ if (p1_d.x < 0) return;
+ if (p2_d.x < 0) return;
+ if (p3_d.x < 0) return;
if (p1_d.y < 0) return;
if (p2_d.y < 0) return;
if (p3_d.y < 0) return;
-
+
xmin = xmax = p1_d.x;
ymin = ymax = p1_d.y;
-
+
if (xmin > p2_d.x) xmin = p2_d.x;
if (xmin > p3_d.x) xmin = p3_d.x;
-
+
if (xmax < p2_d.x) xmax = p2_d.x;
if (xmax < p3_d.x) xmax = p3_d.x;
-
+
if (ymin > p2_d.y) ymin = p2_d.y;
if (ymin > p3_d.y) ymin = p3_d.y;
-
+
if (ymax < p2_d.y) ymax = p2_d.y;
if (ymax < p3_d.y) ymax = p3_d.y;
-
+
/* test if there is no more pixel in the triangle */
if (xmin == xmax || ymin == ymax)
return;
-
+
+ /* test if the triangle is implausibly large as manifested by too deep recursion */
+ if (recursion_depth > 4)
+ return;
+
/* test if the triangle is small enough.
* if yes, we compute the coefficient of the barycenter for the pixel (x,y) and see if a pixel is inside (ie the 3 coef have the same sign).
*/
if (xmax - xmin == 1 && ymax - ymin == 1)
{
+
gfloat a, b, c, denom, x, y;
-
+
rect.x = xmax;
rect.y = ymax;
-
+
x = (gfloat) xmax;
y = (gfloat) ymax;
-
+
denom = (p2_d.x - p1_d.x) * p3_d.y + (p1_d.x - p3_d.x) * p2_d.y + (p3_d.x - p2_d.x) * p1_d.y;
a = ((p2_d.x - x) * p3_d.y + (x - p3_d.x) * p2_d.y + (p3_d.x - p2_d.x) * y) / denom;
b = - ((p1_d.x - x) * p3_d.y + (x - p3_d.x) * p1_d.y + (p3_d.x - p1_d.x) * y) / denom;
c = 1.0 - a - b;
-
+
/* if a pixel is inside, we compute his source coordinate and set it in the output buffer */
if ((a > 0 && b > 0 && c > 0) || (a < 0 && b < 0 && c < 0))
{
coords[0] = (a * p1_s.x + b * p2_s.x + c * p3_s.x);
coords[1] = (a * p1_s.y + b * p2_s.y + c * p3_s.y);
-
+
gegl_buffer_set(out_buf,
&rect,
oct->format_coords,
coords,
GEGL_AUTO_ROWSTRIDE);
}
+
+ return;
}
else
{
@@ -340,60 +364,70 @@ gimp_operation_cage_transform_interpolate_source_coords_recurs (GimpOperationCa
* /__\
* /\ /\
* /__\/__\
- *
+ *
*/
-
+
GimpCoords pm1_d, pm2_d, pm3_d;
GimpCoords pm1_s, pm2_s, pm3_s;
-
+
+ gint next_depth = recursion_depth + 1;
+
pm1_d.x = (p1_d.x + p2_d.x) / 2.0;
pm1_d.y = (p1_d.y + p2_d.y) / 2.0;
-
+
pm2_d.x = (p2_d.x + p3_d.x) / 2.0;
pm2_d.y = (p2_d.y + p3_d.y) / 2.0;
-
+
pm3_d.x = (p3_d.x + p1_d.x) / 2.0;
pm3_d.y = (p3_d.y + p1_d.y) / 2.0;
-
+
pm1_s.x = (p1_s.x + p2_s.x) / 2.0;
pm1_s.y = (p1_s.y + p2_s.y) / 2.0;
-
+
pm2_s.x = (p2_s.x + p3_s.x) / 2.0;
pm2_s.y = (p2_s.y + p3_s.y) / 2.0;
-
+
pm3_s.x = (p3_s.x + p1_s.x) / 2.0;
pm3_s.y = (p3_s.y + p1_s.y) / 2.0;
-
- gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
+
+ gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
out_buf,
roi,
p1_s, p1_d,
pm1_s, pm1_d,
- pm3_s, pm3_d);
-
- gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
+ pm3_s, pm3_d,
+ next_depth,
+ coords);
+
+ gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
out_buf,
roi,
pm1_s, pm1_d,
p2_s, p2_d,
- pm2_s, pm2_d);
+ pm2_s, pm2_d,
+ next_depth,
+ coords);
- gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
+ gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
out_buf,
roi,
pm1_s, pm1_d,
pm2_s, pm2_d,
- pm3_s, pm3_d);
-
- gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
+ pm3_s, pm3_d,
+ next_depth,
+ coords);
+
+ gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
out_buf,
roi,
pm3_s, pm3_d,
pm2_s, pm2_d,
- p3_s, p3_d);
+ p3_s, p3_d,
+ next_depth,
+ coords);
}
-
- g_free (coords);
+
+
}
static GimpCoords
@@ -408,50 +442,50 @@ gimp_cage_transform_compute_destination (GimpCageConfig *config,
GimpCoords result;
gint cvn = config->cage_vertice_number;
Babl *format_coef = babl_format_n (babl_type ("float"), 2 * cvn);
-
+
rect.height = 1;
rect.width = 1;
rect.x = coords.x;
rect.y = coords.y;
-
+
coef = g_malloc (config->cage_vertice_number * 2 * sizeof(gfloat));
-
+
gegl_buffer_get (coef_buf, 1, &rect, format_coef, coef, GEGL_AUTO_ROWSTRIDE);
-
+
pos_x = 0;
pos_y = 0;
-
+
for(i = 0; i < cvn; i++)
{
-
+
if (!isnan(coef[i]))
{
pos_x += coef[i] * config->cage_vertices_d[i].x;
pos_y += coef[i] * config->cage_vertices_d[i].y;
}
-
+
g_assert (!isnan(pos_x));
g_assert (!isnan(pos_y));
}
-
+
for(i = 0; i < cvn; i++)
{
-
+
if (!isnan(coef[i]))
{
pos_x += coef[i + cvn] * config->scaling_factor[i] * gimp_cage_config_get_edge_normal (config, i).x;
pos_y += coef[i + cvn] * config->scaling_factor[i] * gimp_cage_config_get_edge_normal (config, i).y;
}
-
+
g_assert (!isnan(pos_x));
g_assert (!isnan(pos_y));
}
-
+
result.x = pos_x;
result.y = pos_y;
-
+
g_free (coef);
-
+
return result;
}
@@ -470,7 +504,7 @@ gimp_operation_cage_transform_get_required_for_output (GeglOperation *ope
const GeglRectangle *roi)
{
GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
-
+
return result;
}
@@ -478,6 +512,6 @@ GeglRectangle
gimp_operation_cage_get_bounding_box (GeglOperation *operation)
{
GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
-
+
return result;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]