Bug 757444 - Curves and Levels should operate by default on linear RGB...

...and present linear RGB Histograms

This is step one: implement the feature at all (without new defaults
or proper GUI, cough).

Add boolean "linear" properties to GimpOperationPointFilter,
GimpCurvesConfig and GimpLevelsConfig.

In the filter, simply set the input/output formats to linear in
prepare().

In the curves and levels tools, add "Linear" toggles from hell,
like in the histogram dockable, and make sure things work right
wrt changing and resetting the property, switching from levels
to curves, and picking colors.

The result currently changes when switching a non-nop curves/levels
between perceptual and linear, because adjusting the parameters
between the spaces is not implemented yet.
This commit is contained in:
Michael Natterer
2018-01-05 22:37:18 +01:00
parent a16a31ab51
commit 54d3beab9c
10 changed files with 186 additions and 24 deletions

View File

@ -44,6 +44,7 @@
enum enum
{ {
PROP_0, PROP_0,
PROP_LINEAR,
PROP_CHANNEL, PROP_CHANNEL,
PROP_CURVE PROP_CURVE
}; };
@ -99,6 +100,12 @@ gimp_curves_config_class_init (GimpCurvesConfigClass *klass)
viewable_class->default_icon_name = "gimp-tool-curves"; viewable_class->default_icon_name = "gimp-tool-curves";
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LINEAR,
"linear",
_("Linear"),
_("Work on linear RGB"),
FALSE, 0);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_CHANNEL, GIMP_CONFIG_PROP_ENUM (object_class, PROP_CHANNEL,
"channel", "channel",
_("Channel"), _("Channel"),
@ -170,6 +177,10 @@ gimp_curves_config_get_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_LINEAR:
g_value_set_boolean (value, self->linear);
break;
case PROP_CHANNEL: case PROP_CHANNEL:
g_value_set_enum (value, self->channel); g_value_set_enum (value, self->channel);
break; break;
@ -194,6 +205,10 @@ gimp_curves_config_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_LINEAR:
self->linear = g_value_get_boolean (value);
break;
case PROP_CHANNEL: case PROP_CHANNEL:
self->channel = g_value_get_enum (value); self->channel = g_value_get_enum (value);
g_object_notify (object, "curve"); g_object_notify (object, "curve");
@ -228,7 +243,8 @@ gimp_curves_config_serialize (GimpConfig *config,
GimpHistogramChannel old_channel; GimpHistogramChannel old_channel;
gboolean success = TRUE; gboolean success = TRUE;
if (! gimp_config_serialize_property_by_name (config, "time", writer)) if (! gimp_config_serialize_property_by_name (config, "time", writer) ||
! gimp_config_serialize_property_by_name (config, "linear", writer))
return FALSE; return FALSE;
old_channel = c_config->channel; old_channel = c_config->channel;
@ -284,6 +300,9 @@ gimp_curves_config_equal (GimpConfig *a,
GimpCurvesConfig *config_b = GIMP_CURVES_CONFIG (b); GimpCurvesConfig *config_b = GIMP_CURVES_CONFIG (b);
GimpHistogramChannel channel; GimpHistogramChannel channel;
if (config_a->linear != config_b->linear)
return FALSE;
for (channel = GIMP_HISTOGRAM_VALUE; for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA; channel <= GIMP_HISTOGRAM_ALPHA;
channel++) channel++)
@ -322,6 +341,7 @@ gimp_curves_config_reset (GimpConfig *config)
gimp_curves_config_reset_channel (c_config); gimp_curves_config_reset_channel (c_config);
} }
gimp_config_reset_property (G_OBJECT (config), "linear");
gimp_config_reset_property (G_OBJECT (config), "channel"); gimp_config_reset_property (G_OBJECT (config), "channel");
} }
@ -343,8 +363,10 @@ gimp_curves_config_copy (GimpConfig *src,
flags); flags);
} }
dest_config->linear = src_config->linear;
dest_config->channel = src_config->channel; dest_config->channel = src_config->channel;
g_object_notify (G_OBJECT (dest), "linear");
g_object_notify (G_OBJECT (dest), "channel"); g_object_notify (G_OBJECT (dest), "channel");
return TRUE; return TRUE;
@ -594,6 +616,10 @@ gimp_curves_config_load_cruft (GimpCurvesConfig *config,
gimp_data_thaw (GIMP_DATA (curve)); gimp_data_thaw (GIMP_DATA (curve));
} }
config->linear = FALSE;
g_object_notify (G_OBJECT (config), "linear");
g_object_thaw_notify (G_OBJECT (config)); g_object_thaw_notify (G_OBJECT (config));
return TRUE; return TRUE;

