[gimp] app, pdb, libgimp: allow to choose the channel when thresholding



commit 3cef404e20c58fbbd2f7c95fb7e4055fdf38f594
Author: Michael Natterer <mitch gimp org>
Date:   Tue Nov 1 22:41:56 2016 +0100

    app, pdb, libgimp: allow to choose the channel when thresholding
    
    so the threshold can now be based on the GimpHistogramChannel enum.
    Add a channel menu to the threshold dialog and a channel argument to
    the PDB procedure (which is new in 2.10).
    
    If I hadn't forgotten what the "RGB" channel is supposed to do I would
    have implemented the RGB mode in GimpOperationThreshold correctly.
    Right now I'm just guessing. Anyone?

 app/operations/gimpoperationthreshold.c |   56 ++++++++++-
 app/operations/gimpoperationthreshold.h |    1 +
 app/pdb/drawable-color-cmds.c           |   16 +++-
 app/tools/gimpthresholdtool.c           |  162 +++++++++++++++++++++++-------
 app/tools/gimpthresholdtool.h           |    1 +
 libgimp/gimpdrawablecolor_pdb.c         |   13 ++-
 libgimp/gimpdrawablecolor_pdb.h         |    1 +
 tools/pdbgen/pdb/drawable_color.pdb     |    7 +-
 8 files changed, 205 insertions(+), 52 deletions(-)
---
diff --git a/app/operations/gimpoperationthreshold.c b/app/operations/gimpoperationthreshold.c
index 0282af8..ddcd517 100644
--- a/app/operations/gimpoperationthreshold.c
+++ b/app/operations/gimpoperationthreshold.c
@@ -24,6 +24,7 @@
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gegl.h>
 
+#include "libgimpcolor/gimpcolor.h"
 #include "libgimpconfig/gimpconfig.h"
 
 #include "operations-types.h"
@@ -36,6 +37,7 @@
 enum
 {
   PROP_0,
+  PROP_CHANNEL,
   PROP_LOW,
   PROP_HIGH
 };
@@ -82,6 +84,14 @@ gimp_operation_threshold_class_init (GimpOperationThresholdClass *klass)
                                  "description", "GIMP Threshold operation",
                                  NULL);
 
+  GIMP_CONFIG_PROP_ENUM (object_class, PROP_CHANNEL,
+                         "channel",
+                         _("Channel"),
+                         NULL,
+                         GIMP_TYPE_HISTOGRAM_CHANNEL,
+                         GIMP_HISTOGRAM_VALUE,
+                         GIMP_PARAM_STATIC_STRINGS);
+
   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_LOW,
                            "low",
                            _("Low threshold"),
