[gimp] app: add gimp_gegl_average_color()



commit d2723682514e066adab7ad70d2beac0ffe86c1a0
Author: Ell <ell_se yahoo com>
Date:   Fri May 18 14:51:28 2018 -0400

    app: add gimp_gegl_average_color()
    
    ... which takes a GeglBuffer and calculates the average color over
    a given area.

 app/gegl/gimp-gegl-loops.cc |   96 +++++++++++++++++++++++++++++++++++++++++++
 app/gegl/gimp-gegl-loops.h  |    7 +++
 2 files changed, 103 insertions(+), 0 deletions(-)
---
diff --git a/app/gegl/gimp-gegl-loops.cc b/app/gegl/gimp-gegl-loops.cc
index d8f7503..bb6ddb6 100644
--- a/app/gegl/gimp-gegl-loops.cc
+++ b/app/gegl/gimp-gegl-loops.cc
@@ -39,6 +39,7 @@ extern "C"
 #include "gimp-gegl-loops.h"
 #include "gimp-gegl-loops-sse2.h"
 
+#include "core/gimp-atomic.h"
 #include "core/gimp-parallel.h"
 #include "core/gimp-utils.h"
 #include "core/gimpprogress.h"
@@ -916,4 +917,99 @@ gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
     }
 }
 
+void
+gimp_gegl_average_color (GeglBuffer          *buffer,
+                         const GeglRectangle *rect,
+                         gboolean             clip_to_buffer,
+                         GeglAbyssPolicy      abyss_policy,
+                         const Babl          *format,
+                         gpointer             color)
+{
+  typedef struct
+  {
+    gfloat color[4];
+    gint   n;
+  } Sum;
+
+  const Babl        *average_format = babl_format ("RaGaBaA float");
+  GeglRectangle      roi;
+  GSList * volatile  sums           = NULL;
+  GSList            *list;
+  Sum                average        = {};
+  gint               c;
+
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+  g_return_if_fail (color != NULL);
+
+  if (! rect)
+    rect = gegl_buffer_get_extent (buffer);
+
+  if (! format)
+    format = gegl_buffer_get_format (buffer);
+
+  if (clip_to_buffer)
+    gegl_rectangle_intersect (&roi, rect, gegl_buffer_get_extent (buffer));
+  else
+    roi = *rect;
+
+  gimp_parallel_distribute_area (&roi, MIN_PARALLEL_SUB_AREA,
+                                 [&] (const GeglRectangle *area)
+    {
+      Sum                *sum;
+      GeglBufferIterator *iter;
+      gfloat              color[4] = {};
+      gint                n        = 0;
+
+      iter = gegl_buffer_iterator_new (buffer, area, 0, average_format,
+                                       GEGL_BUFFER_READ, abyss_policy);
+
+      while (gegl_buffer_iterator_next (iter))
+        {
+          const gfloat *p = (const gfloat *) iter->data[0];
+          gint          i;
+
+          for (i = 0; i < iter->length; i++)
+            {
+              gint c;
+
+              for (c = 0; c < 4; c++)
+                color[c] += p[c];
+
+              p += 4;
+            }
+
+          n += iter->length;
+        }
+
+      sum = g_slice_new (Sum);
+
+      memcpy (sum->color, color, sizeof (color));
+      sum->n = n;
+
+      gimp_atomic_slist_push_head (&sums, sum);
+    });
+
+  for (list = sums; list; list = g_slist_next (list))
+    {
+      Sum *sum = (Sum *) list->data;
+
+      for (c = 0; c < 4; c++)
+        average.color[c] += sum->color[c];
+
+      average.n += sum->n;
+
+      g_slice_free (Sum, sum);
+    }
+
+  g_slist_free (sums);
+
+  if (average.n > 0)
+    {
+      for (c = 0; c < 4; c++)
+        average.color[c] /= average.n;
+    }
+
+  babl_process (babl_fish (average_format, format), average.color, color, 1);
+}
+
 } /* extern "C" */
diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h
index 9528051..093f12a 100644
--- a/app/gegl/gimp-gegl-loops.h
+++ b/app/gegl/gimp-gegl-loops.h
@@ -100,5 +100,12 @@ void   gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
                                         gboolean                  bpc,
                                         GimpProgress             *progress);
 
+void   gimp_gegl_average_color         (GeglBuffer               *buffer,
+                                        const GeglRectangle      *rect,
+                                        gboolean                  clip_to_buffer,
+                                        GeglAbyssPolicy           abyss_policy,
+                                        const Babl               *format,
+                                        gpointer                  color);
+
 
 #endif /* __GIMP_GEGL_LOOPS_H__ */


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