static void gimp_threshold_tool_auto_clicked (GtkWidget *button, GimpThresholdTool *t_tool) { GimpTool *tool = GIMP_TOOL (t_tool); GimpWaitable *waitable; waitable = gimp_trivially_cancelable_waitable_new ( GIMP_WAITABLE (t_tool->histogram_async)); gimp_wait (tool->tool_info->gimp, waitable, _("Calculating histogram...")); g_object_unref (waitable); if (gimp_async_is_synced (t_tool->histogram_async) && gimp_async_is_finished (t_tool->histogram_async)) { 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, channel, 0, n_bins - 1); gimp_histogram_view_set_range (t_tool->histogram_box->view, low, n_bins - 1); } }
static void gimp_threshold_tool_histogram_range (GimpHistogramView *widget, gint start, gint end, GimpThresholdTool *t_tool) { GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (t_tool); gint n_bins = gimp_histogram_n_bins (t_tool->histogram); gdouble low = (gdouble) start / (n_bins - 1); gdouble high = (gdouble) end / (n_bins - 1); gdouble config_low; gdouble config_high; g_object_get (filter_tool->config, "low", &config_low, "high", &config_high, NULL); if (low != config_low || high != config_high) { g_object_set (filter_tool->config, "low", low, "high", high, NULL); } }
static void gimp_threshold_tool_dialog (GimpImageMapTool *image_map_tool) { GimpThresholdTool *t_tool = GIMP_THRESHOLD_TOOL (image_map_tool); GimpToolOptions *tool_options = GIMP_TOOL_GET_OPTIONS (image_map_tool); GimpThresholdConfig *config = t_tool->config; GtkWidget *main_vbox; GtkWidget *hbox; GtkWidget *menu; GtkWidget *box; GtkWidget *button; gint n_bins; main_vbox = gimp_image_map_tool_dialog_get_vbox (image_map_tool); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); 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); box = gimp_histogram_box_new (); gtk_box_pack_start (GTK_BOX (main_vbox), box, TRUE, TRUE, 0); gtk_widget_show (box); t_tool->histogram_box = GIMP_HISTOGRAM_BOX (box); n_bins = gimp_histogram_n_bins (t_tool->histogram); gimp_histogram_view_set_range (t_tool->histogram_box->view, config->low * (n_bins - 0.0001), config->high * (n_bins - 0.0001)); g_signal_connect (t_tool->histogram_box->view, "range-changed", G_CALLBACK (gimp_threshold_tool_histogram_range), t_tool); gimp_histogram_options_connect_view (GIMP_HISTOGRAM_OPTIONS (tool_options), t_tool->histogram_box->view); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); button = gtk_button_new_with_mnemonic (_("_Auto")); gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); gimp_help_set_help_data (button, _("Automatically adjust to optimal " "binarization threshold"), NULL); gtk_widget_show (button); g_signal_connect (button, "clicked", G_CALLBACK (gimp_threshold_tool_auto_clicked), t_tool); }
static gboolean gimp_threshold_tool_initialize (GimpTool *tool, GimpDisplay *display, GError **error) { GimpThresholdTool *t_tool = GIMP_THRESHOLD_TOOL (tool); GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool); GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable = gimp_image_get_active_drawable (image); gdouble low; gdouble high; gint n_bins; if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error)) { return FALSE; } g_clear_object (&t_tool->histogram_async); g_object_get (filter_tool->config, "low", &low, "high", &high, NULL); /* this is a hack to make sure that * 'gimp_histogram_n_bins (t_tool->histogram)' returns the correct value for * 'drawable' before the asynchronous calculation of its histogram is * finished. */ { GeglBuffer *temp; temp = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 1, 1), gimp_drawable_get_format (drawable)); gimp_histogram_calculate (t_tool->histogram, temp, GEGL_RECTANGLE (0, 0, 1, 1), NULL, NULL); g_object_unref (temp); } n_bins = gimp_histogram_n_bins (t_tool->histogram); t_tool->histogram_async = gimp_drawable_calculate_histogram_async ( drawable, t_tool->histogram, FALSE); gimp_histogram_view_set_histogram (t_tool->histogram_box->view, t_tool->histogram); gimp_histogram_view_set_range (t_tool->histogram_box->view, low * (n_bins - 0.0001), high * (n_bins - 0.0001)); return TRUE; }
static void gimp_histogram_editor_info_update (GimpHistogramEditor *editor) { GimpHistogramView *view = GIMP_HISTOGRAM_BOX (editor->box)->view; GimpHistogram *hist = editor->histogram; if (hist) { gint n_bins; gdouble pixels; gdouble count; gchar text[12]; n_bins = gimp_histogram_n_bins (hist); pixels = gimp_histogram_get_count (hist, view->channel, 0, n_bins - 1); count = gimp_histogram_get_count (hist, view->channel, view->start, view->end); g_snprintf (text, sizeof (text), "%.3f", gimp_histogram_get_mean (hist, view->channel, view->start, view->end)); gtk_label_set_text (GTK_LABEL (editor->labels[0]), text); g_snprintf (text, sizeof (text), "%.3f", gimp_histogram_get_std_dev (hist, view->channel, view->start, view->end)); gtk_label_set_text (GTK_LABEL (editor->labels[1]), text); g_snprintf (text, sizeof (text), "%.3f", gimp_histogram_get_median (hist, view->channel, view->start, view->end)); gtk_label_set_text (GTK_LABEL (editor->labels[2]), text); g_snprintf (text, sizeof (text), "%d", (gint) pixels); gtk_label_set_text (GTK_LABEL (editor->labels[3]), text); g_snprintf (text, sizeof (text), "%d", (gint) count); gtk_label_set_text (GTK_LABEL (editor->labels[4]), text); g_snprintf (text, sizeof (text), "%.1f", (pixels > 0 ? (100.0 * count / pixels) : 0.0)); gtk_label_set_text (GTK_LABEL (editor->labels[5]), text); } else { gint i; for (i = 0; i < 6; i++) gtk_label_set_text (GTK_LABEL (editor->labels[i]), NULL); } }
static void gimp_threshold_tool_auto_clicked (GtkWidget *button, GimpThresholdTool *t_tool) { GimpDrawable *drawable = GIMP_IMAGE_MAP_TOOL (t_tool)->drawable; gint n_bins = gimp_histogram_n_bins (t_tool->histogram); gdouble low; low = gimp_histogram_get_threshold (t_tool->histogram, gimp_drawable_is_rgb (drawable) ? GIMP_HISTOGRAM_RGB : GIMP_HISTOGRAM_VALUE, 0, n_bins - 1); gimp_histogram_view_set_range (t_tool->histogram_box->view, low, n_bins - 1); }
static void gimp_threshold_tool_config_notify (GObject *object, GParamSpec *pspec, GimpThresholdTool *t_tool) { GimpThresholdConfig *config = GIMP_THRESHOLD_CONFIG (object); gint n_bins; if (! t_tool->histogram_box) return; n_bins = gimp_histogram_n_bins (t_tool->histogram); gimp_histogram_view_set_range (t_tool->histogram_box->view, config->low * (n_bins - 0.0001), config->high * (n_bins - 0.0001)); }
static void gimp_threshold_tool_histogram_range (GimpHistogramView *widget, gint start, gint end, GimpThresholdTool *t_tool) { gint n_bins = gimp_histogram_n_bins (t_tool->histogram); gdouble low = (gdouble) start / (n_bins - 1); gdouble high = (gdouble) end / (n_bins - 1); if (low != t_tool->config->low || high != t_tool->config->high) { g_object_set (t_tool->config, "low", low, "high", high, NULL); } }
static void gimp_threshold_tool_config_notify (GimpFilterTool *filter_tool, GimpConfig *config, const GParamSpec *pspec) { GimpThresholdTool *t_tool = GIMP_THRESHOLD_TOOL (filter_tool); GIMP_FILTER_TOOL_CLASS (parent_class)->config_notify (filter_tool, config, pspec); if (! t_tool->histogram_box) return; if (! strcmp (pspec->name, "channel")) { GimpHistogramChannel channel; g_object_get (config, "channel", &channel, NULL); 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 (config, "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)); } }
void gimp_levels_config_stretch_channel (GimpLevelsConfig *config, GimpHistogram *histogram, GimpHistogramChannel channel) { gdouble count; gdouble bias = 0.006; gint n_bins; gint i; g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config)); g_return_if_fail (histogram != NULL); g_object_freeze_notify (G_OBJECT (config)); config->gamma[channel] = 1.0; config->low_output[channel] = 0.0; config->high_output[channel] = 1.0; n_bins = gimp_histogram_n_bins (histogram); count = gimp_histogram_get_count (histogram, channel, 0, n_bins - 1); 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 < (n_bins - 1); 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 - bias) < fabs (next_percentage - bias)) { config->low_input[channel] = (gdouble) (i + 1) / (n_bins - 1); break; } } /* Set the high input */ new_count = 0.0; for (i = (n_bins - 1); 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 - bias) < fabs (next_percentage - bias)) { config->high_input[channel] = (gdouble) (i - 1) / (n_bins - 1); break; } } } g_object_notify (G_OBJECT (config), "gamma"); g_object_notify (G_OBJECT (config), "low-input"); g_object_notify (G_OBJECT (config), "high-input"); g_object_notify (G_OBJECT (config), "low-output"); g_object_notify (G_OBJECT (config), "high-output"); g_object_thaw_notify (G_OBJECT (config)); }