[gimp] app: add gimp_gegl_replace() as replacement for combine_regions_replace()
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add gimp_gegl_replace() as replacement for combine_regions_replace()
- Date: Sun, 6 May 2012 20:52:21 +0000 (UTC)
commit b2c4bd5d3f098be3758ef72df71d611f2eeb6c39
Author: Michael Natterer <mitch gimp org>
Date: Sun May 6 19:50:46 2012 +0200
app: add gimp_gegl_replace() as replacement for combine_regions_replace()
and use it in gimp_drawable_real_replace_buffer(). The new GEGL loop
is a stupid 1:1 copy of legacy and needs improvement.
app/core/gimpdrawable-combine.c | 86 +++++++++-----------------------
app/gegl/gimp-gegl-loops.c | 105 +++++++++++++++++++++++++++++++++++++++
app/gegl/gimp-gegl-loops.h | 11 ++++
3 files changed, 139 insertions(+), 63 deletions(-)
---
diff --git a/app/core/gimpdrawable-combine.c b/app/core/gimpdrawable-combine.c
index ca759e5..f8a2011 100644
--- a/app/core/gimpdrawable-combine.c
+++ b/app/core/gimpdrawable-combine.c
@@ -268,50 +268,10 @@ gimp_drawable_real_replace_buffer (GimpDrawable *drawable,
GimpImage *image = gimp_item_get_image (item);
GimpChannel *mask = gimp_image_get_mask (image);
GeglBuffer *drawable_buffer;
- GimpTempBuf *temp_buf;
- PixelRegion src2PR;
- PixelRegion maskPR;
gint x, y, width, height;
gint offset_x, offset_y;
- PixelRegion src1PR, destPR;
gboolean active_components[MAX_CHANNELS];
- temp_buf = gimp_gegl_buffer_get_temp_buf (buffer);
-
- if (temp_buf)
- {
- pixel_region_init_temp_buf (&src2PR, temp_buf,
- buffer_region->x, buffer_region->y,
- buffer_region->width, buffer_region->height);
- }
- else
- {
- pixel_region_init (&src2PR, gimp_gegl_buffer_get_tiles (buffer),
- buffer_region->x, buffer_region->y,
- buffer_region->width, buffer_region->height,
- FALSE);
- }
-
- temp_buf = gimp_gegl_buffer_get_temp_buf (mask_buffer);
-
- if (temp_buf)
- {
- pixel_region_init_temp_buf (&maskPR, temp_buf,
- mask_buffer_region->x,
- mask_buffer_region->y,
- mask_buffer_region->width,
- mask_buffer_region->height);
- }
- else
- {
- pixel_region_init (&maskPR, gimp_gegl_buffer_get_tiles (mask_buffer),
- mask_buffer_region->x,
- mask_buffer_region->y,
- mask_buffer_region->width,
- mask_buffer_region->height,
- FALSE);
- }
-
/* don't apply the mask to itself and don't apply an empty mask */
if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask))
mask = NULL;
@@ -323,7 +283,8 @@ gimp_drawable_real_replace_buffer (GimpDrawable *drawable,
gimp_item_get_offset (item, &offset_x, &offset_y);
/* make sure the image application coordinates are within drawable bounds */
- gimp_rectangle_intersect (dest_x, dest_y, src2PR.w, src2PR.h,
+ gimp_rectangle_intersect (dest_x, dest_y,
+ buffer_region->width, buffer_region->height,
0, 0,
gimp_item_get_width (item),
gimp_item_get_height (item),
@@ -351,20 +312,8 @@ gimp_drawable_real_replace_buffer (GimpDrawable *drawable,
drawable_buffer = gimp_drawable_get_buffer (drawable);
- /* configure the pixel regions */
- pixel_region_init (&src1PR, gimp_gegl_buffer_get_tiles (drawable_buffer),
- x, y, width, height,
- FALSE);
- pixel_region_init (&destPR, gimp_gegl_buffer_get_tiles (drawable_buffer),
- x, y, width, height,
- TRUE);
- pixel_region_resize (&src2PR,
- src2PR.x + (x - dest_x), src2PR.y + (y - dest_y),
- width, height);
-
if (mask)
{
- PixelRegion tempPR;
GimpTempBuf *temp_buf;
GeglBuffer *src_buffer;
GeglBuffer *dest_buffer;
@@ -386,20 +335,31 @@ gimp_drawable_real_replace_buffer (GimpDrawable *drawable,
dest_buffer, GEGL_RECTANGLE (0, 0, width, height),
1.0);
- g_object_unref (dest_buffer);
-
- pixel_region_init_temp_buf (&tempPR, temp_buf, 0, 0, width, height);
-
- combine_regions_replace (&src1PR, &src2PR, &destPR, &tempPR,
- opacity * 255.999,
- active_components);
+ gimp_gegl_replace (buffer,
+ buffer_region,
+ drawable_buffer,
+ GEGL_RECTANGLE (x, y, width, height),
+ dest_buffer,
+ GEGL_RECTANGLE (0, 0, width, height),
+ drawable_buffer,
+ GEGL_RECTANGLE (x, y, width, height),
+ opacity * 255.999,
+ active_components);
+ g_object_unref (dest_buffer);
gimp_temp_buf_unref (temp_buf);
}
else
{
- combine_regions_replace (&src1PR, &src2PR, &destPR, &maskPR,
- opacity * 255.999,
- active_components);
+ gimp_gegl_replace (buffer,
+ buffer_region,
+ drawable_buffer,
+ GEGL_RECTANGLE (x, y, width, height),
+ mask_buffer,
+ mask_buffer_region,
+ drawable_buffer,
+ GEGL_RECTANGLE (x, y, width, height),
+ opacity * 255.999,
+ active_components);
}
}
diff --git a/app/gegl/gimp-gegl-loops.c b/app/gegl/gimp-gegl-loops.c
index badf5f8..785bfa8 100644
--- a/app/gegl/gimp-gegl-loops.c
+++ b/app/gegl/gimp-gegl-loops.c
@@ -470,3 +470,108 @@ gimp_gegl_combine_mask (GeglBuffer *mask_buffer,
}
}
}
+
+void
+gimp_gegl_replace (GeglBuffer *top_buffer,
+ const GeglRectangle *top_rect,
+ GeglBuffer *bottom_buffer,
+ const GeglRectangle *bottom_rect,
+ GeglBuffer *mask_buffer,
+ const GeglRectangle *mask_rect,
+ GeglBuffer *dest_buffer,
+ const GeglRectangle *dest_rect,
+ guchar opacity,
+ const gboolean *affect)
+{
+ GeglBufferIterator *iter;
+ const gint alpha = 4 - 1;
+ const gdouble norm_opacity = opacity * (1.0 / 65536.0);
+
+ iter = gegl_buffer_iterator_new (top_buffer, top_rect, 0,
+ babl_format ("R'G'B'A u8"),
+ GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+ gegl_buffer_iterator_add (iter, bottom_buffer, bottom_rect, 0,
+ babl_format ("R'G'B'A u8"),
+ GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+ gegl_buffer_iterator_add (iter, mask_buffer, mask_rect, 0,
+ babl_format ("Y u8"),
+ GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+ gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
+ babl_format ("R'G'B'A u8"),
+ GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+
+ while (gegl_buffer_iterator_next (iter))
+ {
+ const guchar *top = iter->data[0];
+ const guchar *bottom = iter->data[1];
+ const guchar *mask = iter->data[2];
+ guchar *dest = iter->data[3];
+
+ while (iter->length--)
+ {
+ guint b;
+ gdouble mask_val = mask[0] * norm_opacity;
+
+ /* calculate new alpha first. */
+ gint s1_a = bottom[alpha];
+ gint s2_a = top[alpha];
+ gdouble a_val = s1_a + mask_val * (s2_a - s1_a);
+
+ if (a_val == 0)
+ {
+ /* In any case, write out versions of the blending
+ * function that result when combinations of s1_a, s2_a,
+ * and mask_val --> 0 (or mask_val -->1)
+ */
+
+ /* 1: s1_a, s2_a, AND mask_val all approach 0+: */
+ /* 2: s1_a AND s2_a both approach 0+, regardless of mask_val: */
+ if (s1_a + s2_a == 0.0)
+ {
+ for (b = 0; b < alpha; b++)
+ {
+ gint new_val = 0.5 + (gdouble) bottom[b] +
+ mask_val * ((gdouble) top[b] - (gdouble) bottom[b]);
+
+ dest[b] = affect[b] ? MIN (new_val, 255) : bottom[b];
+ }
+ }
+
+ /* 3: mask_val AND s1_a both approach 0+, regardless of s2_a */
+ else if (s1_a + mask_val == 0.0)
+ {
+ for (b = 0; b < alpha; b++)
+ dest[b] = bottom[b];
+ }
+
+ /* 4: mask_val -->1 AND s2_a -->0, regardless of s1_a */
+ else if (1.0 - mask_val + s2_a == 0.0)
+ {
+ for (b = 0; b < alpha; b++)
+ dest[b] = affect[b] ? top[b] : bottom[b];
+ }
+ }
+ else
+ {
+ gdouble a_recip = 1.0 / a_val;
+ /* possible optimization: fold a_recip into s1_a and s2_a */
+ for (b = 0; b < alpha; b++)
+ {
+ gint new_val = 0.5 + a_recip * (bottom[b] * s1_a + mask_val *
+ (top[b] * s2_a - bottom[b] * s1_a));
+ dest[b] = affect[b] ? MIN (new_val, 255) : bottom[b];
+ }
+ }
+
+ dest[alpha] = affect[alpha] ? a_val + 0.5 : s1_a;
+
+ top += 4;
+ bottom += 4;
+ mask += 1;
+ dest += 4;
+ }
+ }
+}
diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h
index 76e6fe7..264a5a9 100644
--- a/app/gegl/gimp-gegl-loops.h
+++ b/app/gegl/gimp-gegl-loops.h
@@ -64,5 +64,16 @@ void gimp_gegl_combine_mask (GeglBuffer *mask_buffer,
gdouble opacity,
gboolean stipple);
+void gimp_gegl_replace (GeglBuffer *top_buffer,
+ const GeglRectangle *top_rect,
+ GeglBuffer *bottom_buffer,
+ const GeglRectangle *bottom_rect,
+ GeglBuffer *mask_buffer,
+ const GeglRectangle *mask_rect,
+ GeglBuffer *dest_buffer,
+ const GeglRectangle *dest_rect,
+ guchar opacity,
+ const gboolean *affect);
+
#endif /* __GIMP_GEGL_LOOPS_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]