[gimp] app: implement the GEGL histogram with an iterator loop for now



commit 28f655ed2729ba648774463d252df2488d3fca3d
Author: Michael Natterer <mitch gimp org>
Date:   Mon Apr 16 21:01:39 2012 +0200

    app: implement the GEGL histogram with an iterator loop for now
    
    its body can later be reused in the working histogram sink op.

 app/core/gimpdrawable-histogram.c |   28 +++++
 app/core/gimphistogram.c          |  196 +++++++++++++++++++++++++++++++++++--
 app/core/gimphistogram.h          |    6 +
 3 files changed, 222 insertions(+), 8 deletions(-)
---
diff --git a/app/core/gimpdrawable-histogram.c b/app/core/gimpdrawable-histogram.c
index ebe4ac9b..d5efdd8 100644
--- a/app/core/gimpdrawable-histogram.c
+++ b/app/core/gimpdrawable-histogram.c
@@ -28,6 +28,7 @@
 #include "gegl/gimp-gegl-nodes.h"
 
 #include "gimp.h" /* gimp_use_gegl */
+#include "gimp-utils.h"
 #include "gimpchannel.h"
 #include "gimpdrawable-histogram.h"
 #include "gimphistogram.h"
@@ -52,6 +53,8 @@ gimp_drawable_calculate_histogram (GimpDrawable  *drawable,
   image = gimp_item_get_image (GIMP_ITEM (drawable));
   mask  = gimp_image_get_mask (image);
 
+  GIMP_TIMER_START();
+
   if (FALSE) // gimp_use_gegl (image->gimp))
     {
       GeglNode      *node = gegl_node_new ();
@@ -99,6 +102,29 @@ gimp_drawable_calculate_histogram (GimpDrawable  *drawable,
       g_object_unref (processor);
       g_object_unref (node);
     }
+  else if (gimp_use_gegl (image->gimp))
+    {
+      if (! gimp_channel_is_empty (mask))
+        {
+          gint off_x, off_y;
+
+          gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
+
+          gimp_histogram_calc_gegl (histogram,
+                                    gimp_drawable_get_buffer (drawable),
+                                    GEGL_RECTANGLE (x, y, width, height),
+                                    gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)),
+                                    GEGL_RECTANGLE (x - off_x, y - off_y,
+                                                    width, height));
+        }
+      else
+        {
+          gimp_histogram_calc_gegl (histogram,
+                                    gimp_drawable_get_buffer (drawable),
+                                    GEGL_RECTANGLE (x, y, width, height),
+                                    NULL, NULL);
+        }
+    }
   else
     {
       PixelRegion  region;
@@ -122,4 +148,6 @@ gimp_drawable_calculate_histogram (GimpDrawable  *drawable,
           gimp_histogram_calculate (histogram, &region, NULL);
         }
     }
+
+  GIMP_TIMER_END("histogram");
 }
diff --git a/app/core/gimphistogram.c b/app/core/gimphistogram.c
index 0133378..4a3b5c6 100644
--- a/app/core/gimphistogram.c
+++ b/app/core/gimphistogram.c
@@ -22,7 +22,7 @@
 #include <string.h>
 
 #undef G_DISABLE_DEPRECATED /* GStaticMutex */
-#include <glib-object.h>
+#include <gegl.h>
 
 #include "libgimpmath/gimpmath.h"
 
@@ -33,7 +33,6 @@
 
 #include "gimphistogram.h"
 
-
 #ifdef ENABLE_MP
 #define NUM_SLOTS  GIMP_MAX_NUM_THREADS
 #else
@@ -136,6 +135,183 @@ gimp_histogram_duplicate (GimpHistogram *histogram)
 }
 
 void
