Commit bb2b9f68 authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

added the API for level correction using black, gray and white point.

2002-10-15  Sven Neumann  <sven@gimp.org>

	* app/base/levels.[ch]: added the API for level correction using
	black, gray and white point.

	* app/tools/gimpcurvestool.c
	* app/tools/gimphistogramtool.c
	* app/tools/gimplevelstool.[ch]: misc smaller changes.

	* app/widgets/gimphistogrambox.[ch]: allocate the buffer for the
	gradient preview on size_allocate, not for every expose event.

	* app/widgets/gimphistogramview.c: fixed drawing for width > 256.

	* themes/Default/images/stock-color-picker-white-18.png: tweaked.
parent 26bcdcca
2002-10-15 Sven Neumann <sven@gimp.org>
* app/base/levels.[ch]: added the API for level correction using
black, gray and white point.
* app/tools/gimpcurvestool.c
* app/tools/gimphistogramtool.c
* app/tools/gimplevelstool.[ch]: misc smaller changes.
* app/widgets/gimphistogrambox.[ch]: allocate the buffer for the
gradient preview on size_allocate, not for every expose event.
* app/widgets/gimphistogramview.c: fixed drawing for width > 256.
* themes/Default/images/stock-color-picker-white-18.png: tweaked.
2002-10-15 Sven Neumann <sven@gimp.org>
* app/tools/gimpinktool.c: using gtk_image_new_from_pixmap() feels
......
......@@ -61,14 +61,14 @@ levels_channel_reset (Levels *levels,
void
levels_auto (Levels *levels,
GimpHistogram *hist,
gboolean color)
gboolean is_color)
{
GimpHistogramChannel channel;
g_return_if_fail (levels != NULL);
g_return_if_fail (hist != NULL);
if (color)
if (is_color)
{
/* Set the overall value to defaults */
levels_channel_reset (levels, GIMP_HISTOGRAM_VALUE);
......@@ -144,6 +144,24 @@ levels_channel_auto (Levels *levels,
}
}
void
levels_adjust_by_colors (Levels *levels,
GimpHistogramChannel channel,
guchar *black,
guchar *gray,
guchar *white)
{
g_return_if_fail (levels != NULL);
if (black)
levels->low_input[channel] = black[channel];
/* FIXME: gray adjustment */
if (white)
levels->high_input[channel] = white[channel];
}
void
levels_calculate_transfers (Levels *levels)
{
......
......@@ -39,10 +39,15 @@ void levels_channel_reset (Levels *levels,
GimpHistogramChannel channel);
void levels_auto (Levels *levels,
GimpHistogram *hist,
gboolean color);
gboolean is_color);
void levels_channel_auto (Levels *levels,
GimpHistogram *hist,
GimpHistogramChannel channel);
void levels_adjust_by_colors (Levels *levels,
GimpHistogramChannel channel,
guchar *black,
guchar *gray,
guchar *white);
void levels_calculate_transfers (Levels *levels);
gfloat levels_lut_func (Levels *levels,
gint n_channels,
......
......@@ -256,8 +256,6 @@ gimp_curves_tool_init (GimpCurvesTool *c_tool)
i++)
c_tool->col_value[i] = -1;
gimp_tool_control_set_tool_cursor (GIMP_TOOL (c_tool)->control,
GIMP_COLOR_PICKER_TOOL_CURSOR);
}
static void
......@@ -1435,35 +1433,23 @@ file_dialog_ok_callback (GimpCurvesTool *c_tool)
filename =
gtk_file_selection_get_filename (GTK_FILE_SELECTION (c_tool->file_dialog));
if (! c_tool->is_save)
{
file = fopen (filename, "rt");
if (! file)
{
g_message (_("Failed to open file: '%s': %s"),
filename, g_strerror (errno));
return;
}
file = fopen (filename, c_tool->is_save ? "wt" : "rt");
if (! curves_read_from_file (c_tool, file))
{
g_message (("Error in reading file '%s'."), filename);
}
}
else
if (! file)
{
file = fopen (filename, "wt");
if (! file)
{
g_message (_("Failed to open file: '%s': %s"),
filename, g_strerror (errno));
return;
}
g_message (_("Failed to open file: '%s': %s"),
filename, g_strerror (errno));
return;
}
if (c_tool->is_save)
{
curves_write_to_file (c_tool, file);
}
else if (! curves_read_from_file (c_tool, file))
{
g_message (("Error in reading file '%s'."), filename);
}
if (file)
fclose (file);
......
......@@ -265,12 +265,9 @@ histogram_tool_histogram_range (GimpHistogramView *widget,
pixels = gimp_histogram_get_count (htd->hist, 0, 255);
count = gimp_histogram_get_count (htd->hist, start, end);
htd->mean = gimp_histogram_get_mean (htd->hist, htd->channel,
start, end);
htd->std_dev = gimp_histogram_get_std_dev (htd->hist, htd->channel,
start, end);
htd->median = gimp_histogram_get_median (htd->hist, htd->channel,
start, end);
htd->mean = gimp_histogram_get_mean (htd->hist, htd->channel, start, end);
htd->std_dev = gimp_histogram_get_std_dev (htd->hist, htd->channel, start, end);
htd->median = gimp_histogram_get_median (htd->hist, htd->channel, start, end);
htd->pixels = pixels;
htd->count = count;
htd->percentile = count / pixels;
......@@ -398,7 +395,7 @@ histogram_tool_dialog_new (GimpToolInfo *tool_info)
y = (i % 3);
x = (i / 3) * 2;
label = gtk_label_new (gettext(histogram_info_names[i]));
label = gtk_label_new (gettext (histogram_info_names[i]));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, x, x + 1, y, y + 1,
GTK_FILL, GTK_FILL, 2, 2);
......
......@@ -84,11 +84,15 @@
static void gimp_levels_tool_class_init (GimpLevelsToolClass *klass);
static void gimp_levels_tool_init (GimpLevelsTool *tool);
static void gimp_levels_tool_finalize (GObject *object);
static void gimp_levels_tool_finalize (GObject *object);
static void gimp_levels_tool_initialize (GimpTool *tool,
GimpDisplay *gdisp);
static void gimp_levels_tool_initialize (GimpTool *tool,
GimpDisplay *gdisp);
static void gimp_levels_tool_cursor_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
GimpDisplay *gdisp);
static void gimp_levels_tool_map (GimpImageMapTool *image_map_tool);
static void gimp_levels_tool_dialog (GimpImageMapTool *image_map_tool);
......@@ -118,6 +122,8 @@ static void levels_low_output_adjustment_update (GtkAdjustment *adjustment,
gpointer data);
static void levels_high_output_adjustment_update (GtkAdjustment *adjustment,
gpointer data);
static void levels_input_picker_toggled (GtkWidget *widget,
gpointer data);
static gint levels_input_da_events (GtkWidget *widget,
GdkEvent *event,
GimpLevelsTool *l_tool);
......@@ -201,7 +207,8 @@ gimp_levels_tool_class_init (GimpLevelsToolClass *klass)
object_class->finalize = gimp_levels_tool_finalize;
tool_class->initialize = gimp_levels_tool_initialize;
tool_class->initialize = gimp_levels_tool_initialize;
tool_class->cursor_update = gimp_levels_tool_cursor_update;
image_map_tool_class->map = gimp_levels_tool_map;
image_map_tool_class->dialog = gimp_levels_tool_dialog;
......@@ -217,10 +224,11 @@ gimp_levels_tool_init (GimpLevelsTool *l_tool)
image_map_tool->shell_desc = _("Adjust Color Levels");
l_tool->lut = gimp_lut_new ();
l_tool->levels = g_new0 (Levels, 1);
l_tool->hist = gimp_histogram_new ();
l_tool->channel = GIMP_HISTOGRAM_VALUE;
l_tool->lut = gimp_lut_new ();
l_tool->levels = g_new0 (Levels, 1);
l_tool->hist = gimp_histogram_new ();
l_tool->channel = GIMP_HISTOGRAM_VALUE;
l_tool->active_picker = NULL;
levels_init (l_tool->levels);
}
......@@ -295,6 +303,29 @@ gimp_levels_tool_initialize (GimpTool *tool,
l_tool->hist);
}
static void
gimp_levels_tool_cursor_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
GimpDisplay *gdisp)
{
if (GIMP_LEVELS_TOOL (tool)->active_picker)
{
gimp_tool_control_set_tool_cursor (tool->control, GIMP_COLOR_PICKER_TOOL_CURSOR);
gimp_tool_control_set_cursor (tool->control,
gimp_display_coords_in_active_drawable (gdisp,
coords) ?
GIMP_MOUSE_CURSOR : GIMP_BAD_CURSOR);
}
else
{
gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_NONE);
gimp_tool_control_set_cursor (tool->control, GIMP_MOUSE_CURSOR);
}
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, gdisp);
}
static void
gimp_levels_tool_map (GimpImageMapTool *image_map_tool)
{
......@@ -440,12 +471,21 @@ gimp_levels_tool_dialog (GimpImageMapTool *image_map_tool)
gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
gtk_widget_show (hbox2);
button = gtk_toggle_button_new_with_label (GIMP_STOCK_COLOR_PICKER_BLACK);
gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
"label", GIMP_STOCK_COLOR_PICKER_BLACK,
"use_stock", TRUE,
"draw_indicator", FALSE,
NULL);
gimp_help_set_help_data (button, _("Pick Black Point"), NULL);
gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_object_set_data (G_OBJECT (button), "pick-value",
GUINT_TO_POINTER (LOW_INPUT));
g_signal_connect (G_OBJECT (button), "toggled",
G_CALLBACK (levels_input_picker_toggled),
l_tool);
data = gtk_adjustment_new (0, 0, 255, 1, 10, 10);
l_tool->low_input_data = GTK_ADJUSTMENT (data);
......@@ -463,12 +503,21 @@ gimp_levels_tool_dialog (GimpImageMapTool *image_map_tool)
gtk_box_pack_start (GTK_BOX (hbox), hbox2, TRUE, FALSE, 0);
gtk_widget_show (hbox2);
button = gtk_toggle_button_new_with_label (GIMP_STOCK_COLOR_PICKER_GRAY);
gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
"label", GIMP_STOCK_COLOR_PICKER_GRAY,
"use_stock", TRUE,
"draw_indicator", FALSE,
NULL);
gimp_help_set_help_data (button, _("Pick Gray Point"), NULL);
gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_object_set_data (G_OBJECT (button), "pick-value",
GUINT_TO_POINTER (GAMMA));
g_signal_connect (G_OBJECT (button), "toggled",
G_CALLBACK (levels_input_picker_toggled),
l_tool);
data = gtk_adjustment_new (1, 0.1, 10, 0.1, 1, 1);
l_tool->gamma_data = GTK_ADJUSTMENT (data);
......@@ -487,12 +536,21 @@ gimp_levels_tool_dialog (GimpImageMapTool *image_map_tool)
gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
gtk_widget_show (hbox2);
button = gtk_toggle_button_new_with_label (GIMP_STOCK_COLOR_PICKER_WHITE);
gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
"label", GIMP_STOCK_COLOR_PICKER_WHITE,
"use_stock", TRUE,
"draw_indicator", FALSE,
NULL);
gimp_help_set_help_data (button, _("Pick White Point"), NULL);
gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_object_set_data (G_OBJECT (button), "pick-value",
GUINT_TO_POINTER (HIGH_INPUT));
g_signal_connect (G_OBJECT (button), "toggled",
G_CALLBACK (levels_input_picker_toggled),
l_tool);
data = gtk_adjustment_new (255, 0, 255, 1, 10, 10);
l_tool->high_input_data = GTK_ADJUSTMENT (data);
......@@ -649,16 +707,20 @@ levels_draw_slider (GdkWindow *window,
int y;
for (y = 0; y < CONTROL_HEIGHT; y++)
gdk_draw_line (window, fill_gc, xpos - y / 2, y,
xpos + y / 2, y);
gdk_draw_line (window, fill_gc,
xpos - y / 2, y,
xpos + y / 2, y);
gdk_draw_line (window, border_gc, xpos, 0,
gdk_draw_line (window, border_gc,
xpos, 0,
xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
gdk_draw_line (window, border_gc, xpos, 0,
gdk_draw_line (window, border_gc,
xpos, 0,
xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
gdk_draw_line (window, border_gc, xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1,
gdk_draw_line (window, border_gc,
xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1,
xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
}
......@@ -1043,6 +1105,29 @@ levels_high_output_adjustment_update (GtkAdjustment *adjustment,
}
}
static void
levels_input_picker_toggled (GtkWidget *widget,
gpointer data)
{
GimpLevelsTool *l_tool = GIMP_LEVELS_TOOL (data);
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
{
if (l_tool->active_picker == widget)
return;
if (l_tool->active_picker)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (l_tool->active_picker),
FALSE);
l_tool->active_picker = widget;
}
else if (l_tool->active_picker == widget)
{
l_tool->active_picker = NULL;
}
}
static gboolean
levels_input_da_events (GtkWidget *widget,
GdkEvent *event,
......@@ -1319,35 +1404,23 @@ file_dialog_ok_callback (GimpLevelsTool *l_tool)
filename =
gtk_file_selection_get_filename (GTK_FILE_SELECTION (l_tool->file_dialog));
if (! l_tool->is_save)
{
file = fopen (filename, "rt");
file = fopen (filename, l_tool->is_save ? "wt" : "rt");
if (! file)
{
g_message (_("Failed to open file: '%s': %s"),
filename, g_strerror (errno));
return;
}
if (! levels_read_from_file (l_tool, file))
{
g_message (("Error in reading file '%s'."), filename);
}
}
else
if (! file)
{
file = fopen (filename, "wt");
if (! file)
{
g_message (_("Failed to open file: '%s': %s"),
filename, g_strerror (errno));
return;
}
g_message (_("Failed to open file: '%s': %s"),
filename, g_strerror (errno));
return;
}
if (l_tool->is_save)
{
levels_write_to_file (l_tool, file);
}
else if (! levels_read_from_file (l_tool, file))
{
g_message (("Error in reading file '%s'."), filename);
}
if (file)
fclose (file);
......
......@@ -49,6 +49,7 @@ struct _GimpLevelsTool
GimpHistogram *hist;
GtkWidget *hist_view;
GtkWidget *active_picker;
GtkAdjustment *low_input_data;
GtkAdjustment *gamma_data;
GtkAdjustment *high_input_data;
......
......@@ -37,20 +37,25 @@
/* local function prototypes */
static void gimp_histogram_box_class_init (GimpHistogramBoxClass *klass);
static void gimp_histogram_box_init (GimpHistogramBox *histogram_box);
static void gimp_histogram_box_low_adj_update (GtkAdjustment *adj,
GimpHistogramBox *box);
static void gimp_histogram_box_high_adj_update (GtkAdjustment *adj,
GimpHistogramBox *box);
static void gimp_histogram_box_histogram_range (GimpHistogramView *view,
gint start,
gint end,
GimpHistogramBox *box);
static gboolean gimp_histogram_box_gradient_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer data);
static void gimp_histogram_box_class_init (GimpHistogramBoxClass *klass);
static void gimp_histogram_box_init (GimpHistogramBox *histogram_box);
static void gimp_histogram_box_finalize (GObject *object);
static void gimp_histogram_box_low_adj_update (GtkAdjustment *adj,
GimpHistogramBox *box);
static void gimp_histogram_box_high_adj_update (GtkAdjustment *adj,
GimpHistogramBox *box);
static void gimp_histogram_box_histogram_range (GimpHistogramView *view,
gint start,
gint end,
GimpHistogramBox *box);
static void gimp_histogram_box_gradient_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
gpointer data);
static gboolean gimp_histogram_box_gradient_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer data);
static GtkVBoxClass *parent_class = NULL;
......@@ -87,7 +92,13 @@ gimp_histogram_box_get_type (void)
static void
gimp_histogram_box_class_init (GimpHistogramBoxClass *klass)
{
GObjectClass *object_class;
parent_class = g_type_class_peek_parent (klass);
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gimp_histogram_box_finalize;
}
static void
......@@ -163,11 +174,25 @@ gimp_histogram_box_init (GimpHistogramBox *box)
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (box->gradient));
gtk_widget_show (box->gradient);
g_signal_connect (G_OBJECT (box->gradient), "size_allocate",
G_CALLBACK (gimp_histogram_box_gradient_size_allocate),
box);
g_signal_connect (G_OBJECT (box->gradient), "expose_event",
G_CALLBACK (gimp_histogram_box_gradient_expose),
box);
}
static void
gimp_histogram_box_finalize (GObject *object)
{
GimpHistogramBox *box = GIMP_HISTOGRAM_BOX (object);
g_free (box->gradient_buf);
box->gradient_buf = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_histogram_box_low_adj_update (GtkAdjustment *adjustment,
GimpHistogramBox *box)
......@@ -211,6 +236,18 @@ gimp_histogram_box_histogram_range (GimpHistogramView *widget,
gtk_adjustment_set_value (box->high_adj, end);
}
static void
gimp_histogram_box_gradient_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
gpointer data)
{
GimpHistogramBox *box = GIMP_HISTOGRAM_BOX (data);
box->gradient_buf = g_realloc (box->gradient_buf,
3 * ((allocation->width - 2) *
(allocation->height - 2)));
}
static gboolean
gimp_histogram_box_gradient_expose (GtkWidget *widget,
GdkEventExpose *event,
......@@ -219,7 +256,6 @@ gimp_histogram_box_gradient_expose (GtkWidget *widget,
GimpHistogramBox *box = GIMP_HISTOGRAM_BOX (data);
GimpHistogramChannel channel;
guchar *buffer;
gint i;
gint width, height;
guchar r, g, b;
......@@ -230,9 +266,6 @@ gimp_histogram_box_gradient_expose (GtkWidget *widget,
if (width <= 0 || height <= 0)
return TRUE;
/* FIXME: should probably reallocate on size_allocate */
buffer = g_new (guchar, 3 * width * height);
if (box->histogram)
channel = box->histogram->channel;
else
......@@ -257,21 +290,20 @@ gimp_histogram_box_gradient_expose (GtkWidget *widget,
for (i = 0; i < width; i++)
{
gint x = (i * 256) / width;
guchar *buffer = box->gradient_buf + 3 * i;
gint x = (i * 256) / width;
buffer[3 * i + 0] = x * r;
buffer[3 * i + 1] = x * g;
buffer[3 * i + 2] = x * b;
buffer[0] = x * r;
buffer[1] = x * g;
buffer[2] = x * b;
}
for (i = 1; i < height; i++)
memcpy (buffer + 3 * i * width, buffer, 3 * width);
memcpy (box->gradient_buf + 3 * i * width, box->gradient_buf, 3 * width);
gdk_draw_rgb_image (widget->window, widget->style->black_gc,
1, 1, width, height, GDK_RGB_DITHER_NORMAL,
buffer, 3 * width);
g_free (buffer);
box->gradient_buf, 3 * width);
return TRUE;
}
......
......@@ -37,6 +37,8 @@ struct _GimpHistogramBox
GtkWidget *label;
GimpHistogramView *histogram;
GtkWidget *gradient;
guchar *gradient_buf;
GtkAdjustment *low_adj;
GtkAdjustment *high_adj;
};
......
......@@ -134,7 +134,7 @@ gimp_histogram_view_expose (GtkWidget *widget,
GdkEventExpose *event)
{
GimpHistogramView *view;
gint i;
gint x, y;
gint width, height;
gdouble max;
......@@ -159,11 +159,10 @@ gimp_histogram_view_expose (GtkWidget *widget,
1, height + 1, width, height + 1);
/* Draw the spikes */
for (i = 0; i < 256; i++)
for (x = 0; x < width; x++)
{
gint y;
gint x = (width * i) / 256 + 1;
gdouble v = gimp_histogram_get_value (view->histogram, view->channel, i);
gdouble v = gimp_histogram_get_value (view->histogram, view->channel,
(x * 256) / width);
if (v > 0.0)
y = (gint) ((height * log (v)) / max);
......@@ -172,14 +171,14 @@ gimp_histogram_view_expose (GtkWidget *widget,
gdk_draw_line (widget->window,
widget->style->black_gc,
x, height + 1,
x, height + 1 - y);
x + 1, height + 1,
x + 1, height + 1 - y);
}
if (view->start >= 0 && view->end >= 0)
{
gint x1 = (width * MIN (view->start, view->end)) / 256 + 1;
gint x2 = (width * MAX (view->start, view->end)) / 256 + 1;
gint x1 = (width * MIN (view->start, view->end)) / 256;
gint x2 = (width * MAX (view->start, view->end)) / 255;
if (!view->range_gc)
{
......@@ -188,7 +187,7 @@ gimp_histogram_view_expose (GtkWidget *widget,
}
gdk_draw_rectangle (widget->window, view->range_gc, TRUE,
x1, 1, (x2 - x1) + 1, height);
x1 + 1, 1, (x2 - x1), height);
}
return TRUE;
......
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