View File

@ -39,6 +39,8 @@ struct _GimpCurvesConfig
{ {
GimpSettings parent_instance; GimpSettings parent_instance;
gboolean linear;
GimpHistogramChannel channel; GimpHistogramChannel channel;
GimpCurve *curve[5]; GimpCurve *curve[5];

View File

@ -46,6 +46,7 @@
enum enum
{ {
PROP_0, PROP_0,
PROP_LINEAR,
PROP_CHANNEL, PROP_CHANNEL,
PROP_LOW_INPUT, PROP_LOW_INPUT,
PROP_HIGH_INPUT, PROP_HIGH_INPUT,
@ -102,6 +103,12 @@ gimp_levels_config_class_init (GimpLevelsConfigClass *klass)
viewable_class->default_icon_name = "gimp-tool-levels"; viewable_class->default_icon_name = "gimp-tool-levels";
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LINEAR,
"linear",
_("Linear"),
_("Work on linear RGB"),
FALSE, 0);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_CHANNEL, GIMP_CONFIG_PROP_ENUM (object_class, PROP_CHANNEL,
"channel", "channel",
_("Channel"), _("Channel"),
@ -178,6 +185,10 @@ gimp_levels_config_get_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_LINEAR:
g_value_set_boolean (value, self->linear);
break;
case PROP_CHANNEL: case PROP_CHANNEL:
g_value_set_enum (value, self->channel); g_value_set_enum (value, self->channel);
break; break;
@ -226,6 +237,10 @@ gimp_levels_config_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_LINEAR:
self->linear = g_value_get_boolean (value);
break;
case PROP_CHANNEL: case PROP_CHANNEL:
self->channel = g_value_get_enum (value); self->channel = g_value_get_enum (value);
g_object_notify (object, "low-input"); g_object_notify (object, "low-input");
@ -280,6 +295,7 @@ gimp_levels_config_serialize (GimpConfig *config,
gboolean success = TRUE; gboolean success = TRUE;
if (! gimp_config_serialize_property_by_name (config, "time", writer) || if (! gimp_config_serialize_property_by_name (config, "time", writer) ||
! gimp_config_serialize_property_by_name (config, "linear", writer) ||
! gimp_config_serialize_property_by_name (config, "clamp-input", writer) || ! gimp_config_serialize_property_by_name (config, "clamp-input", writer) ||
! gimp_config_serialize_property_by_name (config, "clamp-output", writer)) ! gimp_config_serialize_property_by_name (config, "clamp-output", writer))
return FALSE; return FALSE;
@ -341,7 +357,8 @@ gimp_levels_config_equal (GimpConfig *a,
GimpLevelsConfig *config_b = GIMP_LEVELS_CONFIG (b); GimpLevelsConfig *config_b = GIMP_LEVELS_CONFIG (b);
GimpHistogramChannel channel; GimpHistogramChannel channel;
if (config_a->clamp_input != config_b->clamp_input || if (config_a->linear != config_b->linear ||
config_a->clamp_input != config_b->clamp_input ||
config_a->clamp_output != config_b->clamp_output) config_a->clamp_output != config_b->clamp_output)
return FALSE; return FALSE;
@ -376,6 +393,7 @@ gimp_levels_config_reset (GimpConfig *config)
gimp_levels_config_reset_channel (l_config); gimp_levels_config_reset_channel (l_config);
} }
gimp_config_reset_property (G_OBJECT (config), "linear");
gimp_config_reset_property (G_OBJECT (config), "channel"); gimp_config_reset_property (G_OBJECT (config), "channel");
gimp_config_reset_property (G_OBJECT (config), "clamp-input"); gimp_config_reset_property (G_OBJECT (config), "clamp-input");
gimp_config_reset_property (G_OBJECT (config), "clamp_output"); gimp_config_reset_property (G_OBJECT (config), "clamp_output");
@ -407,10 +425,12 @@ gimp_levels_config_copy (GimpConfig *src,
g_object_notify (G_OBJECT (dest), "low-output"); g_object_notify (G_OBJECT (dest), "low-output");
g_object_notify (G_OBJECT (dest), "high-output"); g_object_notify (G_OBJECT (dest), "high-output");
dest_config->linear = src_config->linear;
dest_config->channel = src_config->channel; dest_config->channel = src_config->channel;
dest_config->clamp_input = src_config->clamp_input; dest_config->clamp_input = src_config->clamp_input;
dest_config->clamp_output = src_config->clamp_output; dest_config->clamp_output = src_config->clamp_output;
g_object_notify (G_OBJECT (dest), "linear");
g_object_notify (G_OBJECT (dest), "channel"); g_object_notify (G_OBJECT (dest), "channel");
g_object_notify (G_OBJECT (dest), "clamp-input"); g_object_notify (G_OBJECT (dest), "clamp-input");
g_object_notify (G_OBJECT (dest), "clamp-output"); g_object_notify (G_OBJECT (dest), "clamp-output");
@ -668,13 +688,15 @@ gimp_levels_config_to_curves_config (GimpLevelsConfig *config)
curves = g_object_new (GIMP_TYPE_CURVES_CONFIG, NULL); curves = g_object_new (GIMP_TYPE_CURVES_CONFIG, NULL);
curves->linear = config->linear;
for (channel = GIMP_HISTOGRAM_VALUE; for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA; channel <= GIMP_HISTOGRAM_ALPHA;
channel++) channel++)
{ {
GimpCurve *curve = curves->curve[channel]; GimpCurve *curve = curves->curve[channel];
const gint n_points = gimp_curve_get_n_points (curve); const gint n_points = gimp_curve_get_n_points (curve);
static const gint n = 4; static const gint n = 8;
gint point = -1; gint point = -1;
gdouble gamma = config->gamma[channel]; gdouble gamma = config->gamma[channel];
gdouble delta_in; gdouble delta_in;
@ -871,9 +893,11 @@ gimp_levels_config_load_cruft (GimpLevelsConfig *config,
config->high_output[i] = high_output[i] / 255.0; config->high_output[i] = high_output[i] / 255.0;
} }
config->linear = FALSE;
config->clamp_input = TRUE; config->clamp_input = TRUE;
config->clamp_output = TRUE; config->clamp_output = TRUE;
g_object_notify (G_OBJECT (config), "linear");
g_object_notify (G_OBJECT (config), "low-input"); g_object_notify (G_OBJECT (config), "low-input");
g_object_notify (G_OBJECT (config), "high-input"); g_object_notify (G_OBJECT (config), "high-input");
g_object_notify (G_OBJECT (config), "clamp-input"); g_object_notify (G_OBJECT (config), "clamp-input");

View File

@ -39,6 +39,8 @@ struct _GimpLevelsConfig
{ {
GimpSettings parent_instance; GimpSettings parent_instance;
gboolean linear;
GimpHistogramChannel channel; GimpHistogramChannel channel;
gdouble low_input[5]; gdouble low_input[5];

View File

@ -67,6 +67,14 @@ gimp_operation_curves_class_init (GimpOperationCurvesClass *klass)
point_class->process = gimp_operation_curves_process; point_class->process = gimp_operation_curves_process;
g_object_class_install_property (object_class,
GIMP_OPERATION_POINT_FILTER_PROP_LINEAR,
g_param_spec_boolean ("linear",
"Linear",
"Whether to operate on linear RGB",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
GIMP_OPERATION_POINT_FILTER_PROP_CONFIG, GIMP_OPERATION_POINT_FILTER_PROP_CONFIG,
g_param_spec_object ("config", g_param_spec_object ("config",

View File

@ -64,6 +64,14 @@ gimp_operation_levels_class_init (GimpOperationLevelsClass *klass)
point_class->process = gimp_operation_levels_process; point_class->process = gimp_operation_levels_process;
g_object_class_install_property (object_class,
GIMP_OPERATION_POINT_FILTER_PROP_LINEAR,
g_param_spec_boolean ("linear",
"Linear",
"Whether to operate on linear RGB",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
GIMP_OPERATION_POINT_FILTER_PROP_CONFIG, GIMP_OPERATION_POINT_FILTER_PROP_CONFIG,
g_param_spec_object ("config", g_param_spec_object ("config",

View File

@ -73,6 +73,10 @@ gimp_operation_point_filter_get_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case GIMP_OPERATION_POINT_FILTER_PROP_LINEAR:
g_value_set_boolean (value, self->linear);
break;
case GIMP_OPERATION_POINT_FILTER_PROP_CONFIG: case GIMP_OPERATION_POINT_FILTER_PROP_CONFIG:
g_value_set_object (value, self->config); g_value_set_object (value, self->config);
break; break;
@ -93,6 +97,10 @@ gimp_operation_point_filter_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case GIMP_OPERATION_POINT_FILTER_PROP_LINEAR:
self->linear = g_value_get_boolean (value);
break;
case GIMP_OPERATION_POINT_FILTER_PROP_CONFIG: case GIMP_OPERATION_POINT_FILTER_PROP_CONFIG:
if (self->config) if (self->config)
g_object_unref (self->config); g_object_unref (self->config);
@ -108,7 +116,13 @@ gimp_operation_point_filter_set_property (GObject *object,
static void static void
gimp_operation_point_filter_prepare (GeglOperation *operation) gimp_operation_point_filter_prepare (GeglOperation *operation)
{ {
const Babl *format = babl_format ("R'G'B'A float"); GimpOperationPointFilter *self = GIMP_OPERATION_POINT_FILTER (operation);
const Babl *format;
if (self->linear)
format = babl_format ("RGBA float");
else
format = babl_format ("R'G'B'A float");
gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "output", format); gegl_operation_set_format (operation, "output", format);

View File

@ -29,6 +29,7 @@
enum enum
{ {
GIMP_OPERATION_POINT_FILTER_PROP_0, GIMP_OPERATION_POINT_FILTER_PROP_0,
GIMP_OPERATION_POINT_FILTER_PROP_LINEAR,
GIMP_OPERATION_POINT_FILTER_PROP_CONFIG GIMP_OPERATION_POINT_FILTER_PROP_CONFIG
}; };
@ -47,6 +48,7 @@ struct _GimpOperationPointFilter
{ {
GeglOperationPointFilter parent_instance; GeglOperationPointFilter parent_instance;
gboolean linear;
GObject *config; GObject *config;
}; };

View File

@ -183,18 +183,25 @@ gimp_curves_tool_initialize (GimpTool *tool,
GimpDisplay *display, GimpDisplay *display,
GError **error) GError **error)
{ {
GimpCurvesTool *c_tool = GIMP_CURVES_TOOL (tool); GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool);
GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool); GimpCurvesTool *c_tool = GIMP_CURVES_TOOL (tool);
GimpImage *image = gimp_display_get_image (display); GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable = gimp_image_get_active_drawable (image); GimpDrawable *drawable = gimp_image_get_active_drawable (image);
GimpHistogram *histogram; GimpCurvesConfig *config;
GimpHistogram *histogram;
if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error)) if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
{ {
return FALSE; return FALSE;
} }
histogram = gimp_histogram_new (FALSE); config = GIMP_CURVES_CONFIG (filter_tool->config);
gegl_node_set (filter_tool->operation,
"linear", config->linear,
NULL);
histogram = gimp_histogram_new (config->linear);
gimp_drawable_calculate_histogram (drawable, histogram, FALSE); gimp_drawable_calculate_histogram (drawable, histogram, FALSE);
gimp_histogram_view_set_background (GIMP_HISTOGRAM_VIEW (c_tool->graph), gimp_histogram_view_set_background (GIMP_HISTOGRAM_VIEW (c_tool->graph),
histogram); histogram);
@ -436,6 +443,11 @@ gimp_curves_tool_dialog (GimpFilterTool *filter_tool)
gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
gtk_widget_show (hbox2); gtk_widget_show (hbox2);
button = gimp_prop_check_button_new (G_OBJECT (config), "linear", NULL);
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox); gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox);
gtk_widget_show (frame_vbox); gtk_widget_show (frame_vbox);
@ -545,6 +557,13 @@ gimp_curves_tool_reset (GimpFilterTool *filter_tool)
default_config = GIMP_CURVES_CONFIG (filter_tool->default_config); default_config = GIMP_CURVES_CONFIG (filter_tool->default_config);
g_object_freeze_notify (G_OBJECT (config));
if (default_config)
g_object_set (config, "linear", default_config->linear, NULL);
else
gimp_config_reset_property (G_OBJECT (config), "linear");
for (channel = GIMP_HISTOGRAM_VALUE; for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA; channel <= GIMP_HISTOGRAM_ALPHA;
channel++) channel++)
@ -570,6 +589,8 @@ gimp_curves_tool_reset (GimpFilterTool *filter_tool)
gimp_curve_reset (config->curve[channel], FALSE); gimp_curve_reset (config->curve[channel], FALSE);
} }
} }
g_object_thaw_notify (G_OBJECT (config));
} }
static void static void
@ -587,7 +608,22 @@ gimp_curves_tool_config_notify (GimpFilterTool *filter_tool,
if (! curves_tool->channel_menu) if (! curves_tool->channel_menu)
return; return;
if (! strcmp (pspec->name, "channel")) if (! strcmp (pspec->name, "linear"))
{
GimpHistogram *histogram;
gegl_node_set (filter_tool->operation,
"linear", curves_config->linear,
NULL);
histogram = gimp_histogram_new (curves_config->linear);
gimp_drawable_calculate_histogram (GIMP_TOOL (filter_tool)->drawable,
histogram, FALSE);
gimp_histogram_view_set_background (GIMP_HISTOGRAM_VIEW (curves_tool->graph),
histogram);
g_object_unref (histogram);
}
else if (! strcmp (pspec->name, "channel"))
{ {
gimp_curves_tool_update_channel (GIMP_CURVES_TOOL (filter_tool)); gimp_curves_tool_update_channel (GIMP_CURVES_TOOL (filter_tool));
} }
@ -652,18 +688,23 @@ gimp_curves_tool_color_picked (GimpFilterTool *filter_tool,
GimpCurvesTool *tool = GIMP_CURVES_TOOL (filter_tool); GimpCurvesTool *tool = GIMP_CURVES_TOOL (filter_tool);
GimpCurvesConfig *config = GIMP_CURVES_CONFIG (filter_tool->config); GimpCurvesConfig *config = GIMP_CURVES_CONFIG (filter_tool->config);
GimpDrawable *drawable = GIMP_TOOL (tool)->drawable; GimpDrawable *drawable = GIMP_TOOL (tool)->drawable;
GimpRGB rgb = *color;
tool->picked_color[GIMP_HISTOGRAM_RED] = color->r; if (config->linear)
tool->picked_color[GIMP_HISTOGRAM_GREEN] = color->g; babl_process (babl_fish (babl_format ("R'G'B'A double"),
tool->picked_color[GIMP_HISTOGRAM_BLUE] = color->b; babl_format ("RGBA double")),
&rgb, &rgb, 1);
tool->picked_color[GIMP_HISTOGRAM_RED] = rgb.r;
tool->picked_color[GIMP_HISTOGRAM_GREEN] = rgb.g;
tool->picked_color[GIMP_HISTOGRAM_BLUE] = rgb.b;
if (gimp_drawable_has_alpha (drawable)) if (gimp_drawable_has_alpha (drawable))
tool->picked_color[GIMP_HISTOGRAM_ALPHA] = color->a; tool->picked_color[GIMP_HISTOGRAM_ALPHA] = rgb.a;
else else
tool->picked_color[GIMP_HISTOGRAM_ALPHA] = -1; tool->picked_color[GIMP_HISTOGRAM_ALPHA] = -1;
tool->picked_color[GIMP_HISTOGRAM_VALUE] = MAX (MAX (color->r, color->g), tool->picked_color[GIMP_HISTOGRAM_VALUE] = MAX (MAX (rgb.r, rgb.g), rgb.b);
color->b);
gimp_curve_view_set_xpos (GIMP_CURVE_VIEW (tool->graph), gimp_curve_view_set_xpos (GIMP_CURVE_VIEW (tool->graph),
tool->picked_color[config->channel]); tool->picked_color[config->channel]);

View File

@ -160,7 +160,6 @@ gimp_levels_tool_class_init (GimpLevelsToolClass *klass)
static void static void
gimp_levels_tool_init (GimpLevelsTool *tool) gimp_levels_tool_init (GimpLevelsTool *tool)
{ {
tool->histogram = gimp_histogram_new (FALSE);
} }
static void static void
@ -178,9 +177,11 @@ gimp_levels_tool_initialize (GimpTool *tool,
GimpDisplay *display, GimpDisplay *display,
GError **error) GError **error)
{ {
GimpLevelsTool *l_tool = GIMP_LEVELS_TOOL (tool); GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool);
GimpImage *image = gimp_display_get_image (display); GimpLevelsTool *l_tool = GIMP_LEVELS_TOOL (tool);
GimpDrawable *drawable = gimp_image_get_active_drawable (image); GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
GimpLevelsConfig *config;
gdouble scale_factor; gdouble scale_factor;
gdouble step_increment; gdouble step_increment;
gdouble page_increment; gdouble page_increment;
@ -191,6 +192,15 @@ gimp_levels_tool_initialize (GimpTool *tool,
return FALSE; return FALSE;
} }
config = GIMP_LEVELS_CONFIG (filter_tool->config);
gegl_node_set (filter_tool->operation,
"linear", config->linear,
NULL);
g_clear_object (&l_tool->histogram);
l_tool->histogram = gimp_histogram_new (config->linear);
gimp_drawable_calculate_histogram (drawable, l_tool->histogram, FALSE); gimp_drawable_calculate_histogram (drawable, l_tool->histogram, FALSE);
gimp_histogram_view_set_histogram (GIMP_HISTOGRAM_VIEW (l_tool->histogram_view), gimp_histogram_view_set_histogram (GIMP_HISTOGRAM_VIEW (l_tool->histogram_view),
l_tool->histogram); l_tool->histogram);
@ -376,6 +386,11 @@ gimp_levels_tool_dialog (GimpFilterTool *filter_tool)
gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
gtk_widget_show (hbox2); gtk_widget_show (hbox2);
button = gimp_prop_check_button_new (G_OBJECT (config), "linear", NULL);
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox); gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox);
gtk_widget_show (frame_vbox); gtk_widget_show (frame_vbox);
@ -654,7 +669,21 @@ gimp_levels_tool_config_notify (GimpFilterTool *filter_tool,
if (! levels_tool->channel_menu) if (! levels_tool->channel_menu)
return; return;
if (! strcmp (pspec->name, "channel")) if (! strcmp (pspec->name, "linear"))
{
gegl_node_set (filter_tool->operation,
"linear", levels_config->linear,
NULL);
g_clear_object (&levels_tool->histogram);
levels_tool->histogram = gimp_histogram_new (levels_config->linear);
gimp_drawable_calculate_histogram (GIMP_TOOL (filter_tool)->drawable,
levels_tool->histogram, FALSE);
gimp_histogram_view_set_histogram (GIMP_HISTOGRAM_VIEW (levels_tool->histogram_view),
levels_tool->histogram);
}
else if (! strcmp (pspec->name, "channel"))
{ {
gimp_histogram_view_set_channel (GIMP_HISTOGRAM_VIEW (levels_tool->histogram_view), gimp_histogram_view_set_channel (GIMP_HISTOGRAM_VIEW (levels_tool->histogram_view),
levels_config->channel); levels_config->channel);
@ -763,8 +792,14 @@ gimp_levels_tool_color_picked (GimpFilterTool *color_tool,
{ {
GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (color_tool); GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (color_tool);
GimpLevelsConfig *config = GIMP_LEVELS_CONFIG (filter_tool->config); GimpLevelsConfig *config = GIMP_LEVELS_CONFIG (filter_tool->config);
GimpRGB rgb = *color;
guint value = GPOINTER_TO_UINT (identifier); guint value = GPOINTER_TO_UINT (identifier);
if (config->linear)
babl_process (babl_fish (babl_format ("R'G'B'A double"),
babl_format ("RGBA double")),
&rgb, &rgb, 1);
if (value & PICK_ALL_CHANNELS && if (value & PICK_ALL_CHANNELS &&
gimp_babl_format_get_base_type (sample_format) == GIMP_RGB) gimp_babl_format_get_base_type (sample_format) == GIMP_RGB)
{ {
@ -791,12 +826,12 @@ gimp_levels_tool_color_picked (GimpFilterTool *color_tool,
channel <= GIMP_HISTOGRAM_BLUE; channel <= GIMP_HISTOGRAM_BLUE;
channel++) channel++)
{ {
levels_input_adjust_by_color (config, value, channel, color); levels_input_adjust_by_color (config, value, channel, &rgb);
} }
} }
else else
{ {
levels_input_adjust_by_color (config, value, config->channel, color); levels_input_adjust_by_color (config, value, config->channel, &rgb);
} }
} }