[gimp] app: speed up gradient rendering a lot
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: speed up gradient rendering a lot
- Date: Tue, 17 Apr 2018 23:20:47 +0000 (UTC)
commit 9dbf919d46aeb9604404d551979b7dd511cb0a8f
Author: Michael Natterer <mitch gimp org>
Date: Wed Apr 18 01:11:33 2018 +0200
app: speed up gradient rendering a lot
by using a cache of colors that is calculated once, instead of
calling gimp_gradient_get_color_at() for each rendered pixel.
app/core/gimpdrawable-gradient.c | 9 ++
app/operations/gimpoperationgradient.c | 159 +++++++++++++-------------------
app/operations/gimpoperationgradient.h | 4 +
app/tools/gimpgradienttool.c | 35 ++++++-
4 files changed, 105 insertions(+), 102 deletions(-)
---
diff --git a/app/core/gimpdrawable-gradient.c b/app/core/gimpdrawable-gradient.c
index 696d7a6..8d56997 100644
--- a/app/core/gimpdrawable-gradient.c
+++ b/app/core/gimpdrawable-gradient.c
@@ -91,6 +91,15 @@ gimp_drawable_gradient (GimpDrawable *drawable,
gimp_drawable_gradient_shapeburst_distmap (drawable, metric,
GEGL_RECTANGLE (x, y, width, height),
progress);
+
+ /* in shapeburst mode, make sure the "line" is long enough to
+ * span across the selection, so the operation's cache has the
+ * right size
+ */
+ startx = x;
+ starty = y;
+ endx = x + width;
+ endy = y + height;
}
render = gegl_node_new_child (NULL,
diff --git a/app/operations/gimpoperationgradient.c b/app/operations/gimpoperationgradient.c
index 8382285..69c5bbe 100644
--- a/app/operations/gimpoperationgradient.c
+++ b/app/operations/gimpoperationgradient.c
@@ -36,8 +36,6 @@
#include "gimpoperationgradient.h"
-//#define USE_GRADIENT_CACHE 1
-
enum
{
PROP_0,
@@ -60,25 +58,16 @@ enum
typedef struct
{
- GimpGradient *gradient;
- gboolean reverse;
- GimpGradientBlendColorSpace blend_color_space;
-#ifdef USE_GRADIENT_CACHE
- GimpRGB *gradient_cache;
- gint gradient_cache_size;
-#else
- GimpGradientSegment *last_seg;
-#endif
- gdouble offset;
- gdouble sx, sy;
- GimpGradientType gradient_type;
- gdouble dist;
- gdouble vec[2];
- GimpRepeatMode repeat;
- GimpRGB leftmost_color;
- GimpRGB rightmost_color;
- GRand *seed;
- GeglBuffer *dist_buffer;
+ GimpGradient *gradient;
+ GimpRGB *gradient_cache;
+ gint gradient_cache_size;
+ gdouble offset;
+ gdouble sx, sy;
+ GimpGradientType gradient_type;
+ gdouble dist;
+ gdouble vec[2];
+ GimpRepeatMode repeat;
+ GeglBuffer *dist_buffer;
} RenderBlendData;
@@ -335,6 +324,7 @@ gimp_operation_gradient_dispose (GObject *object)
g_clear_object (&self->gradient);
g_clear_object (&self->context);
+ g_clear_pointer (&self->gradient_cache, g_free);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -509,7 +499,23 @@ gimp_operation_gradient_set_property (GObject *object,
static void
gimp_operation_gradient_prepare (GeglOperation *operation)
{
+ GimpOperationGradient *self = GIMP_OPERATION_GRADIENT (operation);
+ gint cache_size;
+
gegl_operation_set_format (operation, "output", babl_format ("R'G'B'A float"));
+
+ cache_size = ceil (sqrt (SQR (self->start_x - self->end_x) +
+ SQR (self->start_y - self->end_y))) * 4;
+
+ if (cache_size != self->gradient_cache_size)
+ {
+ g_clear_pointer (&self->gradient_cache, g_free);
+
+ self->gradient_cache = g_new0 (GimpRGB, cache_size);
+ self->gradient_cache_size = cache_size;
+ }
+
+ self->gradient_cache_valid = FALSE;
}
static GeglRectangle
@@ -900,7 +906,6 @@ gradient_render_pixel (gdouble x,
switch (rbd->repeat)
{
- case GIMP_REPEAT_TRUNCATE:
case GIMP_REPEAT_NONE:
break;
@@ -922,30 +927,21 @@ gradient_render_pixel (gdouble x,
factor = 1.0 - factor;
}
break;
+
+ case GIMP_REPEAT_TRUNCATE:
+ if (factor < 0.0 || factor > 1.0)
+ {
+ gimp_rgba_set (color, 0.0, 0.0, 0.0, 0.0);
+ return;
+ }
+ break;
}
/* Blend the colors */
- if (factor <= 0.0)
- {
- *color = rbd->leftmost_color;
- }
- else if (factor >= 1.0)
- {
- *color = rbd->rightmost_color;
- }
- else
- {
-#ifdef USE_GRADIENT_CACHE
- *color = rbd->gradient_cache[(gint) (factor * (rbd->gradient_cache_size - 1))];
-#else
- rbd->last_seg = gimp_gradient_get_color_at (rbd->gradient, NULL,
- rbd->last_seg, factor,
- rbd->reverse,
- rbd->blend_color_space,
- color);
-#endif
- }
+ factor = CLAMP (factor, 0.0, 1.0);
+
+ *color = rbd->gradient_cache[(gint) (factor * (rbd->gradient_cache_size - 1))];
}
static void
@@ -1008,35 +1004,31 @@ gimp_operation_gradient_process (GeglOperation *operation,
RenderBlendData rbd = { 0, };
- rbd.gradient = NULL;
- rbd.reverse = self->gradient_reverse;
- rbd.blend_color_space = self->gradient_blend_color_space;
+ if (! self->gradient)
+ return TRUE;
- if (self->gradient)
- rbd.gradient = g_object_ref (self->gradient);
- else
- rbd.gradient = GIMP_GRADIENT (gimp_gradient_new (NULL, "Gradient-Temp"));
+ if (! self->gradient_cache_valid)
+ {
+ GimpGradientSegment *last_seg = NULL;
+ gint i;
-#ifdef USE_GRADIENT_CACHE
- {
- GimpGradientSegment *last_seg = NULL;
- gint i;
+ for (i = 0; i < self->gradient_cache_size; i++)
+ {
+ gdouble factor = (gdouble) i / (gdouble) (self->gradient_cache_size - 1);
- rbd.gradient_cache_size = ceil (sqrt (SQR (sx - ex) + SQR (sy - ey)));
- rbd.gradient_cache = g_new0 (GimpRGB, rbd.gradient_cache_size);
+ last_seg = gimp_gradient_get_color_at (self->gradient, NULL, last_seg,
+ factor,
+ self->gradient_reverse,
+ self->gradient_blend_color_space,
+ self->gradient_cache + i);
+ }
- for (i = 0; i < rbd.gradient_cache_size; i++)
- {
- gdouble factor = (gdouble) i / (gdouble) (rbd.gradient_cache_size - 1);
+ self->gradient_cache_valid = TRUE;
+ }
- last_seg = gimp_gradient_get_color_at (rbd.gradient, NULL, last_seg,
- factor,
- rbd.reverse,
- rbd.blend_color_space,
- rbd.gradient_cache + i);
- }
- }
-#endif
+ rbd.gradient = self->gradient;
+ rbd.gradient_cache = self->gradient_cache;
+ rbd.gradient_cache_size = self->gradient_cache_size;
/* Calculate type-specific parameters */
@@ -1086,26 +1078,6 @@ gimp_operation_gradient_process (GeglOperation *operation,
rbd.gradient_type = self->gradient_type;
rbd.repeat = self->gradient_repeat;
- if (rbd.repeat == GIMP_REPEAT_NONE)
- {
- gimp_gradient_segment_get_left_flat_color (rbd.gradient, NULL,
- rbd.gradient->segments,
- &rbd.leftmost_color);
- gimp_gradient_segment_get_right_flat_color (rbd.gradient, NULL,
- gimp_gradient_segment_get_last (
- rbd.gradient->segments),
- &rbd.rightmost_color);
-
- if (rbd.reverse)
- {
- GimpRGB temp;
-
- temp = rbd.leftmost_color;
- rbd.leftmost_color = rbd.rightmost_color;
- rbd.rightmost_color = temp;
- }
- }
-
/* Render the gradient! */
if (self->supersample)
@@ -1137,6 +1109,7 @@ gimp_operation_gradient_process (GeglOperation *operation,
{
GeglBufferIterator *iter;
GeglRectangle *roi;
+ GRand *seed = NULL;
iter = gegl_buffer_iterator_new (output, result, 0,
babl_format ("R'G'B'A float"),
@@ -1144,7 +1117,7 @@ gimp_operation_gradient_process (GeglOperation *operation,
roi = &iter->roi[0];
if (self->dither)
- rbd.seed = g_rand_new ();
+ seed = g_rand_new ();
while (gegl_buffer_iterator_next (iter))
{
@@ -1153,9 +1126,9 @@ gimp_operation_gradient_process (GeglOperation *operation,
gint endy = roi->y + roi->height;
gint x, y;
- if (rbd.seed)
+ if (seed)
{
- GRand *dither_rand = g_rand_new_with_seed (g_rand_int (rbd.seed));
+ GRand *dither_rand = g_rand_new_with_seed (g_rand_int (seed));
for (y = roi->y; y < endy; y++)
for (x = roi->x; x < endx; x++)
@@ -1201,14 +1174,8 @@ gimp_operation_gradient_process (GeglOperation *operation,
}
if (self->dither)
- g_rand_free (rbd.seed);
+ g_rand_free (seed);
}
-#ifdef USE_GRADIENT_CACHE
- g_free (rbd.gradient_cache);
-#endif
-
- g_object_unref (rbd.gradient);
-
return TRUE;
}
diff --git a/app/operations/gimpoperationgradient.h b/app/operations/gimpoperationgradient.h
index b63686a..5f29464 100644
--- a/app/operations/gimpoperationgradient.h
+++ b/app/operations/gimpoperationgradient.h
@@ -55,6 +55,10 @@ struct _GimpOperationGradient
gdouble supersample_threshold;
gboolean dither;
+
+ GimpRGB *gradient_cache;
+ gint gradient_cache_size;
+ gboolean gradient_cache_valid;
};
struct _GimpOperationGradientClass
diff --git a/app/tools/gimpgradienttool.c b/app/tools/gimpgradienttool.c
index b66b15b..d4278aa 100644
--- a/app/tools/gimpgradienttool.c
+++ b/app/tools/gimpgradienttool.c
@@ -909,12 +909,35 @@ gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
else
#endif
{
- gegl_node_set (gradient_tool->render_node,
- "start_x", gradient_tool->start_x - off_x,
- "start_y", gradient_tool->start_y - off_y,
- "end_x", gradient_tool->end_x - off_x,
- "end_y", gradient_tool->end_y - off_y,
- NULL);
+ if (gimp_gradient_tool_is_shapeburst (gradient_tool))
+ {
+ /* in shapeburst mode, make sure the "line" is long enough
+ * to span across the selection, so the operation's cache
+ * has the right size
+ */
+
+ GimpImage *image = gimp_display_get_image (tool->display);
+ gdouble x, y, w, h;
+
+ gimp_item_bounds_f (GIMP_ITEM (gimp_image_get_mask (image)),
+ &x, &y, &w, &h);
+
+ gegl_node_set (gradient_tool->render_node,
+ "start-x", x,
+ "start-y", y,
+ "end-x", x + w,
+ "end-y", y + h,
+ NULL);
+ }
+ else
+ {
+ gegl_node_set (gradient_tool->render_node,
+ "start-x", gradient_tool->start_x - off_x,
+ "start-y", gradient_tool->start_y - off_y,
+ "end-x", gradient_tool->end_x - off_x,
+ "end-y", gradient_tool->end_y - off_y,
+ NULL);
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]