/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include "libpikaconfig/pikaconfig.h" #include "libpikawidgets/pikawidgets.h" #include "tools-types.h" #include "operations/pikabrightnesscontrastconfig.h" #include "core/pikadrawable.h" #include "core/pikaerror.h" #include "core/pikaimage.h" #include "widgets/pikahelp-ids.h" #include "widgets/pikapropwidgets.h" #include "widgets/pikawidgets-constructors.h" #include "display/pikadisplay.h" #include "pikabrightnesscontrasttool.h" #include "pikafilteroptions.h" #include "pikatoolcontrol.h" #include "pika-intl.h" #define SLIDER_WIDTH 200 static gboolean pika_brightness_contrast_tool_initialize (PikaTool *tool, PikaDisplay *display, GError **error); static void pika_brightness_contrast_tool_button_press (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonPressType press_type, PikaDisplay *display); static void pika_brightness_contrast_tool_button_release (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonReleaseType release_type, PikaDisplay *display); static void pika_brightness_contrast_tool_motion (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaDisplay *display); static gchar * pika_brightness_contrast_tool_get_operation (PikaFilterTool *filter_tool, gchar **description); static void pika_brightness_contrast_tool_dialog (PikaFilterTool *filter_tool); static void brightness_contrast_to_levels_callback (GtkWidget *widget, PikaFilterTool *filter_tool); G_DEFINE_TYPE (PikaBrightnessContrastTool, pika_brightness_contrast_tool, PIKA_TYPE_FILTER_TOOL) #define parent_class pika_brightness_contrast_tool_parent_class void pika_brightness_contrast_tool_register (PikaToolRegisterCallback callback, gpointer data) { (* callback) (PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL, PIKA_TYPE_FILTER_OPTIONS, NULL, 0, "pika-brightness-contrast-tool", _("Brightness-Contrast"), _("Adjust brightness and contrast"), N_("B_rightness-Contrast..."), NULL, NULL, PIKA_HELP_TOOL_BRIGHTNESS_CONTRAST, PIKA_ICON_TOOL_BRIGHTNESS_CONTRAST, data); } static void pika_brightness_contrast_tool_class_init (PikaBrightnessContrastToolClass *klass) { PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass); PikaFilterToolClass *filter_tool_class = PIKA_FILTER_TOOL_CLASS (klass); tool_class->initialize = pika_brightness_contrast_tool_initialize; tool_class->button_press = pika_brightness_contrast_tool_button_press; tool_class->button_release = pika_brightness_contrast_tool_button_release; tool_class->motion = pika_brightness_contrast_tool_motion; filter_tool_class->get_operation = pika_brightness_contrast_tool_get_operation; filter_tool_class->dialog = pika_brightness_contrast_tool_dialog; } static void pika_brightness_contrast_tool_init (PikaBrightnessContrastTool *bc_tool) { } static gboolean pika_brightness_contrast_tool_initialize (PikaTool *tool, PikaDisplay *display, GError **error) { PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool); PikaImage *image = pika_display_get_image (display); GList *drawables; if (! PIKA_TOOL_CLASS (parent_class)->initialize (tool, display, error)) { return FALSE; } drawables = pika_image_get_selected_drawables (image); /* Single drawable selection has been checked in parent initialize(). */ g_return_val_if_fail (g_list_length (drawables) == 1, FALSE); if (pika_drawable_get_component_type (drawables->data) == PIKA_COMPONENT_TYPE_U8) { pika_prop_widget_set_factor (bc_tool->brightness_scale, 127.0, 1.0, 8.0, 0); pika_prop_widget_set_factor (bc_tool->contrast_scale, 127.0, 1.0, 8.0, 0); } else { pika_prop_widget_set_factor (bc_tool->brightness_scale, 0.5, 0.01, 0.1, 3); pika_prop_widget_set_factor (bc_tool->contrast_scale, 0.5, 0.01, 0.1, 3); } g_list_free (drawables); return TRUE; } static gchar * pika_brightness_contrast_tool_get_operation (PikaFilterTool *filter_tool, gchar **description) { *description = g_strdup (_("Adjust Brightness and Contrast")); return g_strdup ("pika:brightness-contrast"); } static void pika_brightness_contrast_tool_button_press (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonPressType press_type, PikaDisplay *display) { PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool); bc_tool->dragging = ! pika_filter_tool_on_guide (PIKA_FILTER_TOOL (tool), coords, display); if (! bc_tool->dragging) { PIKA_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, press_type, display); } else { gdouble brightness; gdouble contrast; g_object_get (PIKA_FILTER_TOOL (tool)->config, "brightness", &brightness, "contrast", &contrast, NULL); bc_tool->x = coords->x - contrast * 127.0; bc_tool->y = coords->y + brightness * 127.0; bc_tool->dx = contrast * 127.0; bc_tool->dy = - brightness * 127.0; tool->display = display; pika_tool_control_activate (tool->control); } } static void pika_brightness_contrast_tool_button_release (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonReleaseType release_type, PikaDisplay *display) { PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool); if (! bc_tool->dragging) { PIKA_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state, release_type, display); } else { pika_tool_control_halt (tool->control); bc_tool->dragging = FALSE; if (bc_tool->dx == 0 && bc_tool->dy == 0) return; if (release_type == PIKA_BUTTON_RELEASE_CANCEL) pika_config_reset (PIKA_CONFIG (PIKA_FILTER_TOOL (tool)->config)); } } static void pika_brightness_contrast_tool_motion (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaDisplay *display) { PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool); if (! bc_tool->dragging) { PIKA_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display); } else { bc_tool->dx = (coords->x - bc_tool->x); bc_tool->dy = - (coords->y - bc_tool->y); g_object_set (PIKA_FILTER_TOOL (tool)->config, "brightness", CLAMP (bc_tool->dy, -127.0, 127.0) / 127.0, "contrast", CLAMP (bc_tool->dx, -127.0, 127.0) / 127.0, NULL); } } /********************************/ /* Brightness Contrast dialog */ /********************************/ static void pika_brightness_contrast_tool_dialog (PikaFilterTool *filter_tool) { PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (filter_tool); GtkWidget *main_vbox; GtkWidget *scale; GtkWidget *button; main_vbox = pika_filter_tool_dialog_get_vbox (filter_tool); /* Create the brightness scale widget */ scale = pika_prop_spin_scale_new (filter_tool->config, "brightness", 0.01, 0.1, 3); pika_spin_scale_set_label (PIKA_SPIN_SCALE (scale), _("_Brightness")); gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0); bc_tool->brightness_scale = scale; /* Create the contrast scale widget */ scale = pika_prop_spin_scale_new (filter_tool->config, "contrast", 0.01, 0.1, 3); pika_spin_scale_set_label (PIKA_SPIN_SCALE (scale), _("_Contrast")); gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0); bc_tool->contrast_scale = scale; button = pika_icon_button_new (PIKA_ICON_TOOL_LEVELS, _("Edit these Settings as Levels")); gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0); gtk_widget_show (button); g_signal_connect (button, "clicked", G_CALLBACK (brightness_contrast_to_levels_callback), filter_tool); } static void brightness_contrast_to_levels_callback (GtkWidget *widget, PikaFilterTool *filter_tool) { PikaLevelsConfig *levels; levels = pika_brightness_contrast_config_to_levels_config (PIKA_BRIGHTNESS_CONTRAST_CONFIG (filter_tool->config)); pika_filter_tool_edit_as (filter_tool, "pika-levels-tool", PIKA_CONFIG (levels)); g_object_unref (levels); }