diff --git a/ChangeLog b/ChangeLog index ccbc84f601..1d9c9021f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2002-10-15 Sven Neumann + + * 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 * app/tools/gimpinktool.c: using gtk_image_new_from_pixmap() feels diff --git a/app/base/levels.c b/app/base/levels.c index 7aa38de31e..3a07c33538 100644 --- a/app/base/levels.c +++ b/app/base/levels.c @@ -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) { diff --git a/app/base/levels.h b/app/base/levels.h index b7fa3c2efc..4b42934a9f 100644 --- a/app/base/levels.h +++ b/app/base/levels.h @@ -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, diff --git a/app/tools/gimpcurvestool.c b/app/tools/gimpcurvestool.c index b211be99f3..7d4e852ae5 100644 --- a/app/tools/gimpcurvestool.c +++ b/app/tools/gimpcurvestool.c @@ -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, c_tool->is_save ? "wt" : "rt"); + + if (! file) { - file = fopen (filename, "rt"); - - if (! file) - { - g_message (_("Failed to open file: '%s': %s"), - filename, g_strerror (errno)); - return; - } - - if (! curves_read_from_file (c_tool, file)) - { - g_message (("Error in reading file '%s'."), filename); - } + g_message (_("Failed to open file: '%s': %s"), + filename, g_strerror (errno)); + return; } - else + + if (c_tool->is_save) { - file = fopen (filename, "wt"); - - if (! file) - { - g_message (_("Failed to open file: '%s': %s"), - filename, g_strerror (errno)); - return; - } - 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); diff --git a/app/tools/gimphistogramtool.c b/app/tools/gimphistogramtool.c index 7a4fd57483..2eb79174dd 100644 --- a/app/tools/gimphistogramtool.c +++ b/app/tools/gimphistogramtool.c @@ -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); diff --git a/app/tools/gimplevelstool.c b/app/tools/gimplevelstool.c index 426d571efe..b5d52fc1a5 100644 --- a/app/tools/gimplevelstool.c +++ b/app/tools/gimplevelstool.c @@ -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, l_tool->is_save ? "wt" : "rt"); + + if (! file) { - file = fopen (filename, "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); - } + g_message (_("Failed to open file: '%s': %s"), + filename, g_strerror (errno)); + return; } - else + + if (l_tool->is_save) { - file = fopen (filename, "wt"); - - if (! file) - { - g_message (_("Failed to open file: '%s': %s"), - filename, g_strerror (errno)); - return; - } - 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); diff --git a/app/tools/gimplevelstool.h b/app/tools/gimplevelstool.h index e556599b5e..ffa8c9d2d4 100644 --- a/app/tools/gimplevelstool.h +++ b/app/tools/gimplevelstool.h @@ -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; diff --git a/app/widgets/gimphistogrambox.c b/app/widgets/gimphistogrambox.c index f65a9a9a08..a46f4b323f 100644 --- a/app/widgets/gimphistogrambox.c +++ b/app/widgets/gimphistogrambox.c @@ -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_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 gboolean gimp_histogram_box_gradient_expose (GtkWidget *widget, - GdkEventExpose *event, - gpointer data); +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; } diff --git a/app/widgets/gimphistogrambox.h b/app/widgets/gimphistogrambox.h index 00ee8333c6..a3354ae969 100644 --- a/app/widgets/gimphistogrambox.h +++ b/app/widgets/gimphistogrambox.h @@ -37,6 +37,8 @@ struct _GimpHistogramBox GtkWidget *label; GimpHistogramView *histogram; GtkWidget *gradient; + guchar *gradient_buf; + GtkAdjustment *low_adj; GtkAdjustment *high_adj; }; diff --git a/app/widgets/gimphistogramview.c b/app/widgets/gimphistogramview.c index 1b4f7d12c6..5c3ae7ebfc 100644 --- a/app/widgets/gimphistogramview.c +++ b/app/widgets/gimphistogramview.c @@ -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; diff --git a/themes/Default/images/stock-color-picker-white-18.png b/themes/Default/images/stock-color-picker-white-18.png index 2852a1e980..24e07bfe28 100644 Binary files a/themes/Default/images/stock-color-picker-white-18.png and b/themes/Default/images/stock-color-picker-white-18.png differ