+gimp_histogram_calc_gegl (GimpHistogram       *histogram,
+                          GeglBuffer          *buffer,
+                          const GeglRectangle *buffer_rect,
+                          GeglBuffer          *mask,
+                          const GeglRectangle *mask_rect)
+{
+  GeglBufferIterator *iter;
+  const Babl         *format;
+  gint                bpp;
+  gdouble            *values;
+
+  g_return_if_fail (histogram != NULL);
+  g_return_if_fail (GEGL_IS_BUFFER (buffer));
+  g_return_if_fail (buffer_rect != NULL);
+
+  format = gegl_buffer_get_format (buffer);
+  bpp    = babl_format_get_bytes_per_pixel (format);
+
+  gimp_histogram_alloc_values (histogram, bpp);
+
+  iter = gegl_buffer_iterator_new (buffer, buffer_rect, 0, NULL,
+                                   GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+  if (mask)
+    gegl_buffer_iterator_add (iter, mask, mask_rect, 0,
+                              babl_format ("Y float"),
+                              GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+  values = histogram->values[0];
+
+#define VALUE(c,i) (values[(c) * 256 + (i)])
+
+  while (gegl_buffer_iterator_next (iter))
+    {
+      const guchar *data = iter->data[0];
+      gint          max;
+
+      if (mask)
+        {
+          const gfloat *mask_data = iter->data[1];
+
+          switch (bpp)
+            {
+            case 1:
+              while (iter->length)
+                {
+                  const gdouble masked = *mask_data;
+
+                  VALUE (0, data[0]) += masked;
+
+                  data += bpp;
+                  mask_data += 1;
+                }
+              break;
+
+            case 2:
+              while (iter->length--)
+                {
+                  const gdouble masked = *mask_data;
+                  const gdouble weight = data[1] / 255.0;
+
+                  VALUE (0, data[0]) += weight * masked;
+                  VALUE (1, data[1]) += masked;
+
+                  data += bpp;
+                  mask_data += 1;
+                }
+              break;
+
+            case 3: /* calculate separate value values */
+              while (iter->length--)
+                {
+                  const gdouble masked = *mask_data;
+
+                  VALUE (1, data[0]) += masked;
+                  VALUE (2, data[1]) += masked;
+                  VALUE (3, data[2]) += masked;
+
+                  max = MAX (data[0], data[1]);
+                  max = MAX (data[2], max);
+
+                  VALUE (0, max) += masked;
+
+                  data += bpp;
+                  mask_data += 1;
+                }
+              break;
+
+            case 4: /* calculate separate value values */
+              while (iter->length--)
+                {
+                  const gdouble masked = *mask_data;
+                  const gdouble weight = data[3] / 255.0;
+
+                  VALUE (1, data[0]) += weight * masked;
+                  VALUE (2, data[1]) += weight * masked;
+                  VALUE (3, data[2]) += weight * masked;
+                  VALUE (4, data[3]) += masked;
+
+                  max = MAX (data[0], data[1]);
+                  max = MAX (data[2], max);
+
+                  VALUE (0, max) += weight * masked;
+
+                  data += bpp;
+                  mask_data += 1;
+                }
+              break;
+            }
+        }
+      else /* no mask */
+        {
+          switch (bpp)
+            {
+            case 1:
+              while (iter->length--)
+                {
+                  VALUE (0, data[0]) += 1.0;
+
+                  data += bpp;
+                }
+              break;
+
+            case 2:
+              while (iter->length--)
+                {
+                  const gdouble weight = data[1] / 255;
+
+                  VALUE (0, data[0]) += weight;
+                  VALUE (1, data[1]) += 1.0;
+
+                  data += bpp;
+                }
+              break;
+
+            case 3: /* calculate separate value values */
+              while (iter->length--)
+                {
+                  VALUE (1, data[0]) += 1.0;
+                  VALUE (2, data[1]) += 1.0;
+                  VALUE (3, data[2]) += 1.0;
+
+                  max = MAX (data[0], data[1]);
+                  max = MAX (data[2], max);
+
+                  VALUE (0, max) += 1.0;
+
+                  data += bpp;
+                }
+              break;
+
+            case 4: /* calculate separate value values */
+              while (iter->length--)
+                {
+                  const gdouble weight = data[3] / 255;
+
+                  VALUE (1, data[0]) += weight;
+                  VALUE (2, data[1]) += weight;
+                  VALUE (3, data[2]) += weight;
+                  VALUE (4, data[3]) += 1.0;
+
+                  max = MAX (data[0], data[1]);
+                  max = MAX (data[2], max);
+
+                  VALUE (0, max) += weight;
+
+                  data += bpp;
+                }
+              break;
+            }
+        }
+    }
+
+#undef VALUE
+}
+
+void
 gimp_histogram_calculate (GimpHistogram *histogram,
                           PixelRegion   *region,
                           PixelRegion   *mask)
@@ -147,11 +323,6 @@ gimp_histogram_calculate (GimpHistogram *histogram,
 
   gimp_histogram_alloc_values (histogram, region->bytes);
 
-  for (i = 0; i < NUM_SLOTS; i++)
-    if (histogram->values[i])
-      memset (histogram->values[i],
-              0, histogram->n_channels * 256 * sizeof (gdouble));
-
   pixel_regions_process_parallel ((PixelProcessorFunc)
                                   gimp_histogram_calculate_sub_region,
                                   histogram, 2, region, mask);
@@ -565,7 +736,16 @@ gimp_histogram_alloc_values (GimpHistogram *histogram,
 
       histogram->n_channels = bytes + 1;
 
-      histogram->values[0] = g_new (gdouble, histogram->n_channels * 256);
+      histogram->values[0] = g_new0 (gdouble, histogram->n_channels * 256);
+    }
+  else
+    {
+      gint i;
+
+      for (i = 0; i < NUM_SLOTS; i++)
+        if (histogram->values[i])
+          memset (histogram->values[i],
+                  0, histogram->n_channels * 256 * sizeof (gdouble));
     }
 }
 
diff --git a/app/core/gimphistogram.h b/app/core/gimphistogram.h
index 2174122..76294fe 100644
--- a/app/core/gimphistogram.h
+++ b/app/core/gimphistogram.h
@@ -28,6 +28,12 @@ void            gimp_histogram_unref         (GimpHistogram        *histogram);
 
 GimpHistogram * gimp_histogram_duplicate     (GimpHistogram        *histogram);
 
+void            gimp_histogram_calc_gegl     (GimpHistogram        *histogram,
+                                              GeglBuffer           *buffer,
+                                              const GeglRectangle  *buffer_rect,
+                                              GeglBuffer           *mask,
+                                              const GeglRectangle  *mask_rect);
+
 void            gimp_histogram_calculate     (GimpHistogram        *histogram,
                                               PixelRegion          *region,
                                               PixelRegion          *mask);



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