ported the stretch and pick functions from base/levels.c.

2008-01-18  Michael Natterer  <mitch@gimp.org>

	* app/gegl/gimplevelsconfig.[ch]: ported the stretch and pick
	functions from base/levels.c.

	* app/tools/gimplevelstool.[ch]: use them instead of the old
	stuff. Also switch to GimpLevelsConfig as primary storage for all
	settings and fill the old Levels struct only when needed in map().
	Remove all hackish fiddling with levels_tool->channel because it
	is now always what is set in the menu.


svn path=/trunk/; revision=24646
This commit is contained in:
Michael Natterer
2008-01-18 13:54:46 +00:00
committed by Michael Natterer
parent ca8d74160f
commit a09925eae8
5 changed files with 300 additions and 114 deletions

View File

@ -1,3 +1,14 @@
2008-01-18 Michael Natterer <mitch@gimp.org>
* app/gegl/gimplevelsconfig.[ch]: ported the stretch and pick
functions from base/levels.c.
* app/tools/gimplevelstool.[ch]: use them instead of the old
stuff. Also switch to GimpLevelsConfig as primary storage for all
settings and fill the old Levels struct only when needed in map().
Remove all hackish fiddling with levels_tool->channel because it
is now always what is set in the menu.
2008-01-18 Michael Natterer <mitch@gimp.org>
* app/gegl/gimpoperationtilesink.c (class_init)

View File

@ -28,6 +28,8 @@
#include "gegl-types.h"
#include "base/gimphistogram.h"
#include "gimplevelsconfig.h"
@ -206,31 +208,204 @@ gimp_levels_config_set_property (GObject *object,
/* public functions */
void
gimp_levels_config_reset (GimpLevelsConfig *self)
gimp_levels_config_reset (GimpLevelsConfig *config)
{
GimpHistogramChannel channel;
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (self));
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));
self->channel = GIMP_HISTOGRAM_VALUE;
config->channel = GIMP_HISTOGRAM_VALUE;
for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA;
channel++)
{
gimp_levels_config_reset_channel (self, channel);
gimp_levels_config_reset_channel (config, channel);
}
}
void
gimp_levels_config_reset_channel (GimpLevelsConfig *self,
gimp_levels_config_reset_channel (GimpLevelsConfig *config,
GimpHistogramChannel channel)
{
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (self));
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));
self->gamma[channel] = 1.0;
self->low_input[channel] = 0.0;
self->high_input[channel] = 1.0;
self->low_output[channel] = 0.0;
self->high_output[channel] = 1.0;
config->gamma[channel] = 1.0;
config->low_input[channel] = 0.0;
config->high_input[channel] = 1.0;
config->low_output[channel] = 0.0;
config->high_output[channel] = 1.0;
}
void
gimp_levels_config_stretch (GimpLevelsConfig *config,
GimpHistogram *histogram,
gboolean is_color)
{
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));
g_return_if_fail (histogram != NULL);
if (is_color)
{
GimpHistogramChannel channel;
/* Set the overall value to defaults */
gimp_levels_config_reset_channel (config, GIMP_HISTOGRAM_VALUE);
for (channel = GIMP_HISTOGRAM_RED;
channel <= GIMP_HISTOGRAM_BLUE;
channel++)
gimp_levels_config_stretch_channel (config, histogram, channel);
}
else
{
gimp_levels_config_stretch_channel (config, histogram,
GIMP_HISTOGRAM_VALUE);
}
}
void
gimp_levels_config_stretch_channel (GimpLevelsConfig *config,
GimpHistogram *histogram,
GimpHistogramChannel channel)
{
gdouble count;
gint i;
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));
g_return_if_fail (histogram != NULL);
config->gamma[channel] = 1.0;
config->low_output[channel] = 0.0;
config->high_output[channel] = 1.0;
count = gimp_histogram_get_count (histogram, channel, 0, 255);
if (count == 0.0)
{
config->low_input[channel] = 0.0;
config->high_input[channel] = 0.0;
}
else
{
gdouble new_count;
gdouble percentage;
gdouble next_percentage;
/* Set the low input */
new_count = 0.0;
for (i = 0; i < 255; i++)
{
new_count += gimp_histogram_get_value (histogram, channel, i);
percentage = new_count / count;
next_percentage = (new_count +
gimp_histogram_get_value (histogram,
channel,
i + 1)) / count;
if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
{
config->low_input[channel] = (gdouble) (i + 1) / 255.0;
break;
}
}
/* Set the high input */
new_count = 0.0;
for (i = 255; i > 0; i--)
{
new_count += gimp_histogram_get_value (histogram, channel, i);
percentage = new_count / count;
next_percentage = (new_count +
gimp_histogram_get_value (histogram,
channel,
i - 1)) / count;
if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
{
config->high_input[channel] = (gdouble) (i - 1) / 255.0;
break;
}
}
}
}
static gdouble
gimp_levels_config_input_from_color (GimpHistogramChannel channel,
const GimpRGB *color)
{
switch (channel)
{
case GIMP_HISTOGRAM_VALUE:
return MAX (MAX (color->r, color->g), color->b);
case GIMP_HISTOGRAM_RED:
return color->r;
case GIMP_HISTOGRAM_GREEN:
return color->g;
case GIMP_HISTOGRAM_BLUE:
return color->b;
case GIMP_HISTOGRAM_ALPHA:
return color->a;
case GIMP_HISTOGRAM_RGB:
return MIN (MIN (color->r, color->g), color->b);
}
return 0.0;
}
void
gimp_levels_config_adjust_by_colors (GimpLevelsConfig *config,
GimpHistogramChannel channel,
const GimpRGB *black,
const GimpRGB *gray,
const GimpRGB *white)
{
g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));
if (black)
config->low_input[channel] = gimp_levels_config_input_from_color (channel,
black);
if (white)
config->high_input[channel] = gimp_levels_config_input_from_color (channel,
white);
if (gray)
{
gdouble input;
gdouble range;
gdouble inten;
gdouble out_light;
gdouble lightness;
/* Calculate lightness value */
lightness = GIMP_RGB_LUMINANCE (gray->r, gray->g, gray->b);
input = gimp_levels_config_input_from_color (channel, gray);
range = config->high_input[channel] - config->low_input[channel];
if (range <= 0)
return;
input -= config->low_input[channel];
if (input < 0)
return;
/* Normalize input and lightness */
inten = input / range;
out_light = lightness/ range;
if (out_light <= 0)
return;
/* Map selected color to corresponding lightness */
config->gamma[channel] = log (inten) / log (out_light);
}
}

