[gimp/goat-invasion: 505/526] app: add gimp_gegl_smudge_blend(), a brute-force port of blend_region()



commit f8c8d6c8a7099c4af89143c606a40d987124d947
Author: Michael Natterer <mitch gimp org>
Date:   Wed Apr 18 00:32:10 2012 +0200

    app: add gimp_gegl_smudge_blend(), a brute-force port of blend_region()
    
    and use it in GimpSmudge. This only to get functionality ported and
    the API done, and not the final state.

 app/gegl/gimp-gegl-loops.c |   99 ++++++++++++++++++++++++++++++++++++++++++++
 app/gegl/gimp-gegl-loops.h |   40 +++++++++++-------
 app/paint/gimpsmudge.c     |   69 +++++++++++++++---------------
 3 files changed, 157 insertions(+), 51 deletions(-)
---
diff --git a/app/gegl/gimp-gegl-loops.c b/app/gegl/gimp-gegl-loops.c
index 84d79ac..0983c9c 100644
--- a/app/gegl/gimp-gegl-loops.c
+++ b/app/gegl/gimp-gegl-loops.c
@@ -307,3 +307,102 @@ gimp_gegl_dodgeburn (GeglBuffer          *src_buffer,
       break;
     }
 }
+
+/*
+ * blend_pixels patched 8-24-05 to fix bug #163721.  Note that this change
+ * causes the function to treat src1 and src2 asymmetrically.  This gives the
+ * right behavior for the smudge tool, which is the only user of this function
+ * at the time of patching.  If you want to use the function for something
+ * else, caveat emptor.
+ */
+void
+gimp_gegl_smudge_blend (GeglBuffer          *top_buffer,
+                        const GeglRectangle *top_rect,
+                        GeglBuffer          *bottom_buffer,
+                        const GeglRectangle *bottom_rect,
+                        GeglBuffer          *dest_buffer,
+                        const GeglRectangle *dest_rect,
+                        guchar               blend)
+{
+  GeglBufferIterator *iter;
+  const Babl         *top_format;
+  const Babl         *bottom_format;
+  const Babl         *dest_format;
+  gint                top_bpp;
+  gint                bottom_bpp;
+  gint                dest_bpp;
+
+  top_format    = gegl_buffer_get_format (top_buffer);
+  bottom_format = gegl_buffer_get_format (bottom_buffer);
+  dest_format   = gegl_buffer_get_format (dest_buffer);
+
+  top_bpp    = babl_format_get_bytes_per_pixel (top_format);
+  bottom_bpp = babl_format_get_bytes_per_pixel (bottom_format);
+  dest_bpp   = babl_format_get_bytes_per_pixel (dest_format);
+
+  iter = gegl_buffer_iterator_new (top_buffer, top_rect, 0, NULL,
+                                   GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, bottom_buffer, bottom_rect, 0, NULL,
+                            GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0, NULL,
+                            GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+
+  while (gegl_buffer_iterator_next (iter))
+    {
+      const guchar *top    = iter->data[0];
+      const guchar *bottom = iter->data[1];
+      guchar       *dest   = iter->data[2];
+
+      if (babl_format_has_alpha (top_format))
+        {
+          const guint blend1 = 255 - blend;
+          const guint blend2 = blend + 1;
+          const guint c      = top_bpp - 1;
+
+          while (iter->length--)
+            {
+              const gint  a1 = blend1 * bottom[c];
+              const gint  a2 = blend2 * top[c];
+              const gint  a  = a1 + a2;
+              guint       b;
+
+              if (!a)
+                {
+                  for (b = 0; b < top_bpp; b++)
+                    dest[b] = 0;
+                }
+              else
+                {
+                  for (b = 0; b < c; b++)
+                    dest[b] =
+                      bottom[b] + (bottom[b] * a1 + top[b] * a2 - a * bottom[b]) / a;
+
+                  dest[c] = a >> 8;
+                }
+
+              top    += top_bpp;
+              bottom += bottom_bpp;
+              dest   += dest_bpp;
+            }
+        }
+      else
+        {
+          const guchar blend1 = 255 - blend;
+
+          while (iter->length--)
+            {
+              guint b;
+
+              for (b = 0; b < top_bpp; b++)
+                dest[b] =
+                  bottom[b] + (bottom[b] * blend1 + top[b] * blend - bottom[b] * 255) / 255;
+
+              top    += top_bpp;
+              bottom += bottom_bpp;
+              dest   += dest_bpp;
+            }
+        }
+    }
+}
diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h
index 525c799..a85bb5b 100644
--- a/app/gegl/gimp-gegl-loops.h
+++ b/app/gegl/gimp-gegl-loops.h
@@ -25,23 +25,31 @@
 /*  this is a pretty stupid port of concolve_region() that only works
  *  on a linear source buffer
  */
-void   gimp_gegl_convolve  (GeglBuffer          *src_buffer,
-                            const GeglRectangle *src_rect,
-                            GeglBuffer          *dest_buffer,
-                            const GeglRectangle *dest_rect,
-                            const gfloat        *kernel,
-                            gint                 kernel_size,
-                            gdouble              divisor,
-                            GimpConvolutionType  mode,
-                            gboolean             alpha_weighting);
+void   gimp_gegl_convolve     (GeglBuffer          *src_buffer,
+                               const GeglRectangle *src_rect,
+                               GeglBuffer          *dest_buffer,
+                               const GeglRectangle *dest_rect,
+                               const gfloat        *kernel,
+                               gint                 kernel_size,
+                               gdouble              divisor,
+                               GimpConvolutionType  mode,
+                               gboolean             alpha_weighting);
 
-void   gimp_gegl_dodgeburn (GeglBuffer          *src_buffer,
-                            const GeglRectangle *src_rect,
-                            GeglBuffer          *dest_buffer,
-                            const GeglRectangle *dest_rect,
-                            gdouble              exposure,
-                            GimpDodgeBurnType    type,
-                            GimpTransferMode     mode);
+void   gimp_gegl_dodgeburn    (GeglBuffer          *src_buffer,
+                               const GeglRectangle *src_rect,
+                               GeglBuffer          *dest_buffer,
+                               const GeglRectangle *dest_rect,
+                               gdouble              exposure,
+                               GimpDodgeBurnType    type,
+                               GimpTransferMode     mode);
+
+void   gimp_gegl_smudge_blend (GeglBuffer          *top_buffer,
+                               const GeglRectangle *top_rect,
+                               GeglBuffer          *bottom_buffer,
+                               const GeglRectangle *bottom_rect,
+                               GeglBuffer          *dest_buffer,
+                               const GeglRectangle *dest_rect,
+                               guchar               blend);
 
 
 #endif /* __GIMP_GEGL_LOOPS_H__ */
diff --git a/app/paint/gimpsmudge.c b/app/paint/gimpsmudge.c
index a4b7494..8129a40 100644
--- a/app/paint/gimpsmudge.c
+++ b/app/paint/gimpsmudge.c
@@ -23,13 +23,9 @@
 
 #include "paint-types.h"
 
-#include "base/pixel-region.h"
-
-#include "paint-funcs/paint-funcs.h"
-
+#include "gegl/gimp-gegl-loops.h"
 #include "gegl/gimp-gegl-utils.h"
 
-#include "core/gimp.h"
 #include "core/gimpbrush.h"
 #include "core/gimpdrawable.h"
 #include "core/gimpdynamics.h"
@@ -164,13 +160,12 @@ gimp_smudge_start (GimpPaintCore    *paint_core,
                    GimpPaintOptions *paint_options,
                    const GimpCoords *coords)
 {
-  GimpSmudge  *smudge = GIMP_SMUDGE (paint_core);
-  GeglBuffer  *paint_buffer;
-  gint         paint_buffer_x;
-  gint         paint_buffer_y;
-  GimpTempBuf *accum_temp;
-  gint         accum_size;
-  gint         x, y;
+  GimpSmudge *smudge = GIMP_SMUDGE (paint_core);
+  GeglBuffer *paint_buffer;
+  gint        paint_buffer_x;
+  gint        paint_buffer_y;
+  gint        accum_size;
+  gint        x, y;
 
   if (gimp_drawable_is_indexed (drawable))
     return FALSE;
@@ -185,10 +180,10 @@ gimp_smudge_start (GimpPaintCore    *paint_core,
   gimp_smudge_accumulator_size (paint_options, &accum_size);
 
   /*  Allocate the accumulation buffer */
-  accum_temp = gimp_temp_buf_new (accum_size, accum_size,
-                                  gimp_drawable_get_format (drawable));
-  smudge->accum_buffer = gimp_temp_buf_create_buffer (accum_temp);
-  gimp_temp_buf_unref (accum_temp);
+  smudge->accum_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+                                                          accum_size,
+                                                          accum_size),
+                                          gimp_drawable_get_format (drawable));
 
   /*  adjust the x and y coordinates to the upper left corner of the
    *  accumulator
@@ -251,7 +246,8 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
   GeglBuffer         *paint_buffer;
   gint                paint_buffer_x;
   gint                paint_buffer_y;
-  PixelRegion         srcPR, tempPR;
+  gint                paint_buffer_width;
+  gint                paint_buffer_height;
   gdouble             fade_point;
   gdouble             opacity;
   gdouble             rate;
@@ -284,16 +280,12 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
   if (! paint_buffer)
     return;
 
+  paint_buffer_width  = gegl_buffer_get_width  (paint_buffer);
+  paint_buffer_height = gegl_buffer_get_height (paint_buffer);
+
   /*  Get the unclipped acumulator coordinates  */
   gimp_smudge_accumulator_coords (paint_core, coords, &x, &y);
 
-  /* srcPR will be the pixels under the current painthit from the drawable */
-  pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
-                     paint_buffer_x,
-                     paint_buffer_y,
-                     gegl_buffer_get_width  (paint_buffer),
-                     gegl_buffer_get_height (paint_buffer), FALSE);
-
   /* Enable dynamic rate */
   rate_output = gimp_dynamics_get_output (dynamics,
                                           GIMP_DYNAMICS_OUTPUT_RATE);
