[gegl] c2g, stress: use sampler and iterator instead of temporary linear buffers
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] c2g, stress: use sampler and iterator instead of temporary linear buffers
- Date: Sun, 15 Jun 2014 07:06:45 +0000 (UTC)
commit 73a88d2d8f72f1c6babd0aabd76137d5a5660e1b
Author: Øyvind Kolås <pippin gimp org>
Date: Sun Jun 15 08:03:24 2014 +0200
c2g,stress: use sampler and iterator instead of temporary linear buffers
For low radiuses, this makes the op slower - but for larger radiuses it makes
it faster since the temporary memory requirements does not scale with the
radius.
operations/common/c2g.c | 131 ++++++++++++++++++++---------------------
operations/common/envelopes.h | 67 +++++++++-------------
operations/common/stress.c | 99 ++++++++++++++++---------------
3 files changed, 140 insertions(+), 157 deletions(-)
---
diff --git a/operations/common/c2g.c b/operations/common/c2g.c
index aa3e74b..3bd4490 100644
--- a/operations/common/c2g.c
+++ b/operations/common/c2g.c
@@ -28,7 +28,7 @@ property_int (radius, _("Radius"), 300)
description(_("Neighborhood taken into account, this is the radius "
"in pixels taken into account when deciding which "
"colors map to which gray values"))
- value_range (2, 3000)
+ value_range (2, 6000)
ui_range (2, 1000)
ui_gamma (1.6)
ui_meta ("unit", "pixel-distance")
@@ -36,13 +36,13 @@ property_int (radius, _("Radius"), 300)
property_int (samples, _("Samples"), 4)
description (_("Number of samples to do per iteration looking for the range of colors"))
value_range (1, 1000)
- ui_range (1, 20)
+ ui_range (3, 17)
property_int (iterations, _("Iterations"), 10)
description(_("Number of iterations, a higher number of iterations "
"provides less noisy results at a computational cost"))
value_range (1, 1000)
- ui_range (1, 20)
+ ui_range (1, 30)
/*
property_double (rgamma, _("Radial Gamma"), 0.0, 8.0, 2.0,
@@ -56,7 +56,7 @@ property_double (rgamma, _("Radial Gamma"), 0.0, 8.0, 2.0,
#include "gegl-op.h"
#include <math.h>
#include <stdlib.h>
-#include "envelopes.h"
+#include "envelopes2.h"
#define RGAMMA 2.0
@@ -69,76 +69,71 @@ static void c2g (GeglBuffer *src,
gint iterations,
gdouble rgamma)
{
- gint x,y;
- gint dst_offset=0;
- gfloat *src_buf;
- gfloat *dst_buf;
- gint inw = src_rect->width;
- gint outw = dst_rect->width;
- gint inh = src_rect->height;
-
- src_buf = g_new0 (gfloat, src_rect->width * src_rect->height * 4);
- dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 2);
-
- gegl_buffer_get (src, src_rect, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE,
- GEGL_ABYSS_NONE);
+ const Babl *format = babl_format ("RGBA float");
+
+ if (dst_rect->width > 0 && dst_rect->height > 0)
+ {
+ GeglBufferIterator *i = gegl_buffer_iterator_new (dst, dst_rect, 0, babl_format("YA float"),
GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+ GeglSampler *sampler = gegl_buffer_sampler_new (src, format, GEGL_SAMPLER_NEAREST);
- for (y=radius; y<dst_rect->height+radius; y++)
+ while (gegl_buffer_iterator_next (i))
{
- gint src_offset = (inw*y+radius)*4;
- for (x=radius; x<outw+radius; x++)
- {
- gfloat *pixel= src_buf + src_offset;
- gfloat min[4];
- gfloat max[4];
-
- compute_envelopes (src_buf,
- inw, inh,
- x, y,
- radius, samples,
- iterations,
- FALSE, /* same spray */
- rgamma,
- min, max);
- {
- /* this should be replaced with a better/faster projection of
- * pixel onto the vector spanned by min -> max, currently
- * computed by comparing the distance to min with the sum
- * of the distance to min/max.
- */
-
- gfloat nominator = 0;
- gfloat denominator = 0;
- gint c;
- for (c=0; c<3; c++)
- {
- nominator += (pixel[c] - min[c]) * (pixel[c] - min[c]);
- denominator += (pixel[c] - max[c]) * (pixel[c] - max[c]);
- }
+ gint x,y;
+ gint dst_offset=0;
+ gfloat *dst_buf = i->data[0];
- nominator = sqrt (nominator);
- denominator = sqrt (denominator);
- denominator = nominator + denominator;
-
- if (denominator>0.000)
- {
- dst_buf[dst_offset+0] = nominator/denominator;
- }
- else
+ for (y=i->roi[0].y; y < i->roi[0].y + i->roi[0].height; y++)
+ {
+ for (x=i->roi[0].x; x < i->roi[0].x + i->roi[0].width; x++)
+ {
+ gfloat min[4];
+ gfloat max[4];
+ gfloat pixel[4];
+
+ compute_envelopes (src, sampler,
+ x, y,
+ radius, samples,
+ iterations,
+ FALSE, /* same spray */
+ rgamma,
+ min, max, pixel, format);
{
- /* shouldn't happen */
- dst_buf[dst_offset+0] = 0.5;
+ /* this should be replaced with a better/faster projection of
+ * pixel onto the vector spanned by min -> max, currently
+ * computed by comparing the distance to min with the sum
+ * of the distance to min/max.
+ */
+
+ gfloat nominator = 0;
+ gfloat denominator = 0;
+ gint c;
+ for (c=0; c<3; c++)
+ {
+ nominator += (pixel[c] - min[c]) * (pixel[c] - min[c]);
+ denominator += (pixel[c] - max[c]) * (pixel[c] - max[c]);
+ }
+
+ nominator = sqrtf (nominator);
+ denominator = sqrtf (denominator);
+ denominator = nominator + denominator;
+
+ if (denominator>0.000)
+ {
+ dst_buf[dst_offset+0] = nominator/denominator;
+ }
+ else
+ {
+ /* shouldn't happen */
+ dst_buf[dst_offset+0] = 0.5;
+ }
+ dst_buf[dst_offset+1] = pixel[3];
+ dst_offset+=2;
}
- dst_buf[dst_offset+1] = src_buf[src_offset+3];
-
- src_offset+=4;
- dst_offset+=2;
+ }
}
- }
}
- gegl_buffer_set (dst, dst_rect, 0, babl_format ("YA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
- g_free (src_buf);
- g_free (dst_buf);
+ g_object_unref (sampler);
+ }
}
static void prepare (GeglOperation *operation)
diff --git a/operations/common/envelopes.h b/operations/common/envelopes.h
index 40e3b4a..2180de8 100644
--- a/operations/common/envelopes.h
+++ b/operations/common/envelopes.h
@@ -52,43 +52,28 @@ static void compute_luts(gdouble rgamma)
}
static inline void
-sample (gfloat *buf,
- gint width,
- gint height,
- gint x,
- gint y,
- gfloat *dst)
-{
- gfloat *pixel = (buf + ((width * y) + x) * 4);
- gint c;
-
- for (c=0;c<4;c++)
- {
- dst[c] = pixel[c];
- }
-}
-
-static inline void
-sample_min_max (gfloat *buf,
- gint width,
- gint height,
- gint x,
- gint y,
- gint radius,
- gint samples,
- gfloat *min,
- gfloat *max)
+sample_min_max (GeglBuffer *buffer,
+ GeglSampler *sampler,
+ gint x,
+ gint y,
+ gint radius,
+ gint samples,
+ gfloat *min,
+ gfloat *max,
+ gfloat *pixel,
+ const Babl *format)
{
gfloat best_min[3];
gfloat best_max[3];
- gfloat *center_pix = (buf + (width * y + x) * 4);
-
+ gint width = gegl_buffer_get_width (buffer);
+ gint height = gegl_buffer_get_height (buffer);
+
gint i, c;
for (c=0;c<3;c++)
{
- best_min[c]=center_pix[c];
- best_max[c]=center_pix[c];
+ best_min[c]=pixel[c];
+ best_max[c]=pixel[c];
}
for (i=0; i<samples; i++)
@@ -119,7 +104,8 @@ retry: /* if we've sampled outside the valid image
goto retry;
{
- gfloat *pixel = (buf + ((width * v) + u) * 4);
+ gfloat pixel[4];
+ gegl_sampler_get (sampler, u, v, NULL, (void*)(&pixel[0]), GEGL_ABYSS_CLAMP);
if (pixel[3]>0.0) /* ignore fully transparent pixels */
{
@@ -145,9 +131,8 @@ retry: /* if we've sampled outside the valid image
}
}
-static inline void compute_envelopes (gfloat *buf,
- gint width,
- gint height,
+static inline void compute_envelopes (GeglBuffer *buffer,
+ GeglSampler *sampler,
gint x,
gint y,
gint radius,
@@ -156,13 +141,16 @@ static inline void compute_envelopes (gfloat *buf,
gboolean same_spray,
gdouble rgamma,
gfloat *min_envelope,
- gfloat *max_envelope)
+ gfloat *max_envelope,
+ gfloat *pixel,
+ const Babl *format)
{
gint i;
gint c;
gfloat range_sum[4] = {0,0,0,0};
gfloat relative_brightness_sum[4] = {0,0,0,0};
- gfloat *pixel = buf + (width*y+x)*4;
+
+ gegl_sampler_get (sampler, x, y, NULL, (void*)(&pixel[0]), GEGL_ABYSS_CLAMP);
/* compute lookuptables for the gamma, currently not used/exposed
* as a tweakable property */
@@ -178,12 +166,11 @@ static inline void compute_envelopes (gfloat *buf,
{
gfloat min[3], max[3];
- sample_min_max (buf,
- width,
- height,
+ sample_min_max (buffer,
+ sampler,
x, y,
radius, samples,
- min, max);
+ min, max, pixel, format);
for (c=0;c<3;c++)
{
diff --git a/operations/common/stress.c b/operations/common/stress.c
index a402705..7be3cae 100644
--- a/operations/common/stress.c
+++ b/operations/common/stress.c
@@ -26,19 +26,20 @@
property_int (radius, _("Radius"), 300)
description(_("Neighborhood taken into account, for enhancement ideal values are close to the longest
side of the image, increasing this increases the runtime"))
- value_range (2, 5000)
- ui_range (2, 2000)
+ value_range (2, 6000)
+ ui_range (2, 1000)
+ ui_gamma (1.6)
ui_meta ("unit", "pixel-distance")
property_int (samples, _("Samples"), 5)
description(_("Number of samples to do per iteration looking for the range of colors"))
- value_range (2, 200)
- ui_range (2, 10)
+ value_range (2, 500)
+ ui_range (3, 17)
property_int (iterations, _("Iterations"), 5)
description(_("Number of iterations, a higher number of iterations provides a less noisy rendering at a
computational cost"))
- value_range (1, 200)
- ui_range (1, 10)
+ value_range (1, 1000)
+ ui_range (1, 30)
/*
@@ -72,64 +73,64 @@ static void stress (GeglBuffer *src,
gint iterations,
gdouble rgamma)
{
- gint x,y;
- gint dst_offset=0;
- gfloat *src_buf;
- gfloat *dst_buf;
- gint inw = src_rect->width;
- gint inh = src_rect->height;
- gint outw = dst_rect->width;
-
- /* this use of huge linear buffers should be avoided and
- * most probably would lead to great speed ups
- */
-
- src_buf = g_new0 (gfloat, src_rect->width * src_rect->height * 4);
- dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 4);
-
- gegl_buffer_get (src, src_rect, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE,
GEGL_ABYSS_NONE);
-
- for (y=radius; y<dst_rect->height+radius; y++)
+ const Babl *format = babl_format ("RGBA float");
+
+ if (dst_rect->width > 0 && dst_rect->height > 0)
+ {
+ GeglBufferIterator *i = gegl_buffer_iterator_new (dst, dst_rect, 0, babl_format("RaGaBaA float"),
GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+ GeglSampler *sampler = gegl_buffer_sampler_new (src, format, GEGL_SAMPLER_NEAREST);
+
+ while (gegl_buffer_iterator_next (i))
{
- gint src_offset = (inw*y+radius)*4;
- for (x=radius; x<outw+radius; x++)
+ gint x,y;
+ gint dst_offset=0;
+ gfloat *dst_buf = i->data[0];
+
+ for (y=i->roi[0].y; y < i->roi[0].y + i->roi[0].height; y++)
{
- gfloat *center_pix= src_buf + src_offset;
- gfloat min_envelope[4];
- gfloat max_envelope[4];
-
- compute_envelopes (src_buf,
- inw, inh,
- x, y,
- radius, samples,
- iterations,
- FALSE, /* same-spray */
- rgamma,
- min_envelope, max_envelope);
- {
+ for (x=i->roi[0].x; x < i->roi[0].x + i->roi[0].width; x++)
+ {
+ gfloat min[4];
+ gfloat max[4];
+ gfloat pixel[4];
+
+ compute_envelopes (src, sampler,
+ x, y,
+ radius, samples,
+ iterations,
+ FALSE, /* same spray */
+ rgamma,
+ min, max, pixel, format);
+ {
+ /* this should be replaced with a better/faster projection of
+ * pixel onto the vector spanned by min -> max, currently
+ * computed by comparing the distance to min with the sum
+ * of the distance to min/max.
+ */
+
gint c;
for (c=0;c<3;c++)
{
- gfloat delta = max_envelope[c]-min_envelope[c];
+ gfloat delta = max[c]-min[c];
if (delta != 0)
{
dst_buf[dst_offset+c] =
- (center_pix[c]-min_envelope[c])/delta;
+ (pixel[c]-min[c])/delta;
}
else
{
dst_buf[dst_offset+c] = 0.5;
}
}
- }
- dst_buf[dst_offset+3] = src_buf[src_offset+3];
- src_offset+=4;
- dst_offset+=4;
- }
+
+ dst_buf[dst_offset+3] = pixel[3];
+ dst_offset+=4;
+ }
+ }
+ }
}
- gegl_buffer_set (dst, dst_rect, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
- g_free (src_buf);
- g_free (dst_buf);
+ g_object_unref (sampler);
+ }
}
static void prepare (GeglOperation *operation)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]