View File

@ -54,11 +54,24 @@ struct _GimpLevelsConfigClass
};
GType gimp_levels_config_get_type (void) G_GNUC_CONST;
GType gimp_levels_config_get_type (void) G_GNUC_CONST;
void gimp_levels_config_reset (GimpLevelsConfig *config);
void gimp_levels_config_reset_channel (GimpLevelsConfig *config,
GimpHistogramChannel channel);
void gimp_levels_config_stretch (GimpLevelsConfig *config,
GimpHistogram *histogram,
gboolean is_color);
void gimp_levels_config_stretch_channel (GimpLevelsConfig *config,
GimpHistogram *histogram,
GimpHistogramChannel channel);
void gimp_levels_config_adjust_by_colors (GimpLevelsConfig *config,
GimpHistogramChannel channel,
const GimpRGB *black,
const GimpRGB *gray,
const GimpRGB *white);
void gimp_levels_config_reset (GimpLevelsConfig *self);
void gimp_levels_config_reset_channel (GimpLevelsConfig *self,
GimpHistogramChannel channel);
#endif /* __GIMP_LEVELS_CONFIG_H__ */

View File

@ -38,7 +38,6 @@
#include "base/levels.h"
#include "gegl/gimplevelsconfig.h"
#include "gegl/gimpoperationlevels.h"
#include "core/gimpdrawable.h"
#include "core/gimpdrawable-histogram.h"
@ -238,9 +237,7 @@ gimp_levels_tool_initialize (GimpTool *tool,
gimp_levels_config_reset (l_tool->config);
levels_init (l_tool->levels);
l_tool->channel = GIMP_HISTOGRAM_VALUE;
l_tool->channel = l_tool->config->channel;
l_tool->color = gimp_drawable_is_rgb (drawable);
l_tool->alpha = gimp_drawable_has_alpha (drawable);
@ -256,10 +253,6 @@ gimp_levels_tool_initialize (GimpTool *tool,
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (l_tool->channel_menu),
l_tool->channel);
/* FIXME: hack */
if (! l_tool->color)
l_tool->channel = (l_tool->channel == GIMP_HISTOGRAM_ALPHA) ? 1 : 0;
levels_update_adjustments (l_tool);
gimp_drawable_calculate_histogram (drawable, l_tool->hist);
@ -291,39 +284,35 @@ gimp_levels_tool_get_operation (GimpImageMapTool *im_tool)
static void
gimp_levels_tool_map (GimpImageMapTool *image_map_tool)
{
GimpLevelsTool *tool = GIMP_LEVELS_TOOL (image_map_tool);
GimpLevelsTool *tool = GIMP_LEVELS_TOOL (image_map_tool);
GimpLevelsConfig *config = tool->config;
Levels *levels = tool->levels;
GimpHistogramChannel channel;
for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA;
channel++)
{
/* FIXME: hack */
if (! tool->color && channel == 1)
g_object_set (tool->config,
"channel", GIMP_HISTOGRAM_ALPHA,
NULL);
else
g_object_set (tool->config,
"channel", channel,
NULL);
levels->gamma[channel] = config->gamma[channel];
levels->low_input[channel] = config->low_input[channel] * 255.999;
levels->high_input[channel] = config->high_input[channel] * 255.999;
levels->low_output[channel] = config->low_output[channel] * 255.999;
levels->high_output[channel] = config->high_output[channel] * 255.999;
}
g_object_set (tool->config,
"gamma", tool->levels->gamma[channel],
"low-input", tool->levels->low_input[channel] / 255.0,
"high-input", tool->levels->high_input[channel] / 255.0,
"low-output", tool->levels->low_output[channel] / 255.0,
"high-output", tool->levels->high_output[channel] / 255.0,
NULL);
/* FIXME: hack */
if (! tool->color && channel == 1)
break;
/* FIXME: hack */
if (! tool->color)
{
levels->gamma[1] = levels->gamma[GIMP_HISTOGRAM_ALPHA];
levels->low_input[1] = levels->low_input[GIMP_HISTOGRAM_ALPHA];
levels->high_input[1] = levels->high_input[GIMP_HISTOGRAM_ALPHA];
levels->low_output[1] = levels->low_output[GIMP_HISTOGRAM_ALPHA];
levels->high_output[1] = levels->high_output[GIMP_HISTOGRAM_ALPHA];
}
gimp_lut_setup (tool->lut,
(GimpLutFunc) levels_lut_func,
tool->levels,
levels,
gimp_drawable_bytes (image_map_tool->drawable));
}
@ -727,8 +716,6 @@ gimp_levels_tool_reset (GimpImageMapTool *image_map_tool)
GimpLevelsTool *tool = GIMP_LEVELS_TOOL (image_map_tool);
gimp_levels_config_reset (tool->config);
levels_init (tool->levels);
levels_update_adjustments (tool);
}
@ -778,13 +765,23 @@ gimp_levels_tool_settings_load (GimpImageMapTool *image_map_tool,
for (i = 0; i < 5; i++)
{
tool->levels->low_input[i] = low_input[i];
tool->levels->high_input[i] = high_input[i];
tool->levels->low_output[i] = low_output[i];
tool->levels->high_output[i] = high_output[i];
tool->levels->gamma[i] = gamma[i];
g_object_set (tool->config,
"channel", i,
NULL);
g_object_set (tool->config,
"low-input", low_input[i] / 255.0,
"high-input", high_input[i] / 255.0,
"low-output", low_output[i] / 255.0,
"high-output", high_output[i] / 255.0,
"gamma", gamma[i],
NULL);
}
g_object_set (tool->config,
"channel", tool->channel,
NULL);
levels_update_adjustments (tool);
return TRUE;
@ -810,12 +807,12 @@ gimp_levels_tool_settings_save (GimpImageMapTool *image_map_tool,
gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
fprintf (file, "%d %d %d %d %s\n",
tool->levels->low_input[i],
tool->levels->high_input[i],
tool->levels->low_output[i],
tool->levels->high_output[i],
(gint) (tool->config->low_input[i] * 255.999),
(gint) (tool->config->high_input[i] * 255.999),
(gint) (tool->config->low_output[i] * 255.999),
(gint) (tool->config->high_output[i] * 255.999),
g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f",
tool->levels->gamma[i]));
tool->config->gamma[i]));
}
return TRUE;
@ -830,11 +827,11 @@ levels_update_adjustments (GimpLevelsTool *tool)
tool->gamma_linear->upper = 255;
gtk_adjustment_set_value (tool->low_input,
tool->levels->low_input[tool->channel]);
tool->config->low_input[tool->channel] * 255.0);
gtk_adjustment_set_value (tool->gamma,
tool->levels->gamma[tool->channel]);
tool->config->gamma[tool->channel]);
gtk_adjustment_set_value (tool->high_input,
tool->levels->high_input[tool->channel]);
tool->config->high_input[tool->channel] * 255.0);
tool->low_input->upper = tool->high_input->value;
tool->high_input->lower = tool->low_input->value;
@ -845,9 +842,9 @@ levels_update_adjustments (GimpLevelsTool *tool)
gtk_adjustment_changed (tool->gamma_linear);
gtk_adjustment_set_value (tool->low_output,
tool->levels->low_output[tool->channel]);
tool->config->low_output[tool->channel] * 255.0);
gtk_adjustment_set_value (tool->high_output,
tool->levels->high_output[tool->channel]);
tool->config->high_output[tool->channel] * 255.0);
levels_update_input_bar (tool);
}
@ -855,16 +852,10 @@ levels_update_adjustments (GimpLevelsTool *tool)
static void
levels_update_input_bar (GimpLevelsTool *tool)
{
GimpHistogramChannel channel = tool->channel;
/* FIXME: hack */
if (! tool->color && channel == 1)
channel = GIMP_HISTOGRAM_ALPHA;
/* Recalculate the transfer arrays */
levels_calculate_transfers (tool->levels);
switch (channel)
switch (tool->channel)
{
case GIMP_HISTOGRAM_VALUE:
case GIMP_HISTOGRAM_ALPHA:
@ -895,15 +886,16 @@ levels_channel_callback (GtkWidget *widget,
if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value))
{
tool->channel = value;
g_object_set (tool->config,
"channel", tool->channel,
NULL);
gimp_histogram_view_set_channel (GIMP_HISTOGRAM_VIEW (tool->hist_view),
tool->channel);
gimp_color_bar_set_channel (GIMP_COLOR_BAR (tool->output_bar),
tool->channel);
/* FIXME: hack */
if (! tool->color)
tool->channel = (tool->channel == GIMP_HISTOGRAM_ALPHA) ? 1 : 0;
levels_update_adjustments (tool);
}
}
@ -912,15 +904,7 @@ static void
levels_channel_reset_callback (GtkWidget *widget,
GimpLevelsTool *tool)
{
GimpHistogramChannel channel = tool->channel;
/* FIXME: hack */
if (! tool->color && channel == 1)
channel = GIMP_HISTOGRAM_ALPHA;
gimp_levels_config_reset_channel (tool->config, channel);
levels_channel_reset (tool->levels, tool->channel);
gimp_levels_config_reset_channel (tool->config, tool->channel);
levels_update_adjustments (tool);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
@ -957,7 +941,7 @@ static void
levels_stretch_callback (GtkWidget *widget,
GimpLevelsTool *tool)
{
levels_stretch (tool->levels, tool->hist, tool->color);
gimp_levels_config_stretch (tool->config, tool->hist, tool->color);
levels_update_adjustments (tool);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
@ -970,7 +954,7 @@ levels_linear_gamma_update (GimpLevelsTool *tool)
delta = (tool->high_input->value - tool->low_input->value) / 2.0;
mid = tool->low_input->value + delta;
tmp = log10 (1.0 / tool->levels->gamma[tool->channel]);
tmp = log10 (1.0 / tool->config->gamma[tool->channel]);
value = mid + delta * tmp;
gtk_adjustment_set_value (tool->gamma_linear, value);
@ -1008,9 +992,11 @@ levels_low_input_changed (GtkAdjustment *adjustment,
gtk_adjustment_changed (tool->high_input);
gtk_adjustment_changed (tool->gamma_linear);
if (tool->levels->low_input[tool->channel] != value)
if (tool->config->low_input[tool->channel] != value / 255.0)
{
tool->levels->low_input[tool->channel] = value;
g_object_set (tool->config,
"low-input", value / 255.0,
NULL);
levels_update_input_bar (tool);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
@ -1023,9 +1009,11 @@ static void
levels_gamma_changed (GtkAdjustment *adjustment,
GimpLevelsTool *tool)
{
if (tool->levels->gamma[tool->channel] != adjustment->value)
if (tool->config->gamma[tool->channel] != adjustment->value)
{
tool->levels->gamma[tool->channel] = adjustment->value;
g_object_set (tool->config,
"gamma", adjustment->value,
NULL);
levels_update_input_bar (tool);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
@ -1045,9 +1033,11 @@ levels_high_input_changed (GtkAdjustment *adjustment,
gtk_adjustment_changed (tool->low_input);
gtk_adjustment_changed (tool->gamma_linear);
if (tool->levels->high_input[tool->channel] != value)
if (tool->config->high_input[tool->channel] != value / 255.0)
{
tool->levels->high_input[tool->channel] = value;
g_object_set (tool->config,
"high-input", value / 255.0,
NULL);
levels_update_input_bar (tool);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
@ -1062,9 +1052,11 @@ levels_low_output_changed (GtkAdjustment *adjustment,
{
gint value = ROUND (adjustment->value);
if (tool->levels->low_output[tool->channel] != value)
if (tool->config->low_output[tool->channel] != value / 255.0)
{
tool->levels->low_output[tool->channel] = value;
g_object_set (tool->config,
"low-output", value / 255.0,
NULL);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
}
@ -1076,9 +1068,11 @@ levels_high_output_changed (GtkAdjustment *adjustment,
{
gint value = ROUND (adjustment->value);
if (tool->levels->high_output[tool->channel] != value)
if (tool->config->high_output[tool->channel] != value / 255.0)
{
tool->levels->high_output[tool->channel] = value;
g_object_set (tool->config,
"high-output", value / 255.0,
NULL);
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
}
@ -1110,21 +1104,21 @@ levels_input_picker_toggled (GtkWidget *widget,
}
static void
levels_input_adjust_by_color (Levels *levels,
levels_input_adjust_by_color (GimpLevelsConfig *config,
guint value,
GimpHistogramChannel channel,
guchar *color)
const GimpRGB *color)
{
switch (value & 0xF)
{
case PICK_LOW_INPUT:
levels_adjust_by_colors (levels, channel, color, NULL, NULL);
gimp_levels_config_adjust_by_colors (config, channel, color, NULL, NULL);
break;
case PICK_GAMMA:
levels_adjust_by_colors (levels, channel, NULL, color, NULL);
gimp_levels_config_adjust_by_colors (config, channel, NULL, color, NULL);
break;
case PICK_HIGH_INPUT:
levels_adjust_by_colors (levels, channel, NULL, NULL, color);
gimp_levels_config_adjust_by_colors (config, channel, NULL, NULL, color);
break;
default:
break;
@ -1139,15 +1133,8 @@ gimp_levels_tool_color_picked (GimpColorTool *color_tool,
gint color_index)
{
GimpLevelsTool *tool = GIMP_LEVELS_TOOL (color_tool);
guchar col[5];
guint value;
gimp_rgba_get_uchar (color,
col + RED_PIX,
col + GREEN_PIX,
col + BLUE_PIX,
col + ALPHA_PIX);
value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tool->active_picker),
"pick-value"));
@ -1159,13 +1146,13 @@ gimp_levels_tool_color_picked (GimpColorTool *color_tool,
switch (value & 0xF)
{
case PICK_LOW_INPUT:
tool->levels->low_input[GIMP_HISTOGRAM_VALUE] = 0;
tool->config->low_input[GIMP_HISTOGRAM_VALUE] = 0.0;
break;
case PICK_GAMMA:
tool->levels->gamma[GIMP_HISTOGRAM_VALUE] = 1.0;
tool->config->gamma[GIMP_HISTOGRAM_VALUE] = 1.0;
break;
case PICK_HIGH_INPUT:
tool->levels->high_input[GIMP_HISTOGRAM_VALUE] = 255;
tool->config->high_input[GIMP_HISTOGRAM_VALUE] = 1.0;
break;
default:
break;
@ -1176,14 +1163,14 @@ gimp_levels_tool_color_picked (GimpColorTool *color_tool,
channel <= GIMP_HISTOGRAM_BLUE;
channel++)
{
levels_input_adjust_by_color (tool->levels,
value, channel, col);
levels_input_adjust_by_color (tool->config,
value, channel, color);
}
}
else
{
levels_input_adjust_by_color (tool->levels,
value, tool->channel, col);
levels_input_adjust_by_color (tool->config,
value, tool->channel, color);
}
levels_update_adjustments (tool);

View File

@ -38,9 +38,9 @@ struct _GimpLevelsTool
{
GimpImageMapTool parent_instance;
GimpLevelsConfig *config;
GimpLut *lut;
Levels *levels;
GimpLevelsConfig *config;
/* dialog */
gboolean color;