[gegl/soc-2012-ops: 31/58] Wind Operation: Actually randomize bleed lengths.
- From: Michael Murà <mmure src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2012-ops: 31/58] Wind Operation: Actually randomize bleed lengths.
- Date: Wed, 29 Aug 2012 11:07:07 +0000 (UTC)
commit db05d6add4996e708d17916c2cf2918c4acadf50
Author: Hans Lo <hansshulo gmail com>
Date: Mon Aug 6 17:40:38 2012 -0400
Wind Operation: Actually randomize bleed lengths.
Last commit was a mistake.
operations/common/wind.c | 236 +++++++++++++++++++++++++++++++++++----------
1 files changed, 183 insertions(+), 53 deletions(-)
---
diff --git a/operations/common/wind.c b/operations/common/wind.c
index 8bb5a98..a1bdd5a 100644
--- a/operations/common/wind.c
+++ b/operations/common/wind.c
@@ -23,11 +23,11 @@
#ifdef GEGL_CHANT_PROPERTIES
-gegl_chant_double (threshold, _("Threshold"), 0.0, 1.0, 0.2,
+gegl_chant_double (threshold, _("Threshold"), 0.0, 100.0, 10.0,
_("Higher values restrict the effect to fewer "
"areas of the image"))
-gegl_chant_int (strength, _("Strength"), 1, 100, 4,
+gegl_chant_int (strength, _("Strength"), 1, 1000, 40,
_("Higher values increase the magnitude of the effect"))
#else
@@ -36,12 +36,50 @@ gegl_chant_int (strength, _("Strength"), 1, 100, 4,
#define GEGL_CHANT_C_FILE "wind.c"
#include "gegl-chant.h"
-//#include <math.h>
#include <stdlib.h>
+typedef struct
+{
+ gint x;
+ gint y;
+} pair;
+
+guint tuple_hash (gconstpointer v);
+gboolean tuple_equal (gconstpointer v1, gconstpointer v2);
+void get_pixel (gint x,
+ gint y,
+ gint buf_width,
+ gfloat* src_begin,
+ gfloat* dst);
+
+guint tuple_hash (gconstpointer v)
+{
+ const pair *data = v;
+ return (g_int_hash (&data->x) ^ g_int_hash (&data->y));
+}
+
+gboolean tuple_equal (gconstpointer v1, gconstpointer v2)
+{
+ const pair *data1 = v1;
+ const pair *data2 = v2;
+ return (g_int_equal (&data1->x, &data2->x) &&
+ g_int_equal (&data1->y, &data2->y));
+}
+
+void get_pixel (gint x,
+ gint y,
+ gint buf_width,
+ gfloat* src_begin,
+ gfloat* dst)
+{
+ gint b;
+ gfloat* src = src_begin + 4*(x + buf_width*y);
+ for (b = 0; b < 4; b++)
+ {
+ dst[b] = src[b];
+ }
+}
-//assume leading
-//assume has alpha
static void
get_derivative (gfloat *pixel1,
gfloat *pixel2,
@@ -63,11 +101,45 @@ threshold_exceeded (gfloat *pixel1,
get_derivative (pixel1, pixel2, derivative);
- sum = 0;
+ sum = 0.0;
for (i = 0; i < 4; i++)
sum += derivative[i];
+ return ((sum / 4.0) > (threshold/100.0));
+}
- return ((sum / 4.0) > threshold);
+static void
+calculate_bleed (GHashTable *h,
+ gfloat *data,
+ gfloat threshold,
+ gfloat max_length,
+ GeglRectangle *rect)
+{
+ gint x, y;
+
+ for (y = 0; y < rect->height; y++)
+ {
+ for (x = 0; x < rect->width - 3; x++)
+ {
+ gfloat pixel1[4];
+ gfloat pixel2[4];
+ get_pixel (x, y, rect->width, data, pixel1);
+ get_pixel (x + 3, y, rect->width, data, pixel2);
+ if (threshold_exceeded (pixel1,
+ pixel2,
+ threshold))
+ {
+ pair *k = g_new (pair, 1);
+ gint *v = g_new (gint, 1);
+ gint bleed_length = 1 + (gint)(g_random_double () * max_length);
+
+ k->x = x;
+ k->y = y;
+
+ *v = bleed_length;
+ g_hash_table_insert (h, k, v);
+ }
+ }
+ }
}
static void prepare (GeglOperation *operation)
@@ -78,7 +150,16 @@ static void prepare (GeglOperation *operation)
op_area = GEGL_OPERATION_AREA_FILTER (operation);
o = GEGL_CHANT_PROPERTIES (operation);
- op_area->left = o->strength; //only from left for now
+ if (o->chant_data)
+ {
+ g_hash_table_destroy (o->chant_data);
+ o->chant_data = NULL;
+ }
+
+ op_area->left = o->strength;
+ op_area->right = o->strength;
+ op_area->top = o->strength;
+ op_area->bottom = o->strength;
gegl_operation_set_format (operation, "input",
babl_format ("RGBA float"));
@@ -102,100 +183,149 @@ process (GeglOperation *operation,
gint n_pixels = result->width * result->height;
GeglRectangle src_rect;
- gfloat *blend_pix; //left edge
- gfloat *target_pix; //normally right edge
- gfloat *base_pix; //input pixel corresponding to write
- gfloat *dst_pix; //write target
+ gfloat *current_pix;
+ gfloat *target_pix;
+ gfloat *dst_pix;
gint x, y;
- gint total_pixels;
+ gint total_src_pixels;
+ gint total_dst_pixels;
- gfloat denominator;
+ gint bleed_max;
+ gint bleed_index;
+ gfloat blend_coefficient;
- gint n;
- gint bleed_length_max;
- gint bleed_length;
+ GHashTable *bleed_table;
- /* code to calculate each left edge and the associated bleed length
- that is randomly generated*/
+ static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+
+ g_static_mutex_lock (&mutex);
+ if (!o->chant_data)
+ {
+ GeglRectangle *whole_rect = gegl_operation_source_get_bounding_box (operation, "input");
+ gfloat *data = (gfloat*) gegl_buffer_linear_open (input, NULL, NULL, babl_format ("RGBA float"));
+
+ bleed_table = g_hash_table_new_full (tuple_hash, tuple_equal, g_free, g_free);
+ calculate_bleed (bleed_table, data, o->threshold, (gfloat) o->strength, whole_rect);
+ o->chant_data = bleed_table;
+ gegl_buffer_linear_close (input, data);
+ }
+ g_static_mutex_unlock (&mutex);
+
+ bleed_table = (GHashTable*) o->chant_data;
src_rect.x = result->x - op_area->left;
src_rect.width = result->width + op_area->left + op_area->right;
src_rect.y = result->y - op_area->top;
src_rect.height = result->height + op_area->top + op_area->bottom;
- total_pixels = src_rect.width * src_rect.height;
+ total_src_pixels = src_rect.width * src_rect.height;
+ total_dst_pixels = result->width * result->height;
- src_buf = g_slice_alloc (4 * total_pixels * sizeof (gfloat));
- dst_buf = g_slice_alloc (4 * total_pixels * sizeof (gfloat));
+ src_buf = g_slice_alloc (4 * total_src_pixels * sizeof (gfloat));
+ dst_buf = g_slice_alloc (4 * total_dst_pixels * sizeof (gfloat));
gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RGBA float"),
src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- //for each pixel
- base_pix = src_buf + 4 * o->strength;
+ current_pix = src_buf + 4*(o->strength + src_rect.width * o->strength);
dst_pix = dst_buf;
x = 0;
y = 0;
n_pixels = result->width * result->height;
- bleed_length = o->strength;
+ bleed_max = 0;
+ bleed_index = 0;
while (n_pixels--)
{
- /* need to check up to the max bleed length to see if there is a left edge
- which bleeds to the current pixel and bleed approriately */
-
gint i;
- denominator = 1.0/(gfloat) bleed_length;;
+ pair key = {x, y};
+ gint *bleed = g_hash_table_lookup (bleed_table, &key);
+
for (i = 0; i < 4; i++)
- dst_pix[i] = base_pix[i];
- for (n = 0; n < bleed_length; n++)
- {
- target_pix = base_pix - 4 * n;
- blend_pix = target_pix - 4 * 3;
- if (x < 3 + n)
- continue;
+ dst_pix[i] = current_pix[i];
- if (threshold_exceeded (blend_pix, target_pix, o->threshold))
+ if (bleed)
+ {
+ gfloat blend_color[4];
+ gfloat blend_amount[4];
+ gfloat *blend_pix;
+
+ bleed_max = *bleed;
+ bleed_index = *bleed;
+ target_pix = current_pix;
+ blend_pix = current_pix - 12;
+ for (i = 0; i < 4; i++)
{
- gfloat blend_color[4];
- gfloat blend_amount[4];
- for (i = 0; i < 4; i++)
- {
- blend_color[i] = blend_pix[i];
- blend_amount[i] = target_pix[i] - blend_pix[i];
- blend_color[i] += blend_amount[i] * (gfloat) n * denominator;
- dst_pix[i] = (2.0 * blend_color[i] + dst_pix[i])/3.0;
- }
+ blend_amount[i] = target_pix[i] - blend_pix[i];
+ blend_color[i] = blend_pix[i] + blend_amount[i];
+ dst_pix[i] = (2.0 * blend_color[i] + dst_pix[i])/3.0;
}
}
- dst_pix += 4;
- /* update x and y coordinates */
+ else if (bleed_index > 0)
+ {
+ gfloat blend_color[4];
+ gfloat blend_amount[4];
+ gfloat *blend_pix;
+ bleed_index--;
+ blend_coefficient = 1.0 - ((gfloat) bleed_index)/(gfloat) bleed_max;
+ blend_pix = current_pix - 4 * (bleed_max - bleed_index) - 12;
+ target_pix = current_pix;
+ for (i = 0; i < 4; i++)
+ {
+ blend_amount[i] = target_pix[i] - blend_pix[i];
+ blend_color[i] = blend_pix[i] + blend_amount[i] * blend_coefficient;
+ dst_pix[i] = (2.0 * blend_color[i] + dst_pix[i])/3.0;
+ }
+ }
+
x++;
- base_pix += 4;
+ current_pix += 4;
+ dst_pix += 4;
if (x >= result->width)
{
+ bleed_max = 0;
+ bleed_index = 0;
x = 0;
y++;
- base_pix += 4 * o->strength;
+ current_pix += 8 * o->strength;
}
}
- gegl_buffer_set (output, result, 0,
+ gegl_buffer_set (output, result, 1,
babl_format ("RGBA float"),
dst_buf, GEGL_AUTO_ROWSTRIDE);
- g_slice_free1 (4 * total_pixels * sizeof (gfloat), src_buf);
- g_slice_free1 (4 * total_pixels * sizeof (gfloat), dst_buf);
+ g_slice_free1 (4 * total_src_pixels * sizeof (gfloat), src_buf);
+ g_slice_free1 (4 * total_dst_pixels * sizeof (gfloat), dst_buf);
+
return TRUE;
}
+
+static void
+finalize (GObject *object)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (object);
+
+ if (o->chant_data)
+ {
+ g_hash_table_destroy (o->chant_data);
+ o->chant_data = NULL;
+ }
+
+ G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
+}
+
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;
filter_class->process = process;
operation_class->prepare = prepare;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]