예제 #1
0
void gui_init(dt_iop_module_t *self)
{
  self->gui_data = malloc(sizeof(dt_iop_levels_gui_data_t));
  dt_iop_levels_gui_data_t *c = (dt_iop_levels_gui_data_t *)self->gui_data;
  dt_iop_levels_params_t *p = (dt_iop_levels_params_t *)self->params;

  dt_pthread_mutex_init(&c->lock, NULL);

  dt_pthread_mutex_lock(&c->lock);
  c->auto_levels[0] = NAN;
  c->auto_levels[1] = NAN;
  c->auto_levels[2] = NAN;
  dt_pthread_mutex_unlock(&c->lock);

  c->modes = NULL;

  c->mouse_x = c->mouse_y = -1.0;
  c->dragging = 0;
  c->activeToggleButton = NULL;
  c->current_pick = NONE;
  c->last_picked_color = -1;
  for(int i = 0; i < 3; i++)
    for(int j = 0; j < 2; j++) c->pick_xy_positions[i][j] = -1;
  self->widget = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5));

  c->mode = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(c->mode, NULL, _("mode"));

  dt_bauhaus_combobox_add(c->mode, C_("mode", "manual"));
  c->modes = g_list_append(c->modes, GUINT_TO_POINTER(LEVELS_MODE_MANUAL));

  dt_bauhaus_combobox_add(c->mode, _("automatic"));
  c->modes = g_list_append(c->modes, GUINT_TO_POINTER(LEVELS_MODE_AUTOMATIC));

  dt_bauhaus_combobox_set_default(c->mode, LEVELS_MODE_MANUAL);
  dt_bauhaus_combobox_set(c->mode, g_list_index(c->modes, GUINT_TO_POINTER(p->mode)));
  gtk_box_pack_start(GTK_BOX(self->widget), c->mode, TRUE, TRUE, 0);

  c->mode_stack = gtk_stack_new();
  gtk_stack_set_homogeneous(GTK_STACK(c->mode_stack),FALSE);
  gtk_box_pack_start(GTK_BOX(self->widget), c->mode_stack, TRUE, TRUE, 0);

  c->area = GTK_DRAWING_AREA(dtgtk_drawing_area_new_with_aspect_ratio(9.0 / 16.0));
  GtkWidget *vbox_manual = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5));
  gtk_box_pack_start(GTK_BOX(vbox_manual), GTK_WIDGET(c->area), TRUE, TRUE, 0);

  gtk_widget_set_tooltip_text(GTK_WIDGET(c->area),_("drag handles to set black, gray, and white points. "
                                                    "operates on L channel."));

  gtk_widget_add_events(GTK_WIDGET(c->area), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
                                             | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
                                             | GDK_LEAVE_NOTIFY_MASK | GDK_SCROLL_MASK);
  g_signal_connect(G_OBJECT(c->area), "draw", G_CALLBACK(dt_iop_levels_area_draw), self);
  g_signal_connect(G_OBJECT(c->area), "button-press-event", G_CALLBACK(dt_iop_levels_button_press), self);
  g_signal_connect(G_OBJECT(c->area), "button-release-event", G_CALLBACK(dt_iop_levels_button_release), self);
  g_signal_connect(G_OBJECT(c->area), "motion-notify-event", G_CALLBACK(dt_iop_levels_motion_notify), self);
  g_signal_connect(G_OBJECT(c->area), "leave-notify-event", G_CALLBACK(dt_iop_levels_leave_notify), self);
  g_signal_connect(G_OBJECT(c->area), "scroll-event", G_CALLBACK(dt_iop_levels_scroll), self);

  GtkWidget *autobutton = gtk_button_new_with_label(_("auto"));
  gtk_widget_set_tooltip_text(autobutton, _("apply auto levels"));
  gtk_widget_set_size_request(autobutton, -1, DT_PIXEL_APPLY_DPI(24));

  GtkWidget *blackpick = dtgtk_togglebutton_new(dtgtk_cairo_paint_colorpicker, CPF_STYLE_FLAT);
  gtk_widget_set_tooltip_text(blackpick, _("pick black point from image"));

  GtkWidget *greypick = dtgtk_togglebutton_new(dtgtk_cairo_paint_colorpicker, CPF_STYLE_FLAT);
  gtk_widget_set_tooltip_text(greypick, _("pick medium gray point from image"));

  GtkWidget *whitepick = dtgtk_togglebutton_new(dtgtk_cairo_paint_colorpicker, CPF_STYLE_FLAT);
  gtk_widget_set_tooltip_text(whitepick, _("pick white point from image"));

  GdkRGBA color = { 0 };
  color.alpha = 1.0;
  dtgtk_togglebutton_override_color(DTGTK_TOGGLEBUTTON(blackpick), &color);
  color.red = color.green = color.blue = 0.5;
  dtgtk_togglebutton_override_color(DTGTK_TOGGLEBUTTON(greypick), &color);
  color.red = color.green = color.blue = 1.0;
  dtgtk_togglebutton_override_color(DTGTK_TOGGLEBUTTON(whitepick), &color);

  GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_PIXEL_APPLY_DPI(10));
  gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(autobutton), TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(blackpick), TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(greypick), TRUE, TRUE, 0);
  gtk_box_pack_end(GTK_BOX(box), GTK_WIDGET(whitepick), TRUE, TRUE, 0);

  gtk_box_pack_start(GTK_BOX(vbox_manual), box, TRUE, TRUE, 0);

  gtk_widget_show_all(vbox_manual);
  gtk_stack_add_named(GTK_STACK(c->mode_stack), vbox_manual, "manual");

  c->percentile_black = dt_bauhaus_slider_new_with_range(self, 0.0f, 100.0f, .1f, p->percentiles[0], 3);
  gtk_widget_set_tooltip_text(c->percentile_black, _("black percentile"));
  dt_bauhaus_slider_set_format(c->percentile_black, "%.1f%%");
  dt_bauhaus_widget_set_label(c->percentile_black, NULL, _("black"));

  c->percentile_grey = dt_bauhaus_slider_new_with_range(self, 0.0f, 100.0f, .1f, p->percentiles[1], 3);
  gtk_widget_set_tooltip_text(c->percentile_grey, _("gray percentile"));
  dt_bauhaus_slider_set_format(c->percentile_grey, "%.1f%%");
  dt_bauhaus_widget_set_label(c->percentile_grey, NULL, _("gray"));

  c->percentile_white = dt_bauhaus_slider_new_with_range(self, 0.0f, 100.0f, .1f, p->percentiles[2], 3);
  gtk_widget_set_tooltip_text(c->percentile_white, _("white percentile"));
  dt_bauhaus_slider_set_format(c->percentile_white, "%.1f%%");
  dt_bauhaus_widget_set_label(c->percentile_white, NULL, _("white"));

  GtkWidget *vbox_automatic = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5));
  gtk_box_pack_start(GTK_BOX(vbox_automatic), GTK_WIDGET(c->percentile_black), FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox_automatic), GTK_WIDGET(c->percentile_grey), FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox_automatic), GTK_WIDGET(c->percentile_white), FALSE, FALSE, 0);

  gtk_widget_show_all(vbox_automatic);
  gtk_stack_add_named(GTK_STACK(c->mode_stack), vbox_automatic, "automatic");

  switch(p->mode)
  {
    case LEVELS_MODE_AUTOMATIC:
      gtk_stack_set_visible_child_name(GTK_STACK(c->mode_stack), "automatic");
      break;
    case LEVELS_MODE_MANUAL:
    default:
      gtk_stack_set_visible_child_name(GTK_STACK(c->mode_stack), "manual");
      break;
  }

  g_signal_connect(G_OBJECT(c->mode), "value-changed", G_CALLBACK(dt_iop_levels_mode_callback), self);
  g_signal_connect(G_OBJECT(c->percentile_black), "value-changed",
                   G_CALLBACK(dt_iop_levels_percentiles_callback), self);
  g_signal_connect(G_OBJECT(c->percentile_grey), "value-changed",
                   G_CALLBACK(dt_iop_levels_percentiles_callback), self);
  g_signal_connect(G_OBJECT(c->percentile_white), "value-changed",
                   G_CALLBACK(dt_iop_levels_percentiles_callback), self);

  g_signal_connect(G_OBJECT(autobutton), "clicked", G_CALLBACK(dt_iop_levels_autoadjust_callback),
                   (gpointer)self);
  g_signal_connect(G_OBJECT(blackpick), "toggled", G_CALLBACK(dt_iop_levels_pick_black_callback), self);
  g_signal_connect(G_OBJECT(greypick), "toggled", G_CALLBACK(dt_iop_levels_pick_grey_callback), self);
  g_signal_connect(G_OBJECT(whitepick), "toggled", G_CALLBACK(dt_iop_levels_pick_white_callback), self);
}
예제 #2
0
void gui_init(struct dt_iop_module_t *self)
{
  self->gui_data = malloc(sizeof(dt_iop_exposure_gui_data_t));
  dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data;
  dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params;

  g->modes = NULL;
  g->deflicker_histogram_sources = NULL;

  g->deflicker_histogram = NULL;

  dt_pthread_mutex_init(&g->lock, NULL);

  /* register hooks with current dev so that  histogram
     can interact with this module.
   */
  darktable.develop->proxy.exposure.module = self;
  darktable.develop->proxy.exposure.set_white = dt_iop_exposure_set_white;
  darktable.develop->proxy.exposure.get_white = dt_iop_exposure_get_white;
  darktable.develop->proxy.exposure.set_black = dt_iop_exposure_set_black;
  darktable.develop->proxy.exposure.get_black = dt_iop_exposure_get_black;

  self->request_color_pick = DT_REQUEST_COLORPICK_OFF;

  self->widget = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE));

  g->mode = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(g->mode, NULL, _("mode"));

  dt_bauhaus_combobox_add(g->mode, C_("mode", "manual"));
  g->modes = g_list_append(g->modes, GUINT_TO_POINTER(EXPOSURE_MODE_MANUAL));

  dt_bauhaus_combobox_add(g->mode, _("automatic"));
  g->modes = g_list_append(g->modes, GUINT_TO_POINTER(EXPOSURE_MODE_DEFLICKER));

  dt_bauhaus_combobox_set_default(g->mode, 0);
  dt_bauhaus_combobox_set(g->mode, g_list_index(g->modes, GUINT_TO_POINTER(p->mode)));

  gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->mode), TRUE, TRUE, 0);

  g->black = dt_bauhaus_slider_new_with_range(self, -0.1, 0.1, .001, p->black, 4);
  g_object_set(G_OBJECT(g->black), "tooltip-text", _("adjust the black level"), (char *)NULL);
  dt_bauhaus_slider_set_format(g->black, "%.4f");
  dt_bauhaus_widget_set_label(g->black, NULL, _("black"));
  dt_bauhaus_slider_enable_soft_boundaries(g->black, -1.0, 1.0);
  gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->black), TRUE, TRUE, 0);

  g->mode_stack = gtk_stack_new();
  gtk_stack_set_homogeneous(GTK_STACK(g->mode_stack),FALSE);
  gtk_box_pack_start(GTK_BOX(self->widget), g->mode_stack, TRUE, TRUE, 0);

  GtkWidget *vbox_manual = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE));

  g->exposure = dt_bauhaus_slider_new_with_range(self, -3.0, 3.0, .02, p->exposure, 3);
  g_object_set(G_OBJECT(g->exposure), "tooltip-text", _("adjust the exposure correction"), (char *)NULL);
  dt_bauhaus_slider_set_format(g->exposure, "%.2fEV");
  dt_bauhaus_widget_set_label(g->exposure, NULL, _("exposure"));
  dt_bauhaus_slider_enable_soft_boundaries(g->exposure, -18.0, 18.0);
  gtk_box_pack_start(GTK_BOX(vbox_manual), GTK_WIDGET(g->exposure), TRUE, TRUE, 0);

  GtkBox *hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));

  g->autoexp = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("auto")));
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoexp), FALSE);
  gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(g->autoexp), FALSE, TRUE, 0);

  g->autoexpp = dt_bauhaus_slider_new_with_range(self, 0.0, 0.2, .001, 0.01, 3);
  g_object_set(G_OBJECT(g->autoexpp), "tooltip-text", _("percentage of bright values clipped out"),
               (char *)NULL);
  gtk_widget_set_sensitive(GTK_WIDGET(g->autoexpp), TRUE);
  gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(g->autoexpp), TRUE, TRUE, 0);

  gtk_box_pack_start(GTK_BOX(vbox_manual), GTK_WIDGET(hbox), TRUE, TRUE, 0);
  gtk_widget_show_all(vbox_manual);
  gtk_stack_add_named(GTK_STACK(g->mode_stack), vbox_manual, "manual");

  GtkWidget *vbox_deflicker = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE));

  g->deflicker_percentile = dt_bauhaus_slider_new_with_range(self, 0, 100, .01, p->deflicker_percentile, 3);
  // FIXME: this needs a better tooltip!
  g_object_set(G_OBJECT(g->deflicker_percentile), "tooltip-text", _("percentile"), (char *)NULL);
  dt_bauhaus_slider_set_format(g->deflicker_percentile, "%.2f%%");
  dt_bauhaus_widget_set_label(g->deflicker_percentile, NULL, _("percentile"));
  gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(g->deflicker_percentile), TRUE, TRUE, 0);

  g->deflicker_target_level
      = dt_bauhaus_slider_new_with_range(self, -18.0, 18.0, .01, p->deflicker_target_level, 3);
  g_object_set(G_OBJECT(g->deflicker_target_level), "tooltip-text", _("target level"), (char *)NULL);
  dt_bauhaus_slider_set_format(g->deflicker_target_level, "%.2fEV");
  dt_bauhaus_widget_set_label(g->deflicker_target_level, NULL, _("target level"));
  gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(g->deflicker_target_level), TRUE, TRUE, 0);

  g->deflicker_histogram_source = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(g->deflicker_histogram_source, NULL, _("histogram of"));

  dt_bauhaus_combobox_add(g->deflicker_histogram_source, _("pre-processed image"));
  g->deflicker_histogram_sources
      = g_list_append(g->deflicker_histogram_sources, GUINT_TO_POINTER(DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL));

  dt_bauhaus_combobox_add(g->deflicker_histogram_source, _("source raw data"));
  g->deflicker_histogram_sources = g_list_append(g->deflicker_histogram_sources,
                                                 GUINT_TO_POINTER(DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE));

  dt_bauhaus_combobox_set_default(g->deflicker_histogram_source, DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL);
  dt_bauhaus_combobox_set(g->deflicker_histogram_source,
                          g_list_index(g->modes, GUINT_TO_POINTER(p->deflicker_histogram_source)));
  gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(g->deflicker_histogram_source), TRUE, TRUE, 0);

  GtkBox *hbox1 = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
  GtkLabel *label = GTK_LABEL(gtk_label_new(_("computed EC: ")));
  gtk_box_pack_start(GTK_BOX(hbox1), GTK_WIDGET(label), FALSE, FALSE, 0);

  g->deflicker_used_EC = GTK_LABEL(gtk_label_new("")); // This gets filled in by process
  g_object_set(G_OBJECT(g->deflicker_used_EC), "tooltip-text",
               _("what exposure correction have actually been used"), (char *)NULL);
  gtk_box_pack_start(GTK_BOX(hbox1), GTK_WIDGET(g->deflicker_used_EC), FALSE, FALSE, 0);

  dt_pthread_mutex_lock(&g->lock);
  g->deflicker_computed_exposure = NAN;
  dt_pthread_mutex_unlock(&g->lock);

  gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(hbox1), FALSE, FALSE, 0);

  gtk_widget_show_all(vbox_deflicker);
  gtk_stack_add_named(GTK_STACK(g->mode_stack), vbox_deflicker, "deflicker");

  g_signal_connect(G_OBJECT(g->mode), "value-changed", G_CALLBACK(mode_callback), self);
  g_signal_connect(G_OBJECT(g->black), "value-changed", G_CALLBACK(black_callback), self);
  g_signal_connect(G_OBJECT(g->exposure), "value-changed", G_CALLBACK(exposure_callback), self);
  g_signal_connect(G_OBJECT(g->autoexpp), "value-changed", G_CALLBACK(autoexpp_callback), self);
  g_signal_connect(G_OBJECT(g->autoexp), "toggled", G_CALLBACK(autoexp_callback), self);
  g_signal_connect(G_OBJECT(g->deflicker_percentile), "value-changed", G_CALLBACK(deflicker_params_callback),
                   self);
  g_signal_connect(G_OBJECT(g->deflicker_target_level), "value-changed",
                   G_CALLBACK(deflicker_params_callback), self);
  g_signal_connect(G_OBJECT(g->deflicker_histogram_source), "value-changed",
                   G_CALLBACK(deflicker_histogram_source_callback), self);
  g_signal_connect(G_OBJECT(self->widget), "draw", G_CALLBACK(draw), self);
}
예제 #3
0
파일: bilat.c 프로젝트: CChiappa/darktable
void gui_init(dt_iop_module_t *self)
{
  // init the slider (more sophisticated layouts are possible with gtk tables and boxes):
  self->gui_data = malloc(sizeof(dt_iop_bilat_gui_data_t));
  dt_iop_bilat_gui_data_t *g = (dt_iop_bilat_gui_data_t *)self->gui_data;
  memset(&g->ll_boundary, 0, sizeof(local_laplacian_boundary_t));
  dt_pthread_mutex_init(&g->lock, NULL);
  g->hash = 0;
  self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE);

  g->mode = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(g->mode, NULL, _("mode"));
  gtk_box_pack_start(GTK_BOX(self->widget), g->mode, TRUE, TRUE, 0);
  dt_bauhaus_combobox_add(g->mode, _("bilateral grid"));
  dt_bauhaus_combobox_add(g->mode, _("local laplacian filter"));
  dt_bauhaus_combobox_set_default(g->mode, s_mode_local_laplacian);
  dt_bauhaus_combobox_set(g->mode, s_mode_local_laplacian);
  gtk_widget_set_tooltip_text(g->mode, _("the filter used for local contrast enhancement. bilateral is faster but can lead to artifacts around edges for extreme settings."));

  g->detail = dt_bauhaus_slider_new_with_range(self, 0.0, 500.0, 1.0, 120.0, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), g->detail, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->detail, NULL, _("detail"));
  dt_bauhaus_slider_set_format(g->detail, "%.0f%%");
  gtk_widget_set_tooltip_text(g->detail, _("changes the local contrast"));

  g->spatial = dt_bauhaus_slider_new_with_range(self, 1, 100, 1, 50, 0);
  dt_bauhaus_widget_set_label(g->spatial, NULL, _("coarseness"));
  gtk_box_pack_start(GTK_BOX(self->widget), g->spatial, TRUE, TRUE, 0);
  gtk_widget_set_tooltip_text(g->spatial, _("feature size of local details (spatial sigma of bilateral filter)"));

  g->range = dt_bauhaus_slider_new_with_range(self, 1, 100, 1, 20, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), g->range, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->range, NULL, _("contrast"));
  gtk_widget_set_tooltip_text(g->range, _("L difference to detect edges (range sigma of bilateral filter)"));

  g->highlights = dt_bauhaus_slider_new_with_range(self, 0.0, 200.0, 1.0, 100.0, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), g->highlights, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->highlights, NULL, _("highlights"));
  dt_bauhaus_slider_set_format(g->highlights, "%.0f%%");
  gtk_widget_set_tooltip_text(g->highlights, _("changes the local contrast of highlights"));

  g->shadows = dt_bauhaus_slider_new_with_range(self, 0.0, 200.0, 1.0, 100.0, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), g->shadows, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->shadows, NULL, _("shadows"));
  gtk_widget_set_tooltip_text(g->shadows, _("changes the local contrast of shadows"));
  dt_bauhaus_slider_set_format(g->shadows, "%.0f%%");

  g->midtone = dt_bauhaus_slider_new_with_range(self, 0.001, 1.0, 0.001, 0.2, 3);
  gtk_box_pack_start(GTK_BOX(self->widget), g->midtone, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->midtone, NULL, _("midtone range"));
  gtk_widget_set_tooltip_text(g->midtone, _("defines what counts as midtones. lower for better dynamic range compression (reduce shadow and highlight contrast), increase for more powerful local contrast"));

  // work around multi-instance issue which calls show all a fair bit:
  g_object_set(G_OBJECT(g->highlights), "no-show-all", TRUE, NULL);
  g_object_set(G_OBJECT(g->shadows), "no-show-all", TRUE, NULL);
  g_object_set(G_OBJECT(g->midtone), "no-show-all", TRUE, NULL);
  g_object_set(G_OBJECT(g->range), "no-show-all", TRUE, NULL);
  g_object_set(G_OBJECT(g->spatial), "no-show-all", TRUE, NULL);

  g_signal_connect(G_OBJECT(g->spatial), "value-changed", G_CALLBACK(spatial_callback), self);
  g_signal_connect(G_OBJECT(g->range), "value-changed", G_CALLBACK(range_callback), self);
  g_signal_connect(G_OBJECT(g->detail), "value-changed", G_CALLBACK(detail_callback), self);
  g_signal_connect(G_OBJECT(g->highlights), "value-changed", G_CALLBACK(highlights_callback), self);
  g_signal_connect(G_OBJECT(g->shadows), "value-changed", G_CALLBACK(shadows_callback), self);
  g_signal_connect(G_OBJECT(g->midtone), "value-changed", G_CALLBACK(midtone_callback), self);
  g_signal_connect(G_OBJECT(g->mode), "value-changed", G_CALLBACK(mode_callback), self);
}