@@ -305,14 +297,6 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
 
   rate = (options->rate / 100.0) * dynamic_rate;
 
-  /* The tempPR will be the built up buffer (for smudge) */
-  pixel_region_init_temp_buf (&tempPR,
-                              gimp_gegl_buffer_get_temp_buf (smudge->accum_buffer),
-                              paint_buffer_x - x,
-                              paint_buffer_y - y,
-                              gegl_buffer_get_width  (paint_buffer),
-                              gegl_buffer_get_height (paint_buffer));
-
   /*  Smudge uses the buffer Accum.
    *  For each successive painthit Accum is built like this
    *    Accum =  rate*Accum  + (1-rate)*I.
@@ -321,13 +305,28 @@ gimp_smudge_motion (GimpPaintCore    *paint_core,
    *    (Accum,1) (if no alpha),
    */
 
-  blend_region (&srcPR, &tempPR, &tempPR, ROUND (rate * 255.0));
+  gimp_gegl_smudge_blend (smudge->accum_buffer,
+                          GEGL_RECTANGLE (paint_buffer_x - x,
+                                          paint_buffer_y - y,
+                                          paint_buffer_width,
+                                          paint_buffer_height),
+                          gimp_drawable_get_buffer (drawable),
+                          GEGL_RECTANGLE (paint_buffer_x,
+                                          paint_buffer_y,
+                                          paint_buffer_width,
+                                          paint_buffer_height),
+                          smudge->accum_buffer,
+                          GEGL_RECTANGLE (paint_buffer_x - x,
+                                          paint_buffer_y - y,
+                                          paint_buffer_width,
+                                          paint_buffer_height),
+                          ROUND (rate * 255.0));
 
   gegl_buffer_copy (smudge->accum_buffer,
                     GEGL_RECTANGLE (paint_buffer_x - x,
                                     paint_buffer_y - y,
-                                    gegl_buffer_get_width  (paint_buffer),
-                                    gegl_buffer_get_height (paint_buffer)),
+                                    paint_buffer_width,
+                                    paint_buffer_height),
                     paint_buffer,
                     GEGL_RECTANGLE (0, 0, 0, 0));
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]