[gegl] photocopy: Don't linearize, implement get_cached_region
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] photocopy: Don't linearize, implement get_cached_region
- Date: Thu, 20 Mar 2014 03:05:43 +0000 (UTC)
commit fa0b423c707f44a9c5166573488f2e574d9b4872
Author: Daniel Sabo <DanielSabo gmail com>
Date: Tue Mar 18 23:56:50 2014 -0700
photocopy: Don't linearize, implement get_cached_region
operations/common/photocopy.c | 324 ++++++++++++++++-------------------------
1 files changed, 128 insertions(+), 196 deletions(-)
---
diff --git a/operations/common/photocopy.c b/operations/common/photocopy.c
index f49b5b3..0e28656 100644
--- a/operations/common/photocopy.c
+++ b/operations/common/photocopy.c
@@ -48,15 +48,6 @@ gegl_chant_double (white, _("Percent White"),
#define THRESHOLD 0.75
-typedef struct {
- gdouble black;
- gdouble white;
- gdouble prev_mask_radius;
- gdouble prev_sharpness;
- gdouble prev_black;
- gdouble prev_white;
-} Ramps;
-
static void
grey_blur_buffer (GeglBuffer *input,
gdouble sharpness,
@@ -137,83 +128,66 @@ calculate_threshold (gint *hist,
}
static void
-compute_ramp (GeglBuffer *input,
- GeglOperation *operation,
- gdouble pct_black,
- gdouble pct_white,
- gint under_threshold,
- gdouble *threshold_black,
- gdouble *threshold_white)
+compute_ramp (GeglBuffer *dest1,
+ GeglBuffer *dest2,
+ const GeglRectangle *roi,
+ gdouble pct_black,
+ gdouble pct_white,
+ gboolean under_threshold,
+ gdouble *threshold_black,
+ gdouble *threshold_white)
{
- GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ GeglBufferIterator *iter;
- GeglRectangle *whole_region;
- gint n_pixels;
gint hist1[2000];
gint hist2[2000];
gdouble diff;
gint count;
- GeglBuffer *dest1, *dest2;
-
- gfloat *src1_buf;
- gfloat *src2_buf;
- gfloat *dst_buf;
-
- gint total_pixels;
-
- gfloat* ptr1;
- gfloat* ptr2;
- whole_region = gegl_operation_source_get_bounding_box (operation, "input");
- grey_blur_buffer (input, o->sharpness, o->mask_radius, &dest1, &dest2);
-
- total_pixels = whole_region->width * whole_region->height;
- src1_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
- src2_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
- dst_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-
- gegl_buffer_get (dest1, whole_region, 1.0, babl_format ("Y float"),
- src1_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- gegl_buffer_get (dest2, whole_region, 1.0, babl_format ("Y float"),
- src2_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
- n_pixels = whole_region->width * whole_region->height;
+ iter = gegl_buffer_iterator_new (dest1, roi, 0,
+ babl_format ("Y float"),
+ GEGL_BUFFER_READ,
+ GEGL_ABYSS_NONE);
+ gegl_buffer_iterator_add (iter, dest2, roi, 0,
+ babl_format ("Y float"),
+ GEGL_BUFFER_READ,
+ GEGL_ABYSS_NONE);
memset (hist1, 0, sizeof (int) * 2000);
memset (hist2, 0, sizeof (int) * 2000);
count = 0;
- ptr1 = src1_buf;
- ptr2 = src2_buf;
- while (n_pixels--)
- {
- diff = *ptr1 / *ptr2;
- ptr1++;
- ptr2++;
- if (under_threshold)
- {
- if (diff < THRESHOLD)
- {
- hist2[(int) (diff * 1000)] ++;
- count ++;
- }
- }
- else
- {
- if (diff >= THRESHOLD && diff < 2.0)
- {
- hist1[(int) (diff * 1000)] ++;
- count ++;
- }
- }
- }
-
- g_object_unref (dest1);
- g_object_unref (dest2);
-
- g_slice_free1 (total_pixels * sizeof (gfloat), src1_buf);
- g_slice_free1 (total_pixels * sizeof (gfloat), src2_buf);
- g_slice_free1 (total_pixels * sizeof (gfloat), dst_buf);
+ while (gegl_buffer_iterator_next (iter))
+ {
+ gint n_pixels = iter->length;
+ gfloat *ptr1 = iter->data[0];
+ gfloat *ptr2 = iter->data[1];
+
+ while (n_pixels--)
+ {
+ diff = *ptr1 / *ptr2;
+ ptr1++;
+ ptr2++;
+
+ if (under_threshold)
+ {
+ if (diff < THRESHOLD && diff >= 0.0f)
+ {
+ hist2[(int) (diff * 1000)] ++;
+ count ++;
+ }
+ }
+ else
+ {
+ if (diff >= THRESHOLD && diff < 2.0)
+ {
+ hist1[(int) (diff * 1000)] ++;
+ count ++;
+ }
+ }
+
+ }
+ }
*threshold_black = calculate_threshold (hist1, pct_black, count, 0);
*threshold_white = calculate_threshold (hist2, pct_white, count, 1);
@@ -222,26 +196,36 @@ compute_ramp (GeglBuffer *input,
static void
prepare (GeglOperation *operation)
{
- GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
-
gegl_operation_set_format (operation, "input",
babl_format ("Y float"));
gegl_operation_set_format (operation, "output",
babl_format ("Y 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_sharpness != o->sharpness ||
- ramps->prev_black != o->black ||
- ramps->prev_white != o->white)
- {
- g_slice_free (Ramps, o->chant_data);
- o->chant_data = NULL;
- }
- }
+static GeglRectangle
+get_required_for_output (GeglOperation *operation,
+ const gchar *input_pad,
+ const GeglRectangle *roi)
+{
+ GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
+
+ /* Don't request an infinite plane */
+ if (gegl_rectangle_is_infinite_plane (&result))
+ return *roi;
+
+ return result;
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation *operation,
+ const GeglRectangle *roi)
+{
+ GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
+
+ if (gegl_rectangle_is_infinite_plane (&result))
+ return *roi;
+
+ return result;
}
static gboolean
@@ -253,144 +237,92 @@ process (GeglOperation *operation,
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ GeglBufferIterator *iter;
+
GeglBuffer *dest1;
GeglBuffer *dest2;
- Ramps* ramps;
-
- gint n_pixels;
- gfloat *out_pixel;
- gint total_pixels;
-
gdouble diff;
- Ramps *get_ramps;
gdouble ramp_down;
gdouble ramp_up;
gdouble mult;
- gfloat *src1_buf;
- gfloat *src2_buf;
- gfloat *dst_buf;
-
- gfloat* ptr1;
- gfloat* ptr2;
-
- static GMutex mutex = { 0, };
-
- total_pixels = result->width * result->height;
- dst_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-
- g_mutex_lock (&mutex);
- if (o->chant_data == NULL)
- {
- o->chant_data = g_slice_new (Ramps);
- ramps = (Ramps*) o->chant_data;
- compute_ramp (input,
- operation,
- o->black,
- o->white,1,
- &ramps->black,
- &ramps->white);
- ramps->prev_mask_radius = o->mask_radius;
- ramps->prev_sharpness = o->sharpness;
- ramps->prev_black = o->black;
- ramps->prev_white = o->white;
- }
- g_mutex_unlock (&mutex);
-
grey_blur_buffer (input, o->sharpness, o->mask_radius, &dest1, &dest2);
- total_pixels = result->width * result->height;
- src1_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
- src2_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-
- gegl_buffer_get (dest1, result, 1.0, babl_format ("Y float"),
- src1_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- gegl_buffer_get (dest2, result, 1.0, babl_format ("Y float"),
- src2_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- g_object_unref (dest1);
- g_object_unref (dest2);
-
- out_pixel = dst_buf;
- n_pixels = result->width * result->height;
-
- get_ramps = (Ramps*) o->chant_data;
- ramp_down = get_ramps->black;
- ramp_up = get_ramps->white;
-
- ptr1 = src1_buf;
- ptr2 = src2_buf;
-
- while (n_pixels--)
+ compute_ramp (dest1, dest2, result,
+ o->black, o->white, TRUE,
+ &ramp_down, &ramp_up);
+
+ iter = gegl_buffer_iterator_new (dest1, result, 0,
+ babl_format ("Y float"),
+ GEGL_BUFFER_READ,
+ GEGL_ABYSS_NONE);
+ gegl_buffer_iterator_add (iter, dest2, result, 0,
+ babl_format ("Y float"),
+ GEGL_BUFFER_READ,
+ GEGL_ABYSS_NONE);
+ gegl_buffer_iterator_add (iter, output, result, 0,
+ babl_format ("Y float"),
+ GEGL_BUFFER_WRITE,
+ GEGL_ABYSS_NONE);
+
+ while (gegl_buffer_iterator_next (iter))
{
- diff = *ptr1 / *ptr2;
- if (diff < THRESHOLD)
+ gint n_pixels = iter->length;
+ gfloat *ptr1 = iter->data[0];
+ gfloat *ptr2 = iter->data[1];
+ gfloat *out_pixel = iter->data[2];
+
+ while (n_pixels--)
{
- if (ramp_down == 0.0)
- *out_pixel = 0.0;
- else
+ diff = *ptr1 / *ptr2;
+ if (diff < THRESHOLD)
{
- mult = (ramp_down - MIN (ramp_down,
- (THRESHOLD - diff))) / ramp_down;
- *out_pixel = *ptr1 * mult;
+ if (ramp_down == 0.0)
+ *out_pixel = 0.0;
+ else
+ {
+ mult = (ramp_down - MIN (ramp_down,
+ (THRESHOLD - diff))) / ramp_down;
+ *out_pixel = *ptr1 * mult;
+ }
}
- }
- else
- {
- if (ramp_up == 0.0)
- mult = 1.0;
else
- mult = MIN (ramp_up,
- (diff - THRESHOLD)) / ramp_up;
+ {
+ if (ramp_up == 0.0)
+ mult = 1.0;
+ else
+ mult = MIN (ramp_up,
+ (diff - THRESHOLD)) / ramp_up;
- *out_pixel = mult + *ptr1 - mult * *ptr1;
+ *out_pixel = mult + *ptr1 - mult * *ptr1;
+ }
+
+ ptr1++;
+ ptr2++;
+ out_pixel++;
}
- ptr1++;
- ptr2++;
- out_pixel ++;
}
- gegl_buffer_set (output,
- result,
- 0,
- babl_format ("Y float"),
- dst_buf, GEGL_AUTO_ROWSTRIDE);
-
- g_slice_free1 (total_pixels * sizeof (gfloat), src1_buf);
- g_slice_free1 (total_pixels * sizeof (gfloat), src2_buf);
- g_slice_free1 (total_pixels * sizeof (gfloat), dst_buf);
-
- 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_unref (dest1);
+ g_object_unref (dest2);
- 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;
- filter_class->process = process;
+ operation_class->prepare = prepare;
+ operation_class->get_required_for_output = get_required_for_output;
+ operation_class->get_cached_region = get_cached_region;
+ filter_class->process = process;
gegl_operation_class_set_keys (operation_class,
"name", "gegl:photocopy",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]