[gegl] cartoon: Refactor caching behavior, don't linearize
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] cartoon: Refactor caching behavior, don't linearize
- Date: Thu, 20 Mar 2014 09:12:14 +0000 (UTC)
commit c05901419d295d7258194a9fac40417b7806bb27
Author: Daniel Sabo <DanielSabo gmail com>
Date: Tue Mar 18 04:54:06 2014 -0700
cartoon: Refactor caching behavior, don't linearize
* Use get_cached_region instead of internally caching the ramp
calculations, the previous system caused the blur to be
recomputed multiple times.
* Use iterators instead of linearizing the buffers. I left the samplers
for the gray buffers because I'm not sure if the effect they cause
is intentional.
operations/common/cartoon.c | 322 +++++++++++++++++--------------------------
1 files changed, 125 insertions(+), 197 deletions(-)
---
diff --git a/operations/common/cartoon.c b/operations/common/cartoon.c
index 33a737c..3bb751c 100644
--- a/operations/common/cartoon.c
+++ b/operations/common/cartoon.c
@@ -102,14 +102,11 @@ grey_blur_buffer (GeglBuffer *input,
}
static gdouble
-compute_ramp (GeglBuffer *input,
- GeglOperation *operation,
- gdouble pct_black)
+compute_ramp (GeglSampler *sampler1,
+ GeglSampler *sampler2,
+ const GeglRectangle *roi,
+ gdouble pct_black)
{
- GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
-
- GeglRectangle *whole_region;
- gint n_pixels;
gint hist[100];
gdouble diff;
gint count;
@@ -118,77 +115,49 @@ compute_ramp (GeglBuffer *input,
gint y;
gint i;
gint sum;
- GeglSampler *sampler1;
- GeglSampler *sampler2;
- GeglBuffer *dest1, *dest2;
-
- whole_region = gegl_operation_source_get_bounding_box (operation, "input");
- grey_blur_buffer (input, o->mask_radius, &dest1, &dest2);
-
- sampler1 = gegl_buffer_sampler_new (dest1,
- babl_format ("Y' float"),
- GEGL_SAMPLER_LINEAR);
-
- sampler2 = gegl_buffer_sampler_new (dest2,
- babl_format ("Y' float"),
- GEGL_SAMPLER_LINEAR);
- n_pixels = whole_region->width * whole_region->height;
memset (hist, 0, sizeof (int) * 100);
count = 0;
- x = whole_region->x;
- y = whole_region->y;
- while (n_pixels--)
- {
- gegl_sampler_get (sampler1,
- x,
- y,
- NULL,
- &pixel1,
- GEGL_ABYSS_NONE);
-
- gegl_sampler_get (sampler2,
- x,
- y,
- NULL,
- &pixel2,
- GEGL_ABYSS_NONE);
-
- if (pixel2 != 0)
+ for (y = roi->y; y < roi->y + roi->height; ++y)
+ for (x = roi->x; x < roi->x + roi->width; ++x)
{
- diff = (gdouble) pixel1 / (gdouble) pixel2;
-
- if (diff < 1.0)
- {
- hist[(int) (diff * 100)] += 1;
- count += 1;
- }
+ gegl_sampler_get (sampler1,
+ x,
+ y,
+ NULL,
+ &pixel1,
+ GEGL_ABYSS_NONE);
+
+ gegl_sampler_get (sampler2,
+ x,
+ y,
+ NULL,
+ &pixel2,
+ GEGL_ABYSS_NONE);
+
+ if (pixel2 != 0)
+ {
+ diff = (gdouble) pixel1 / (gdouble) pixel2;
+
+ if (diff < 1.0 && diff >= 0.0)
+ {
+ hist[(int) (diff * 100)] += 1;
+ count += 1;
+ }
+ }
}
- x++;
- if (x >= whole_region->x + whole_region->width)
- {
- x = whole_region->x;
- y++;
- }
- }
-
- g_object_unref (sampler1);
- g_object_unref (sampler2);
- g_object_unref (dest1);
- g_object_unref (dest2);
-
if (pct_black == 0.0 || count == 0)
return 1.0;
sum = 0;
for (i = 0; i < 100; i++)
- {
- sum += hist[i];
- if (((gdouble) sum / (gdouble) count) > pct_black)
- return (1.0 - (gdouble) i / 100.0);
- }
+ {
+ sum += hist[i];
+ if (((gdouble) sum / (gdouble) count) > pct_black)
+ return (1.0 - (gdouble) i / 100.0);
+ }
return 0.0;
@@ -197,25 +166,10 @@ compute_ramp (GeglBuffer *input,
static void
prepare (GeglOperation *operation)
{
- GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
-
gegl_operation_set_format (operation, "input",
babl_format ("Y'CbCrA float"));
gegl_operation_set_format (operation, "output",
babl_format ("Y'CbCrA float"));
-
- if(o->chant_data)
- {
- Ramps* ramps = (Ramps*) o->chant_data;
-
- /* hack so that thresholds are only calculated once */
- if(ramps->prev_mask_radius != o->mask_radius ||
- ramps->prev_pct_black != o->pct_black)
- {
- g_slice_free (Ramps, o->chant_data);
- o->chant_data = NULL;
- }
- }
}
static GeglRectangle
@@ -231,6 +185,31 @@ get_bounding_box (GeglOperation *operation)
return *GEGL_RECTANGLE (0, 0, 0, 0);
}
+static GeglRectangle
+get_required_for_output (GeglOperation *operation,
+ const gchar *input_pad,
+ const GeglRectangle *output_roi)
+{
+ GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, input_pad);
+
+ if (in_rect)
+ return *in_rect;
+ else
+ return (GeglRectangle){0, 0, 0, 0};
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation *operation,
+ const GeglRectangle *output_roi)
+{
+ GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input");
+
+ if (in_rect)
+ return *in_rect;
+ else
+ return (GeglRectangle){0, 0, 0, 0};
+}
+
static gboolean
process (GeglOperation *operation,
GeglBuffer *input,
@@ -238,51 +217,16 @@ process (GeglOperation *operation,
const GeglRectangle *result,
gint level)
{
- GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
-
- GeglBuffer *dest1;
- GeglBuffer *dest2;
- GeglSampler *sampler1;
- GeglSampler *sampler2;
-
- Ramps* ramps;
-
- gint n_pixels;
- gfloat pixel1, pixel2;
- gfloat *out_pixel;
- gint x;
- gint y;
-
-
- gdouble diff;
- Ramps *get_ramps;
- gdouble ramp;
- gdouble mult = 0.0;
-
- gfloat *dst_buf;
- GeglRectangle *whole_region;
-
- static GMutex mutex = { 0, };
-
- dst_buf = g_slice_alloc (result->width * result->height * 4 * sizeof(gfloat));
-
- gegl_buffer_get (input, result, 1.0, babl_format ("Y'CbCrA float"), dst_buf, GEGL_AUTO_ROWSTRIDE,
GEGL_ABYSS_NONE);
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ GeglBufferIterator *iter;
+ GeglBuffer *dest1;
+ GeglBuffer *dest2;
+ GeglSampler *sampler1;
+ GeglSampler *sampler2;
+ gdouble ramp;
+ gint x;
+ gint y;
-
- g_mutex_lock (&mutex);
- if(o->chant_data == NULL)
- {
- whole_region = gegl_operation_source_get_bounding_box (operation, "input");
- gegl_buffer_set_extent (input, whole_region);
- o->chant_data = g_slice_new (Ramps);
- ramps = (Ramps*) o->chant_data;
- ramps->prev_ramp = compute_ramp (input,operation,o->pct_black);
- ramps->prev_mask_radius = o->mask_radius;
- ramps->prev_pct_black = o->pct_black;
- }
- g_mutex_unlock (&mutex);
-
- gegl_buffer_set_extent (input, result);
grey_blur_buffer (input, o->mask_radius, &dest1, &dest2);
sampler1 = gegl_buffer_sampler_new (dest1,
@@ -293,99 +237,83 @@ process (GeglOperation *operation,
babl_format ("Y' float"),
GEGL_SAMPLER_LINEAR);
- x = result->x;
- y = result->y;
- n_pixels = result->width * result->height;
+ ramp = compute_ramp (sampler1, sampler2, result, o->pct_black);
- out_pixel = dst_buf;
- get_ramps = (Ramps*) o->chant_data;
- ramp = get_ramps->prev_ramp;
+ iter = gegl_buffer_iterator_new (output, result, 0, babl_format ("Y'CbCrA float"),
+ GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+ gegl_buffer_iterator_add (iter, input, result, 0, babl_format ("Y'CbCrA float"),
+ GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
- while (n_pixels--)
- {
- gegl_sampler_get (sampler1,
- x,
- y,
- NULL,
- &pixel1,
- GEGL_ABYSS_NONE);
-
- gegl_sampler_get (sampler2,
- x,
- y,
- NULL,
- &pixel2,
- GEGL_ABYSS_NONE);
-
- if (pixel2 != 0)
- {
- diff = (gdouble) pixel1 / (gdouble) pixel2;
- if (diff < THRESHOLD)
- {
- if (GEGL_FLOAT_EQUAL(ramp,0.0))
- mult = 0.0;
- else
- mult = (ramp - MIN (ramp, (THRESHOLD - diff))) / ramp;
- }
- else
- mult = 1.0;
- }
-
- *out_pixel = CLAMP(pixel1 * mult, 0.0, 1.0);
- out_pixel += 4;
-
- x++;
- if (x >= result->x + result->width)
- {
- x = result->x;
- y++;
- }
+ while (gegl_buffer_iterator_next (iter))
+ {
+ gfloat *out_pixel = iter->data[0];
+ gfloat *in_pixel = iter->data[1];
+
+ for (y = iter->roi[0].y; y < iter->roi[0].y + iter->roi[0].height; ++y)
+ for (x = iter->roi[0].x; x < iter->roi[0].x + iter->roi[0].width; ++x)
+ {
+ gfloat pixel1;
+ gfloat pixel2;
+ gdouble mult = 0.0;
+ gdouble diff;
+
+ gegl_sampler_get (sampler1, x, y,
+ NULL, &pixel1,
+ GEGL_ABYSS_NONE);
+
+ gegl_sampler_get (sampler2, x, y,
+ NULL, &pixel2,
+ GEGL_ABYSS_NONE);
+
+ if (pixel2 != 0)
+ {
+ diff = (gdouble) pixel1 / (gdouble) pixel2;
+ if (diff < THRESHOLD)
+ {
+ if (GEGL_FLOAT_EQUAL (ramp, 0.0))
+ mult = 0.0;
+ else
+ mult = (ramp - MIN (ramp, (THRESHOLD - diff))) / ramp;
+ }
+ else
+ mult = 1.0;
+ }
+
+ out_pixel[0] = CLAMP (pixel1 * mult, 0.0, 1.0);
+ out_pixel[1] = in_pixel[1];
+ out_pixel[2] = in_pixel[2];
+ out_pixel[3] = in_pixel[3];
+
+ out_pixel += 4;
+ in_pixel += 4;
+ }
}
-
- gegl_buffer_set (output, result, 0, babl_format ("Y'CbCrA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
- g_slice_free1 (result->width * result->height * 4 * sizeof(gfloat), dst_buf);
-
g_object_unref (sampler1);
g_object_unref (sampler2);
+
g_object_unref (dest1);
g_object_unref (dest2);
- whole_region = gegl_operation_source_get_bounding_box (operation, "input");
- gegl_buffer_set_extent (input, whole_region);
- return TRUE;
-}
-
-static void
-finalize (GObject *object)
-{
- GeglChantO *o = GEGL_CHANT_PROPERTIES (object);
-
- if (o->chant_data)
- {
- g_slice_free (Ramps, o->chant_data);
- o->chant_data = NULL;
- }
-
- G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
+ return TRUE;
}
static void
gegl_chant_class_init (GeglChantClass *klass)
{
- GObjectClass *object_class;
GeglOperationClass *operation_class;
GeglOperationFilterClass *filter_class;
- object_class = G_OBJECT_CLASS (klass);
operation_class = GEGL_OPERATION_CLASS (klass);
filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
- object_class->finalize = finalize;
- operation_class->prepare = prepare;
- operation_class->get_bounding_box = get_bounding_box;
- filter_class->process = process;
+ operation_class->prepare = prepare;
+ operation_class->get_bounding_box = get_bounding_box;
+ operation_class->get_cached_region = get_cached_region;
+ operation_class->get_required_for_output = get_required_for_output;
+
+ filter_class->process = process;
gegl_operation_class_set_keys (operation_class,
"categories", "artistic",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]