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?
This commit is contained in:
parent
3307c71966
commit
3cef404e20
8 changed files with 204 additions and 51 deletions
|
|
@ -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;
|
||||
gfloat value = 0.0;
|
||||
|
||||
value = MAX (src[RED], src[GREEN]);
|
||||
value = MAX (value, src[BLUE]);
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue