[gegl/soc-2012-ops] Oilify Operation: Stop using samplers.
- From: Hans Shu Lo <hanslo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2012-ops] Oilify Operation: Stop using samplers.
- Date: Fri, 13 Jul 2012 00:43:25 +0000 (UTC)
commit 64aa3ad91f2c09704d90ab6077f8e34ddbdb4e25
Author: Hans Lo <hansshulo gmail com>
Date: Thu Jul 12 18:36:27 2012 -0400
Oilify Operation: Stop using samplers.
Significant speed up.
operations/common/oilify.c | 284 +++++++++++++++++++++++++++-----------------
1 files changed, 173 insertions(+), 111 deletions(-)
---
diff --git a/operations/common/oilify.c b/operations/common/oilify.c
index 7afb6c4..5c3e97f 100644
--- a/operations/common/oilify.c
+++ b/operations/common/oilify.c
@@ -24,16 +24,14 @@
#ifdef GEGL_CHANT_PROPERTIES
-gegl_chant_double (mask_radius, _("Mask Radius"), 1.0, 25.0, 4.0,
- _("Radius of circle around pixel"))
+gegl_chant_int (mask_radius, _("Mask Radius"), 1, 25, 4,
+ _("Radius of circle around pixel"))
gegl_chant_double (exponent, _("Exponent"), 1.0, 20.0, 8.0,
_("Exponent"))
-gegl_chant_boolean (use_inten, _("Intensity Mode"), TRUE, _("Use pixel luminance values"))
-
-gegl_chant_enum (sampler_type, _("Sampler"), GeglSamplerType, gegl_sampler_type,
- GEGL_SAMPLER_CUBIC, _("Sampler used internally"))
+gegl_chant_boolean (use_inten, _("Intensity Mode"), TRUE,
+ _("Use pixel luminance values"))
#else
@@ -46,18 +44,48 @@ gegl_chant_enum (sampler_type, _("Sampler"), GeglSamplerType, gegl_sampler_type,
#define NUM_INTENSITIES 256
- static void oilify_pixel (gint x,
- gint y,
- gboolean use_inten,
- gdouble radius,
- gdouble exponent,
- GeglSampler *sampler,
- GeglSampler *sampler_inten,
- gfloat *dst_pixel)
+/* Get the pixel from x, y offset from the center pixel src_pix */
+static 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];
+ }
+}
+
+static void
+get_pixel_inten(gint x,
+ gint y,
+ gint buf_width,
+ gfloat* inten_begin,
+ gfloat* dst)
+{
+ *dst = *(inten_begin + (x + buf_width*y));
+}
+
+static void
+oilify_pixel (gint x,
+ gint y,
+ GeglRectangle *whole_rect,
+ gboolean use_inten,
+ gdouble radius,
+ gdouble exponent,
+ gint buf_width,
+ gfloat *src_buf,
+ gfloat *inten_buf,
+ gfloat *dst_pixel)
{
gint hist[4][NUM_INTENSITIES];
gfloat cumulative_rgb[4][NUM_INTENSITIES];
gint hist_inten[NUM_INTENSITIES];
+ gfloat mult_inten[NUM_INTENSITIES];
gfloat temp_pixel[4];
gfloat temp_inten_pixel;
gint ceil_radius = ceil(radius);
@@ -71,99 +99,118 @@ gegl_chant_enum (sampler_type, _("Sampler"), GeglSamplerType, gegl_sampler_type,
gfloat weight;
gfloat color;
gfloat result;
-
+ gfloat div;
for (i = 0; i < NUM_INTENSITIES; i++)
{
hist_inten[i] = 0;
for (b = 0; b < 4; b++)
- {
- hist[b][i] = 0;
- cumulative_rgb[b][i] = 0.0;
- }
+ {
+ hist[b][i] = 0;
+ cumulative_rgb[b][i] = 0.0;
+ }
}
- for (i = -ceil_radius; i < ceil_radius; i++)
+ /* calculate histograms */
+ for (i = -ceil_radius; i <= ceil_radius; i++)
{
- for (j = -ceil_radius; j < ceil_radius; j++)
- {
- if (i*i + j*j < radius_sq)
- {
- gegl_sampler_get (sampler,
- x+i,
- y+j,
- NULL,
- temp_pixel);
-
- if (use_inten)
- {
-
- gegl_sampler_get (sampler_inten,
- x+i,
- y+j,
- NULL,
- &temp_inten_pixel);
- intensity = temp_inten_pixel * NUM_INTENSITIES;
- hist_inten[intensity]++;
- for (b = 0; b < 4; b++)
- {
- cumulative_rgb[b][intensity] += temp_pixel[b];
- }
- }
- else
- {
- for (b = 0; b < 4; b++)
- {
- intensity = temp_pixel[b] * NUM_INTENSITIES;
- hist[b][intensity]++;
- }
- }
- }
- }
+ for (j = -ceil_radius; j <= ceil_radius; j++)
+ {
+ if (i*i + j*j <= radius_sq)
+ {
+ if (x + i < 0 ||
+ x + i > whole_rect->width ||
+ y + j < 0 ||
+ y + j > whole_rect->height)
+ {
+ if (x + i < 0)
+ g_print("%d %d\n", x+i, y+j);
+ continue;
+ }
+ get_pixel (x + i,
+ y + j,
+ buf_width,
+ src_buf,
+ temp_pixel);
+
+ if (use_inten)
+ {
+ get_pixel_inten (x + i,
+ y + j,
+ buf_width,
+ inten_buf,
+ &temp_inten_pixel);
+ intensity = temp_inten_pixel * NUM_INTENSITIES;
+ hist_inten[intensity]++;
+ for (b = 0; b < 4; b++)
+ {
+ cumulative_rgb[b][intensity] += temp_pixel[b];
+ }
+ }
+ else
+ {
+ for (b = 0; b < 4; b++)
+ {
+ intensity = temp_pixel[b] * NUM_INTENSITIES;
+ hist[b][intensity]++;
+ }
+ }
+ }
+ }
}
-
+
inten_max = 1;
/* calculated maximums */
for (i = 0; i < NUM_INTENSITIES; i++) {
inten_max = MAX (inten_max, hist_inten[i]);
}
-
- for (b = 0; b < 4; b++)
+
+ for (b = 0; b < 4; b++)
{
hist_max[b] = 1;
for (i = 0; i < NUM_INTENSITIES; i++) {
- hist_max[b] = MAX (hist_max[b], hist[b][i]);
+ hist_max[b] = MAX (hist_max[b], hist[b][i]);
}
}
-
+
/* calculate weight and use it to set the pixel */
- for (b = 0; b < 4; b++)
+ div = 0.0;
+ for (i = 0; i < NUM_INTENSITIES; i++)
+ {
+ if (use_inten && hist_inten[i] > 0)
+ {
+ ratio = (gfloat) hist_inten[i] / (gfloat) inten_max;
+ weight = pow (ratio, exponent);
+ mult_inten[i] = weight / (gfloat) hist_inten[i];
+ div += weight;
+ }
+ }
+ for (b = 0; b < 4; b++)
{
sum = 0.0;
color = 0.0;
if (use_inten)
- {
- for (i = 0; i < NUM_INTENSITIES; i++)
- {
- ratio = (gfloat) hist_inten[i] / (gfloat) inten_max;
- weight = pow (ratio, exponent);
- if (hist_inten[i] > 0)
- color += weight * cumulative_rgb[b][i] / (gfloat) hist_inten[i];
- }
- result = color;
- dst_pixel[b] = result;
- }
+ {
+ for (i = 0; i < NUM_INTENSITIES; i++)
+ {
+ if (hist_inten[i] > 0)
+ color += mult_inten[i] * cumulative_rgb[b][i];
+ }
+ dst_pixel[b] = color/div;
+ }
else
- {
- for (i = 0; i < NUM_INTENSITIES; i++)
- {
- ratio = (gfloat) hist[b][i] / (gfloat) hist_max[b];
- weight = pow (ratio, exponent);
- sum += weight * (gfloat) i;
- }
- result = sum / (gfloat) NUM_INTENSITIES;
- dst_pixel[b] = result;
- }
+ {
+ div = 0.0;
+ for (i = 0; i < NUM_INTENSITIES; i++)
+ {
+ ratio = (gfloat) hist[b][i] / (gfloat) hist_max[b];
+ weight = pow (ratio, exponent);
+ sum += weight * (gfloat) i;
+ div += weight;
+ }
+ result = sum / (gfloat) NUM_INTENSITIES;
+ dst_pixel[b] = result/div;
+ }
}
}
@@ -175,9 +222,9 @@ static void prepare (GeglOperation *operation)
op_area = GEGL_OPERATION_AREA_FILTER (operation);
o = GEGL_CHANT_PROPERTIES (operation);
- op_area->left =
- op_area->right =
- op_area->top =
+ op_area->left =
+ op_area->right =
+ op_area->top =
op_area->bottom = o->mask_radius;
gegl_operation_set_format (operation, "input",
@@ -194,50 +241,65 @@ process (GeglOperation *operation,
gint level)
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
+
+ GeglRectangle* whole_rect;
+ gint x = o->mask_radius; /* initial x */
+ gint y = o->mask_radius; /* and y coordinates */
+ gfloat *src_buf;
+ gfloat *dst_buf;
+ gfloat *inten_buf;
+ gfloat *out_pixel;
+ gint n_pixels = result->width * result->height;
+ GeglRectangle src_rect;
+ gint total_pixels;
- gint x = result->x; /* initial x */
- gint y = result->y; /* and y coordinates */
-
- gfloat *dst_buf = g_slice_alloc (result->width * result->height * 4 * sizeof(gfloat));
+ whole_rect = gegl_operation_source_get_bounding_box (operation, "input");
- gfloat *out_pixel = dst_buf;
+ 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;
- GeglSampler *sampler = gegl_buffer_sampler_new (input,
- babl_format ("RGBA float"),
- o->sampler_type);
+ total_pixels = src_rect.width * src_rect.height;
- GeglSampler *sampler_inten = gegl_buffer_sampler_new (input,
- babl_format ("Y float"),
- o->sampler_type);
+ src_buf = g_slice_alloc (4 * total_pixels * sizeof(gfloat));
+ dst_buf = g_slice_alloc (4 * total_pixels * sizeof(gfloat));
+ inten_buf = g_slice_alloc (total_pixels * sizeof(gfloat));
- gint n_pixels = result->width * result->height;
+ gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RGBA float"),
+ src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+ gegl_buffer_get (input, &src_rect, 1.0, babl_format ("Y float"),
+ inten_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+ out_pixel = dst_buf;
while (n_pixels--)
{
-
- oilify_pixel(x, y, o->use_inten, o->mask_radius, o->exponent,
- sampler, sampler_inten, out_pixel);
+ oilify_pixel(x, y, whole_rect, o->use_inten, o->mask_radius, o->exponent,
+ src_rect.width, src_buf, inten_buf, out_pixel);
out_pixel += 4;
/* update x and y coordinates */
x++;
- if (x>=result->x + result->width)
+ if (x >= result->width + o->mask_radius)
{
- x=result->x;
+ x=o->mask_radius;
y++;
}
}
- gegl_buffer_set (output, result, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
- g_slice_free1 (result->width * result->height * 4 * sizeof(gfloat), dst_buf);
-
- g_object_unref (sampler);
+ gegl_buffer_set (output, result, 0,
+ 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 (total_pixels * sizeof(gfloat), inten_buf);
return TRUE;
}
-
static void
gegl_chant_class_init (GeglChantClass *klass)
{
@@ -251,9 +313,9 @@ gegl_chant_class_init (GeglChantClass *klass)
operation_class->prepare = prepare;
gegl_operation_class_set_keys (operation_class,
- "categories" , "artistic",
- "name" , "gegl:oilify",
- "description", _("Emulate an oil painting"),
- NULL);
+ "categories" , "artistic",
+ "name" , "gegl:oilify",
+ "description", _("Emulate an oil painting"),
+ NULL);
}
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]