@@ -112,6 +122,10 @@ gimp_operation_threshold_get_property (GObject    *object,
 
   switch (property_id)
     {
+    case PROP_CHANNEL:
+      g_value_set_enum (value, self->channel);
+      break;
+
     case PROP_LOW:
       g_value_set_double (value, self->low);
       break;
@@ -136,6 +150,10 @@ gimp_operation_threshold_set_property (GObject      *object,
 
   switch (property_id)
     {
+    case PROP_CHANNEL:
+      self->channel = g_value_get_enum (value);
+      break;
+
     case PROP_LOW:
       self->low = g_value_get_double (value);
       break;
@@ -164,10 +182,40 @@ gimp_operation_threshold_process (GeglOperation       *operation,
 
   while (samples--)
     {
-      gfloat value;
-
-      value = MAX (src[RED], src[GREEN]);
-      value = MAX (value, src[BLUE]);
+      gfloat value = 0.0;
+
+      switch (threshold->channel)
+        {
+        case GIMP_HISTOGRAM_VALUE:
+          value = MAX (src[RED], src[GREEN]);
+          value = MAX (value, src[BLUE]);
+          break;
+
+        case GIMP_HISTOGRAM_RED:
+          value = src[RED];
+          break;
+
+        case GIMP_HISTOGRAM_GREEN:
+          value = src[GREEN];
+          break;
+
+        case GIMP_HISTOGRAM_BLUE:
+          value = src[BLUE];
+          break;
+
+        case GIMP_HISTOGRAM_ALPHA:
+          value = src[ALPHA];
+          break;
+
+        case GIMP_HISTOGRAM_RGB:
+          value = MIN (src[RED], src[GREEN]);
+          value = MIN (value, src[BLUE]);
+          break;
+
+        case GIMP_HISTOGRAM_LUMINANCE:
+          value = GIMP_RGB_LUMINANCE (src[RED], src[GREEN], src[BLUE]);
+          break;
+        }
 
       value = (value >= threshold->low && value <= threshold->high) ? 1.0 : 0.0;
 
diff --git a/app/operations/gimpoperationthreshold.h b/app/operations/gimpoperationthreshold.h
index d4f82ee..30bc165 100644
--- a/app/operations/gimpoperationthreshold.h
+++ b/app/operations/gimpoperationthreshold.h
@@ -40,6 +40,7 @@ struct _GimpOperationThreshold
 {
   GimpOperationPointFilter  parent_instance;
 
+  GimpHistogramChannel      channel;
   gdouble                   low;
   gdouble                   high;
 };
diff --git a/app/pdb/drawable-color-cmds.c b/app/pdb/drawable-color-cmds.c
index b73ee24..d0011d7 100644
--- a/app/pdb/drawable-color-cmds.c
+++ b/app/pdb/drawable-color-cmds.c
@@ -679,12 +679,14 @@ drawable_threshold_invoker (GimpProcedure         *procedure,
 {
   gboolean success = TRUE;
   GimpDrawable *drawable;
+  gint32 channel;
   gdouble low_threshold;
   gdouble high_threshold;
 
   drawable = gimp_value_get_drawable (gimp_value_array_index (args, 0), gimp);
-  low_threshold = g_value_get_double (gimp_value_array_index (args, 1));
-  high_threshold = g_value_get_double (gimp_value_array_index (args, 2));
+  channel = g_value_get_enum (gimp_value_array_index (args, 1));
+  low_threshold = g_value_get_double (gimp_value_array_index (args, 2));
+  high_threshold = g_value_get_double (gimp_value_array_index (args, 3));
 
   if (success)
     {
@@ -695,6 +697,7 @@ drawable_threshold_invoker (GimpProcedure         *procedure,
           GeglNode *node =
             gegl_node_new_child (NULL,
                                  "operation", "gimp:threshold",
+                                 "channel",   channel,
                                  "low",       low_threshold,
                                  "high",      high_threshold,
                                  NULL);
@@ -1264,7 +1267,7 @@ register_drawable_color_procs (GimpPDB *pdb)
   gimp_procedure_set_static_strings (procedure,
                                      "gimp-drawable-threshold",
                                      "Threshold the specified drawable.",
-                                     "This procedures generates a threshold map of the specified drawable. 
All pixels between the values of 'low_threshold' and 'high_threshold' are replaced with white, and all other 
pixels with black.",
+                                     "This procedures generates a threshold map of the specified drawable. 
All pixels between the values of 'low_threshold' and 'high_threshold', on the scale of 'channel' are replaced 
with white, and all other pixels with black.",
                                      "Spencer Kimball & Peter Mattis",
                                      "Spencer Kimball & Peter Mattis",
                                      "1997",
@@ -1276,6 +1279,13 @@ register_drawable_color_procs (GimpPDB *pdb)
                                                             pdb->gimp, FALSE,
                                                             GIMP_PARAM_READWRITE));
   gimp_procedure_add_argument (procedure,
+                               g_param_spec_enum ("channel",
+                                                  "channel",
+                                                  "The channel to base the threshold on",
+                                                  GIMP_TYPE_HISTOGRAM_CHANNEL,
+                                                  GIMP_HISTOGRAM_VALUE,
+                                                  GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
                                g_param_spec_double ("low-threshold",
                                                     "low threshold",
                                                     "The low threshold value",
diff --git a/app/tools/gimpthresholdtool.c b/app/tools/gimpthresholdtool.c
index 10429e4..da85ece 100644
--- a/app/tools/gimpthresholdtool.c
+++ b/app/tools/gimpthresholdtool.c
@@ -64,6 +64,9 @@ static void       gimp_threshold_tool_config_notify   (GObject           *object
                                                        GParamSpec        *pspec,
                                                        GimpThresholdTool *t_tool);
 
+static gboolean   gimp_threshold_tool_channel_sensitive
+                                                      (gint               value,
+                                                       gpointer           data);
 static void       gimp_threshold_tool_histogram_range (GimpHistogramView *view,
                                                        gint               start,
                                                        gint               end,
@@ -159,6 +162,10 @@ gimp_threshold_tool_initialize (GimpTool     *tool,
       return FALSE;
     }
 
+  gimp_int_combo_box_set_sensitivity (GIMP_INT_COMBO_BOX (t_tool->channel_menu),
+                                      gimp_threshold_tool_channel_sensitive,
+                                      drawable, NULL);
+
   gimp_drawable_calculate_histogram (drawable, t_tool->histogram);
   gimp_histogram_view_set_histogram (t_tool->histogram_box->view,
                                      t_tool->histogram);
@@ -187,42 +194,72 @@ gimp_threshold_tool_get_operation (GimpFilterTool  *filter_tool,
 static void
 gimp_threshold_tool_dialog (GimpFilterTool *filter_tool)
 {
-  GimpThresholdTool *t_tool       = GIMP_THRESHOLD_TOOL (filter_tool);
-  GimpToolOptions   *tool_options = GIMP_TOOL_GET_OPTIONS (filter_tool);
-  GtkWidget         *main_vbox;
-  GtkWidget         *hbox;
-  GtkWidget         *menu;
-  GtkWidget         *box;
-  GtkWidget         *button;
-  gdouble            low;
-  gdouble            high;
-  gint               n_bins;
+  GimpThresholdTool    *t_tool       = GIMP_THRESHOLD_TOOL (filter_tool);
+  GimpToolOptions      *tool_options = GIMP_TOOL_GET_OPTIONS (filter_tool);
+  GtkWidget            *main_vbox;
+  GtkWidget            *main_frame;
+  GtkWidget            *frame_vbox;
+  GtkWidget            *hbox;
+  GtkWidget            *label;
+  GtkWidget            *hbox2;
+  GtkWidget            *box;
+  GtkWidget            *button;
+  GimpHistogramChannel  channel;
+  gdouble               low;
+  gdouble               high;
+  gint                  n_bins;
 
   main_vbox = gimp_filter_tool_dialog_get_vbox (filter_tool);
 
+  main_frame = gimp_frame_new (NULL);
+  gtk_box_pack_start (GTK_BOX (main_vbox), main_frame, TRUE, TRUE, 0);
+  gtk_widget_show (main_frame);
+
   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-  gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
+  gtk_frame_set_label_widget (GTK_FRAME (main_frame), hbox);
   gtk_widget_show (hbox);
 
-  menu = gimp_prop_enum_icon_box_new (G_OBJECT (tool_options),
-                                      "histogram-scale", "gimp-histogram",
-                                      0, 0);
-  gtk_box_pack_end (GTK_BOX (hbox), menu, FALSE, FALSE, 0);
-  gtk_widget_show (menu);
+  label = gtk_label_new_with_mnemonic (_("Cha_nnel:"));
+  gimp_label_set_attributes (GTK_LABEL (label),
+                             PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
+                             -1);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  t_tool->channel_menu = gimp_prop_enum_combo_box_new (filter_tool->config,
+                                                       "channel", -1, -1);
+  gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (t_tool->channel_menu),
+                                       "gimp-channel");
+  gtk_box_pack_start (GTK_BOX (hbox), t_tool->channel_menu, FALSE, FALSE, 0);
+  gtk_widget_show (t_tool->channel_menu);
+
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), t_tool->channel_menu);
+
+  hbox2 = gimp_prop_enum_icon_box_new (G_OBJECT (tool_options),
+                                       "histogram-scale", "gimp-histogram",
+                                       0, 0);
+  gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
+  gtk_widget_show (hbox2);
+
+  frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
+  gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox);
+  gtk_widget_show (frame_vbox);
 
   box = gimp_histogram_box_new ();
-  gtk_box_pack_start (GTK_BOX (main_vbox), box, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (frame_vbox), box, TRUE, TRUE, 0);
   gtk_widget_show (box);
 
   t_tool->histogram_box = GIMP_HISTOGRAM_BOX (box);
 
   g_object_get (filter_tool->config,
-                "low",  &low,
-                "high", &high,
+                "channel", &channel,
+                "low",     &low,
+                "high",    &high,
                 NULL);
 
   n_bins = gimp_histogram_n_bins (t_tool->histogram);
 
+  gimp_histogram_view_set_channel (t_tool->histogram_box->view, channel);
   gimp_histogram_view_set_range (t_tool->histogram_box->view,
                                  low  * (n_bins - 0.0001),
                                  high * (n_bins - 0.0001));
@@ -237,7 +274,7 @@ gimp_threshold_tool_dialog (GimpFilterTool *filter_tool)
                           G_BINDING_BIDIRECTIONAL);
 
   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-  gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (frame_vbox), hbox, FALSE, FALSE, 0);
   gtk_widget_show (hbox);
 
   button = gtk_button_new_with_mnemonic (_("_Auto"));
@@ -256,23 +293,68 @@ gimp_threshold_tool_config_notify (GObject           *object,
                                    GParamSpec        *pspec,
                                    GimpThresholdTool *t_tool)
 {
-  gdouble low;
-  gdouble high;
-  gint    n_bins;
-
   if (! t_tool->histogram_box)
     return;
 
-  g_object_get (object,
-                "low",  &low,
-                "high", &high,
-                NULL);
+  if (! strcmp (pspec->name, "channel"))
+    {
+      GimpHistogramChannel channel;
 
-  n_bins = gimp_histogram_n_bins (t_tool->histogram);
+      g_object_get (object,
+                    "channel", &channel,
+                    NULL);
 
-  gimp_histogram_view_set_range (t_tool->histogram_box->view,
-                                 low  * (n_bins - 0.0001),
-                                 high * (n_bins - 0.0001));
+      gimp_histogram_view_set_channel (t_tool->histogram_box->view,
+                                       channel);
+    }
+  else if (! strcmp (pspec->name, "low") ||
+           ! strcmp (pspec->name, "high"))
+    {
+      gdouble low;
+      gdouble high;
+      gint    n_bins;
+
+      g_object_get (object,
+                    "low",  &low,
+                    "high", &high,
+                    NULL);
+
+      n_bins = gimp_histogram_n_bins (t_tool->histogram);
+
+      gimp_histogram_view_set_range (t_tool->histogram_box->view,
+                                     low  * (n_bins - 0.0001),
+                                     high * (n_bins - 0.0001));
+    }
+}
+
+static gboolean
+gimp_threshold_tool_channel_sensitive (gint     value,
+                                       gpointer data)
+{
+  GimpDrawable         *drawable = GIMP_DRAWABLE (data);
+  GimpHistogramChannel  channel  = value;
+
+  switch (channel)
+    {
+    case GIMP_HISTOGRAM_VALUE:
+      return TRUE;
+
+    case GIMP_HISTOGRAM_RED:
+    case GIMP_HISTOGRAM_GREEN:
+    case GIMP_HISTOGRAM_BLUE:
+      return gimp_drawable_is_rgb (drawable);
+
+    case GIMP_HISTOGRAM_ALPHA:
+      return gimp_drawable_has_alpha (drawable);
+
+    case GIMP_HISTOGRAM_RGB:
+      return gimp_drawable_is_rgb (drawable);
+
+    case GIMP_HISTOGRAM_LUMINANCE:
+      return gimp_drawable_is_rgb (drawable);
+    }
+
+  return FALSE;
 }
 
 static void
@@ -307,14 +389,18 @@ static void
 gimp_threshold_tool_auto_clicked (GtkWidget         *button,
                                   GimpThresholdTool *t_tool)
 {
-  GimpDrawable *drawable = GIMP_FILTER_TOOL (t_tool)->drawable;
-  gint          n_bins   = gimp_histogram_n_bins (t_tool->histogram);
-  gdouble       low;
+  GimpHistogramChannel  channel;
+  gint                  n_bins;
+  gdouble               low;
+
+  g_object_get (GIMP_FILTER_TOOL (t_tool)->config,
+                "channel", &channel,
+                NULL);
+
+  n_bins = gimp_histogram_n_bins (t_tool->histogram);
 
   low = gimp_histogram_get_threshold (t_tool->histogram,
-                                      gimp_drawable_is_rgb (drawable) ?
-                                      GIMP_HISTOGRAM_RGB :
-                                      GIMP_HISTOGRAM_VALUE,
+                                      channel,
                                       0, n_bins - 1);
 
   gimp_histogram_view_set_range (t_tool->histogram_box->view,
diff --git a/app/tools/gimpthresholdtool.h b/app/tools/gimpthresholdtool.h
index 6e4f7dc..4eca23a 100644
--- a/app/tools/gimpthresholdtool.h
+++ b/app/tools/gimpthresholdtool.h
@@ -39,6 +39,7 @@ struct _GimpThresholdTool
 
   /*  dialog  */
   GimpHistogram    *histogram;
+  GtkWidget        *channel_menu;
   GimpHistogramBox *histogram_box;
 };
 
diff --git a/libgimp/gimpdrawablecolor_pdb.c b/libgimp/gimpdrawablecolor_pdb.c
index 6c6ea40..7541d49 100644
--- a/libgimp/gimpdrawablecolor_pdb.c
+++ b/libgimp/gimpdrawablecolor_pdb.c
@@ -635,6 +635,7 @@ gimp_drawable_posterize (gint32 drawable_ID,
 /**
  * gimp_drawable_threshold:
  * @drawable_ID: The drawable.
+ * @channel: The channel to base the threshold on.
  * @low_threshold: The low threshold value.
  * @high_threshold: The high threshold value.
  *
@@ -642,17 +643,18 @@ gimp_drawable_posterize (gint32 drawable_ID,
  *
  * This procedures generates a threshold map of the specified drawable.
  * All pixels between the values of 'low_threshold' and
- * 'high_threshold' are replaced with white, and all other pixels with
- * black.
+ * 'high_threshold', on the scale of 'channel' are replaced with white,
+ * and all other pixels with black.
  *
  * Returns: TRUE on success.
  *
  * Since: 2.10
  **/
 gboolean
-gimp_drawable_threshold (gint32  drawable_ID,
-                         gdouble low_threshold,
-                         gdouble high_threshold)
+gimp_drawable_threshold (gint32               drawable_ID,
+                         GimpHistogramChannel channel,
+                         gdouble              low_threshold,
+                         gdouble              high_threshold)
 {
   GimpParam *return_vals;
   gint nreturn_vals;
@@ -661,6 +663,7 @@ gimp_drawable_threshold (gint32  drawable_ID,
   return_vals = gimp_run_procedure ("gimp-drawable-threshold",
                                     &nreturn_vals,
                                     GIMP_PDB_DRAWABLE, drawable_ID,
+                                    GIMP_PDB_INT32, channel,
                                     GIMP_PDB_FLOAT, low_threshold,
                                     GIMP_PDB_FLOAT, high_threshold,
                                     GIMP_PDB_END);
diff --git a/libgimp/gimpdrawablecolor_pdb.h b/libgimp/gimpdrawablecolor_pdb.h
index b8e138e..a30f1dd 100644
--- a/libgimp/gimpdrawablecolor_pdb.h
+++ b/libgimp/gimpdrawablecolor_pdb.h
@@ -85,6 +85,7 @@ gboolean gimp_drawable_levels_stretch      (gint32                drawable_ID);
 gboolean gimp_drawable_posterize           (gint32                drawable_ID,
                                             gint                  levels);
 gboolean gimp_drawable_threshold           (gint32                drawable_ID,
+                                            GimpHistogramChannel  channel,
                                             gdouble               low_threshold,
                                             gdouble               high_threshold);
 
diff --git a/tools/pdbgen/pdb/drawable_color.pdb b/tools/pdbgen/pdb/drawable_color.pdb
index c825b6a..960289d 100644
--- a/tools/pdbgen/pdb/drawable_color.pdb
+++ b/tools/pdbgen/pdb/drawable_color.pdb
@@ -742,8 +742,8 @@ sub drawable_threshold {
     $help = <<'HELP';
 This procedures generates a threshold map of the specified
 drawable. All pixels between the values of 'low_threshold' and
-'high_threshold' are replaced with white, and all other pixels with
-black.
+'high_threshold', on the scale of 'channel' are replaced with white,
+and all other pixels with black.
 HELP
 
     &std_pdb_misc;
@@ -753,6 +753,8 @@ HELP
     @inargs = (
        { name => 'drawable', type => 'drawable',
          desc => 'The drawable' },
+       { name => 'channel', type => 'enum GimpHistogramChannel',
+         desc => 'The channel to base the threshold on' },
        { name => 'low_threshold', type => '0.0 <= float <= 1.0',
          desc => 'The low threshold value' },
        { name => 'high_threshold', type => '0.0 <= float <= 1.0',
@@ -769,6 +771,7 @@ HELP
       GeglNode *node =
         gegl_node_new_child (NULL,
                              "operation", "gimp:threshold",
+                             "channel",   channel,
                              "low",       low_threshold,
                              "high",      high_threshold,
                              NULL);


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