Commit 3cef404e authored by Michael Natterer's avatar Michael Natterer 😴

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?
parent 3307c719
......@@ -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;
......
......@@ -40,6 +40,7 @@ struct _GimpOperationThreshold
{
GimpOperationPointFilter parent_instance;
GimpHistogramChannel channel;
gdouble low;
gdouble high;
};
......
......@@ -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",
......@@ -1275,6 +1278,13 @@ register_drawable_color_procs (GimpPDB *pdb)
"The drawable",
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",
......
......@@ -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,
......
......@@ -39,6 +39,7 @@ struct _GimpThresholdTool
/* dialog */
GimpHistogram *histogram;
GtkWidget *channel_menu;
GimpHistogramBox *histogram_box;
};
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment