Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gimplevelstool.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * 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 <https://www.gnu.org/licenses/>.
 */


#include "config.h"

#include <gegl.h>
#include <gtk/gtk.h>

#include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmath.h"
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "tools-types.h"

#include "gegl/gimp-babl.h"

#include "operations/gimplevelsconfig.h"
#include "operations/gimpoperationlevels.h"

#include "core/gimp-gui.h"
#include "core/gimpasync.h"
#include "core/gimpcancelable.h"
#include "core/gimpdata.h"
#include "core/gimpdrawable.h"
#include "core/gimpdrawable-histogram.h"
#include "core/gimperror.h"
#include "core/gimphistogram.h"
#include "core/gimpimage.h"
#include "core/gimptoolinfo.h"
#include "core/gimptriviallycancelablewaitable.h"
#include "core/gimpwaitable.h"

#include "widgets/gimpcolorbar.h"
#include "widgets/gimphandlebar.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimphistogramview.h"
#include "widgets/gimppropwidgets.h"
#include "widgets/gimpwidgets-constructors.h"

#include "display/gimpdisplay.h"

#include "gimphistogramoptions.h"
#include "gimplevelstool.h"

#include "gimp-intl.h"


#define PICK_LOW_INPUT    (1 << 0)
#define PICK_GAMMA        (1 << 1)
#define PICK_HIGH_INPUT   (1 << 2)
#define PICK_ALL_CHANNELS (1 << 8)

#define HISTOGRAM_WIDTH    256
#define GRADIENT_HEIGHT     12
#define CONTROL_HEIGHT      10


/*  local function prototypes  */

static void       gimp_levels_tool_finalize       (GObject          *object);

static gboolean   gimp_levels_tool_initialize     (GimpTool         *tool,
                                                   GimpDisplay      *display,
                                                   GError          **error);

static gchar    * gimp_levels_tool_get_operation  (GimpFilterTool   *filter_tool,
                                                   gchar           **description);
static void       gimp_levels_tool_dialog         (GimpFilterTool   *filter_tool);
static void       gimp_levels_tool_reset          (GimpFilterTool   *filter_tool);
static void       gimp_levels_tool_config_notify  (GimpFilterTool   *filter_tool,
                                                   GimpConfig       *config,
                                                   const GParamSpec *pspec);
static gboolean   gimp_levels_tool_settings_import(GimpFilterTool   *filter_tool,
                                                   GInputStream     *input,
                                                   GError          **error);
static gboolean   gimp_levels_tool_settings_export(GimpFilterTool   *filter_tool,
                                                   GOutputStream    *output,
                                                   GError          **error);
static void       gimp_levels_tool_color_picked   (GimpFilterTool   *filter_tool,
                                                   gpointer          identifier,
                                                   gdouble           x,
                                                   gdouble           y,
                                                   const Babl       *sample_format,
                                                   GeglColor        *color);

static void       gimp_levels_tool_export_setup   (GimpSettingsBox  *settings_box,
                                                   GtkFileChooserDialog *dialog,
                                                   gboolean          export,
                                                   GimpLevelsTool   *tool);

static void       levels_update_input_bar         (GimpLevelsTool   *tool);

static void       levels_channel_callback         (GtkWidget        *widget,
                                                   GimpFilterTool   *filter_tool);
static void       levels_channel_reset_callback   (GtkWidget        *widget,
                                                   GimpFilterTool   *filter_tool);

static gboolean   levels_menu_sensitivity         (gint              value,
                                                   gpointer          data);

static void       levels_stretch_callback         (GtkWidget        *widget,
                                                   GimpLevelsTool   *tool);
static void       levels_linear_gamma_changed     (GtkAdjustment    *adjustment,
                                                   GimpLevelsTool   *tool);

static void       levels_to_curves_callback       (GtkWidget        *widget,
                                                   GimpFilterTool   *filter_tool);


G_DEFINE_TYPE (GimpLevelsTool, gimp_levels_tool, GIMP_TYPE_FILTER_TOOL)

#define parent_class gimp_levels_tool_parent_class


void
gimp_levels_tool_register (GimpToolRegisterCallback  callback,
                           gpointer                  data)
{
  (* callback) (GIMP_TYPE_LEVELS_TOOL,
                GIMP_TYPE_HISTOGRAM_OPTIONS,
                gimp_color_options_gui,
                0,
                "gimp-levels-tool",
                _("Levels"),
                _("Adjust color levels"),
                N_("_Levels..."), NULL,
                NULL, GIMP_HELP_TOOL_LEVELS,
                GIMP_ICON_TOOL_LEVELS,
                data);
}

static void
gimp_levels_tool_class_init (GimpLevelsToolClass *klass)
{
  GObjectClass        *object_class      = G_OBJECT_CLASS (klass);
  GimpToolClass       *tool_class        = GIMP_TOOL_CLASS (klass);
  GimpFilterToolClass *filter_tool_class = GIMP_FILTER_TOOL_CLASS (klass);

  object_class->finalize             = gimp_levels_tool_finalize;

  tool_class->initialize             = gimp_levels_tool_initialize;

  filter_tool_class->get_operation   = gimp_levels_tool_get_operation;
  filter_tool_class->dialog          = gimp_levels_tool_dialog;
  filter_tool_class->reset           = gimp_levels_tool_reset;
  filter_tool_class->config_notify   = gimp_levels_tool_config_notify;
  filter_tool_class->settings_import = gimp_levels_tool_settings_import;
  filter_tool_class->settings_export = gimp_levels_tool_settings_export;
  filter_tool_class->color_picked    = gimp_levels_tool_color_picked;
}

static void
gimp_levels_tool_init (GimpLevelsTool *tool)
{
}

static void
gimp_levels_tool_finalize (GObject *object)
{
  GimpLevelsTool *tool = GIMP_LEVELS_TOOL (object);

  g_clear_object (&tool->histogram);
  g_clear_object (&tool->histogram_async);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static gboolean
gimp_levels_tool_initialize (GimpTool     *tool,
                             GimpDisplay  *display,
                             GError      **error)
{
  GimpFilterTool   *filter_tool = GIMP_FILTER_TOOL (tool);
  GimpLevelsTool   *l_tool      = GIMP_LEVELS_TOOL (tool);
  GimpImage        *image       = gimp_display_get_image (display);
  GList            *drawables;
  GimpDrawable     *drawable;
  GimpLevelsConfig *config;
  gdouble           scale_factor;
  gdouble           step_increment;
  gdouble           page_increment;
  gint              digits;

  if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
    {
      return FALSE;
    }

  drawables = gimp_image_get_selected_drawables (image);
  if (g_list_length (drawables) != 1)
    {
      if (g_list_length (drawables) > 1)
        gimp_tool_message_literal (tool, display,
                                   _("Cannot modify multiple drawables. Select only one."));
      else
        gimp_tool_message_literal (tool, display, _("No selected drawables."));

      g_list_free (drawables);
      return FALSE;
    }

  drawable = drawables->data;
  g_list_free (drawables);

  config = GIMP_LEVELS_CONFIG (filter_tool->config);

  g_clear_object (&l_tool->histogram);
  g_clear_object (&l_tool->histogram_async);
  l_tool->histogram = gimp_histogram_new (config->trc);

  l_tool->histogram_async = gimp_drawable_calculate_histogram_async
    (drawable, l_tool->histogram, FALSE);
  gimp_histogram_view_set_histogram (GIMP_HISTOGRAM_VIEW (l_tool->histogram_view),
                                     l_tool->histogram);

  if (gimp_drawable_get_component_type (drawable) == GIMP_COMPONENT_TYPE_U8)
    {
      scale_factor   = 255.0;
      step_increment = 1.0;
      page_increment = 8.0;
      digits         = 0;
    }
  else
    {
      scale_factor   = 100;
      step_increment = 0.01;
      page_increment = 1.0;
      digits         = 2;
    }

  gimp_prop_widget_set_factor (l_tool->low_input_spinbutton,
                               scale_factor, step_increment, page_increment,
                               digits);
  gimp_prop_widget_set_factor (l_tool->high_input_spinbutton,
                               scale_factor, step_increment, page_increment,
                               digits);
  gimp_prop_widget_set_factor (l_tool->low_output_spinbutton,
                               scale_factor, step_increment, page_increment,
                               digits);
  gimp_prop_widget_set_factor (l_tool->high_output_spinbutton,
                               scale_factor, step_increment, page_increment,
                               digits);

  gtk_adjustment_configure (l_tool->gamma_linear,
                            scale_factor / 2.0,
                            0, scale_factor, 0.1, 1.0, 0);

  return TRUE;
}

static gchar *
gimp_levels_tool_get_operation (GimpFilterTool  *filter_tool,
                                gchar          **description)
{
  *description = g_strdup (_("Adjust Color Levels"));

  return g_strdup ("gimp:levels");
}


/*******************/
/*  Levels dialog  */
/*******************/

static GtkWidget *
gimp_levels_tool_color_picker_new (GimpLevelsTool *tool,
                                   guint           value)
{
  const gchar *icon_name;
  const gchar *help;
  gboolean     all_channels = (value & PICK_ALL_CHANNELS) != 0;

  switch (value & 0xF)
    {
    case PICK_LOW_INPUT:
      icon_name = GIMP_ICON_COLOR_PICKER_BLACK;

      if (all_channels)
        help = _("Pick black point for all channels");
      else
        help = _("Pick black point for the selected channel");
      break;

    case PICK_GAMMA:
      icon_name = GIMP_ICON_COLOR_PICKER_GRAY;

      if (all_channels)
        help = _("Pick gray point for all channels");
      else
        help = _("Pick gray point for the selected channel");
      break;

    case PICK_HIGH_INPUT:
      icon_name = GIMP_ICON_COLOR_PICKER_WHITE;

      if (all_channels)
        help = _("Pick white point for all channels");
      else
        help = _("Pick white point for the selected channel");
      break;

    default:
      return NULL;
    }

  return gimp_filter_tool_add_color_picker (GIMP_FILTER_TOOL (tool),
                                            GUINT_TO_POINTER (value),
                                            icon_name,
                                            help,
                                            /* pick_abyss = */ FALSE,
                                            NULL, NULL);
}

static void
gimp_levels_tool_dialog (GimpFilterTool *filter_tool)
{
  GimpLevelsTool   *tool         = GIMP_LEVELS_TOOL (filter_tool);
  GimpToolOptions  *tool_options = GIMP_TOOL_GET_OPTIONS (filter_tool);
  GimpLevelsConfig *config       = GIMP_LEVELS_CONFIG (filter_tool->config);
  GtkListStore     *store;
  GtkWidget        *main_vbox;
  GtkWidget        *frame_vbox;
  GtkWidget        *vbox;
  GtkWidget        *vbox2;
  GtkWidget        *vbox3;
  GtkWidget        *hbox;
  GtkWidget        *hbox2;
  GtkWidget        *label;
  GtkWidget        *main_frame;
  GtkWidget        *frame;
  GtkWidget        *button;
  GtkWidget        *spinbutton;
  GtkAdjustment    *adjustment;
  GtkWidget        *bar;
  GtkWidget        *handle_bar;
  gint              border;

  g_signal_connect (filter_tool->settings_box, "file-dialog-setup",
                    G_CALLBACK (gimp_levels_tool_export_setup),
                    filter_tool);

  main_vbox = gimp_filter_tool_dialog_get_vbox (filter_tool);

  /*  The combo box for selecting channels  */
  main_frame = gimp_frame_new (NULL);
  gtk_box_pack_start (GTK_BOX (main_vbox), main_frame, TRUE, TRUE, 0);
  gtk_widget_show (main_frame);

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_frame_set_label_widget (GTK_FRAME (main_frame), hbox);
  gtk_widget_show (hbox);

  label = gtk_label_new_with_mnemonic (_("Cha_nnel:"));
  gimp_label_set_attributes (GTK_LABEL (label),
                             PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
                             -1);
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  store = gimp_enum_store_new_with_range (GIMP_TYPE_HISTOGRAM_CHANNEL,
                                          GIMP_HISTOGRAM_VALUE,
                                          GIMP_HISTOGRAM_ALPHA);
  g_set_weak_pointer (&tool->channel_menu,
                      gimp_enum_combo_box_new_with_model (GIMP_ENUM_STORE (store)));
  g_object_unref (store);

  gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (tool->channel_menu),
                                       "gimp-channel");
  gimp_int_combo_box_set_sensitivity (GIMP_INT_COMBO_BOX (tool->channel_menu),
                                      levels_menu_sensitivity, filter_tool, NULL);
  gtk_box_pack_start (GTK_BOX (hbox), tool->channel_menu, FALSE, FALSE, 0);
  gtk_widget_show (tool->channel_menu);

  g_signal_connect (tool->channel_menu, "changed",
                    G_CALLBACK (levels_channel_callback),
                    tool);

  gtk_label_set_mnemonic_widget (GTK_LABEL (label), tool->channel_menu);

  button = gtk_button_new_with_mnemonic (_("R_eset Channel"));
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  g_signal_connect (button, "clicked",
                    G_CALLBACK (levels_channel_reset_callback),
                    tool);

  /*  The histogram scale radio buttons  */
  hbox2 = gimp_prop_enum_icon_box_new (G_OBJECT (tool_options),
                                       "histogram-scale", "gimp-histogram",
                                       0, 0);
  gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);

  /*  The linear/perceptual radio buttons  */
  /* XXX: override the default to Perceptual for the time being, until
   * we are able to change "gimp:levels" default for "trc" directly.
   * See #15962.
   */

  g_object_set (config,
                "trc", GIMP_TRC_PERCEPTUAL,
                NULL);
  hbox2 = gimp_prop_enum_icon_box_new (G_OBJECT (config), "trc",
                                       "gimp-color-space",
                                       -1, -1);
  gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);

  frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
  gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox);
  gtk_widget_show (frame_vbox);

  /*  Input levels frame  */
  frame = gimp_frame_new (_("Input Levels"));
  gtk_box_pack_start (GTK_BOX (frame_vbox), frame, TRUE, TRUE, 0);
  gtk_widget_show (frame);

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);

  frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
  gtk_widget_show (frame);

  vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  gtk_container_add (GTK_CONTAINER (frame), vbox2);
  gtk_widget_show (vbox2);

  g_set_weak_pointer (&tool->histogram_view,
                      gimp_histogram_view_new (FALSE));

  gtk_box_pack_start (GTK_BOX (vbox2), tool->histogram_view, TRUE, TRUE, 0);
  gtk_widget_show (GTK_WIDGET (tool->histogram_view));

  g_object_bind_property (G_OBJECT (tool_options),         "histogram-scale",
                          G_OBJECT (tool->histogram_view), "histogram-scale",
                          G_BINDING_SYNC_CREATE |
                          G_BINDING_BIDIRECTIONAL);

  g_object_get (tool->histogram_view, "border-width", &border, NULL);

  vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  gtk_container_set_border_width (GTK_CONTAINER (vbox3), border);
  gtk_box_pack_start (GTK_BOX (vbox2), vbox3, FALSE, FALSE, 0);
  gtk_widget_show (vbox3);

  tool->input_bar = g_object_new (GIMP_TYPE_COLOR_BAR, NULL);
  gtk_widget_set_size_request (tool->input_bar, -1, GRADIENT_HEIGHT / 2);
  gtk_box_pack_start (GTK_BOX (vbox3), tool->input_bar, FALSE, FALSE, 0);
  gtk_widget_show (tool->input_bar);

  bar = g_object_new (GIMP_TYPE_COLOR_BAR, NULL);
  gtk_widget_set_size_request (bar, -1, GRADIENT_HEIGHT / 2);
  gtk_box_pack_start (GTK_BOX (vbox3), bar, FALSE, FALSE, 0);
  gtk_widget_show (bar);

  handle_bar = g_object_new (GIMP_TYPE_HANDLE_BAR, NULL);
  gtk_widget_set_size_request (handle_bar, -1, CONTROL_HEIGHT);
  gtk_box_pack_start (GTK_BOX (vbox3), handle_bar, FALSE, FALSE, 0);
  gtk_widget_show (handle_bar);

  gimp_handle_bar_connect_events (GIMP_HANDLE_BAR (handle_bar),
                                  tool->input_bar);
  gimp_handle_bar_connect_events (GIMP_HANDLE_BAR (handle_bar),
                                  bar);

  /*  Horizontal box for input levels spinbuttons  */
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  /*  low input spin  */
  hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
  gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
  gtk_widget_show (hbox2);

  button = gimp_levels_tool_color_picker_new (tool, PICK_LOW_INPUT);
  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  tool->low_input_spinbutton = spinbutton =
    gimp_prop_spin_button_new (filter_tool->config, "low-input",
                               0.01, 0.1, 1);
  gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);

  tool->low_input = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spinbutton));
  gimp_handle_bar_set_adjustment (GIMP_HANDLE_BAR (handle_bar), 0,
                                  tool->low_input);

  /*  clamp input toggle  */
  hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
  gtk_box_pack_start (GTK_BOX (hbox), hbox2, TRUE, FALSE, 0);
  gtk_widget_show (hbox2);

  button = gimp_prop_check_button_new (filter_tool->config, "clamp-input",
                                       _("Clamp _input"));
  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);

  /*  input gamma spin  */
  spinbutton = gimp_prop_spin_button_new (filter_tool->config, "gamma",
                                          0.01, 0.1, 2);
  gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);
  gimp_help_set_help_data (spinbutton, _("Gamma"), NULL);

  tool->gamma = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spinbutton));

  tool->gamma_linear = gtk_adjustment_new (127, 0, 255, 0.1, 1.0, 0.0);
  g_signal_connect (tool->gamma_linear, "value-changed",
                    G_CALLBACK (levels_linear_gamma_changed),
                    tool);

  gimp_handle_bar_set_adjustment (GIMP_HANDLE_BAR (handle_bar), 1,
                                  tool->gamma_linear);
  g_object_unref (tool->gamma_linear);

  /*  high input spin  */
  hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
  gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
  gtk_widget_show (hbox2);

  button = gimp_levels_tool_color_picker_new (tool, PICK_HIGH_INPUT);
  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  spinbutton = gimp_prop_spin_button_new (filter_tool->config, "high-input",
                                          0.01, 0.1, 1);
  gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);
  tool->high_input_spinbutton = spinbutton;

  tool->high_input = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spinbutton));
  gimp_handle_bar_set_adjustment (GIMP_HANDLE_BAR (handle_bar), 2,
                                  tool->high_input);

  /*  Output levels frame  */
  frame = gimp_frame_new (_("Output Levels"));
  gtk_box_pack_start (GTK_BOX (frame_vbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);

  frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);

  vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  gtk_container_set_border_width (GTK_CONTAINER (vbox2), border);
  gtk_container_add (GTK_CONTAINER (frame), vbox2);
  gtk_widget_show (vbox2);

  tool->output_bar = g_object_new (GIMP_TYPE_COLOR_BAR, NULL);
  gtk_widget_set_size_request (tool->output_bar, -1, GRADIENT_HEIGHT);
  gtk_box_pack_start (GTK_BOX (vbox2), tool->output_bar, FALSE, FALSE, 0);
  gtk_widget_show (tool->output_bar);

  handle_bar = g_object_new (GIMP_TYPE_HANDLE_BAR, NULL);
  gtk_widget_set_size_request (handle_bar, -1, CONTROL_HEIGHT);
  gtk_box_pack_start (GTK_BOX (vbox2), handle_bar, FALSE, FALSE, 0);
  gtk_widget_show (handle_bar);

  gimp_handle_bar_connect_events (GIMP_HANDLE_BAR (handle_bar),
                                  tool->output_bar);

  /*  Horizontal box for levels spin widgets  */
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  /*  low output spin  */
  tool->low_output_spinbutton = spinbutton =
    gimp_prop_spin_button_new (filter_tool->config, "low-output",
                               0.01, 0.1, 1);
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);

  adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spinbutton));
  gimp_handle_bar_set_adjustment (GIMP_HANDLE_BAR (handle_bar), 0, adjustment);

  /*  clamp output toggle  */
  button = gimp_prop_check_button_new (filter_tool->config, "clamp-output",
                                       _("Clamp outpu_t"));
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 0);

  /*  high output spin  */
  tool->high_output_spinbutton = spinbutton =
    gimp_prop_spin_button_new (filter_tool->config, "high-output",
                               0.01, 0.1, 1);
  gtk_box_pack_end (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);

  adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spinbutton));
  gimp_handle_bar_set_adjustment (GIMP_HANDLE_BAR (handle_bar), 2, adjustment);

  /*  all channels frame  */
  main_frame = gimp_frame_new (_("All Channels"));
  gtk_box_pack_start (GTK_BOX (main_vbox), main_frame, FALSE, FALSE, 0);
  gtk_widget_show (main_frame);

  frame_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
  gtk_container_add (GTK_CONTAINER (main_frame), frame_vbox);
  gtk_widget_show (frame_vbox);

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (frame_vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  button = gtk_button_new_with_mnemonic (_("_Auto Input Levels"));
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gimp_help_set_help_data (button,
                           _("Adjust levels for all channels automatically"),
                           NULL);
  gtk_widget_show (button);

  g_signal_connect (button, "clicked",
                    G_CALLBACK (levels_stretch_callback),
                    tool);

  button = gimp_levels_tool_color_picker_new (tool,
                                              PICK_HIGH_INPUT |
                                              PICK_ALL_CHANNELS);
  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  button = gimp_levels_tool_color_picker_new (tool,
                                              PICK_GAMMA |
                                              PICK_ALL_CHANNELS);
  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  button = gimp_levels_tool_color_picker_new (tool,
                                              PICK_LOW_INPUT |
                                              PICK_ALL_CHANNELS);
  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  button = gimp_icon_button_new (GIMP_ICON_TOOL_CURVES,
                                 _("Edit these Settings as Curves"));
  gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  g_signal_connect (button, "clicked",
                    G_CALLBACK (levels_to_curves_callback),
                    tool);

  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (tool->channel_menu),
                                 config->channel);
}

static void
gimp_levels_tool_reset (GimpFilterTool *filter_tool)
{
  GimpHistogramChannel channel;

  g_object_get (filter_tool->config,
                "channel", &channel,
                NULL);

  GIMP_FILTER_TOOL_CLASS (parent_class)->reset (filter_tool);

  g_object_set (filter_tool->config,
                "channel", channel,
                NULL);
  /* XXX: the tool defaults to Perceptual, unlike the op.
   * See #15962.
   */

  g_object_set (filter_tool->config,
                "trc", GIMP_TRC_PERCEPTUAL,
                NULL);
}

static void
gimp_levels_tool_config_notify (GimpFilterTool   *filter_tool,
                                GimpConfig       *config,
                                const GParamSpec *pspec)
{
  GimpLevelsTool   *levels_tool   = GIMP_LEVELS_TOOL (filter_tool);
  GimpLevelsConfig *levels_config = GIMP_LEVELS_CONFIG (config);

  GIMP_FILTER_TOOL_CLASS (parent_class)->config_notify (filter_tool,
                                                        config, pspec);

  if (! levels_tool->channel_menu ||
      ! levels_tool->histogram_view)
    return;

  if (! strcmp (pspec->name, "trc"))
    {
      g_clear_object (&levels_tool->histogram);
      g_clear_object (&levels_tool->histogram_async);
      levels_tool->histogram = gimp_histogram_new (levels_config->trc);

      levels_tool->histogram_async = gimp_drawable_calculate_histogram_async
        (GIMP_TOOL (filter_tool)->drawables->data, levels_tool->histogram, FALSE);
      gimp_histogram_view_set_histogram (GIMP_HISTOGRAM_VIEW (levels_tool->histogram_view),
                                         levels_tool->histogram);
    }
  else if (! strcmp (pspec->name, "channel"))
    {
      gimp_histogram_view_set_channel (GIMP_HISTOGRAM_VIEW (levels_tool->histogram_view),
                                       levels_config->channel);
      gimp_color_bar_set_channel (GIMP_COLOR_BAR (levels_tool->output_bar),
                                  levels_config->channel);
      gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (levels_tool->channel_menu),
                                     levels_config->channel);
    }
  else if (! strcmp (pspec->name, "gamma")     ||
           ! strcmp (pspec->name, "low-input") ||
           ! strcmp (pspec->name, "high-input"))
    {
      gdouble low  = gtk_adjustment_get_value (levels_tool->low_input);
      gdouble high = gtk_adjustment_get_value (levels_tool->high_input);
      gdouble delta, mid, tmp, value;

      gtk_adjustment_set_lower (levels_tool->high_input,   low);
      gtk_adjustment_set_lower (levels_tool->gamma_linear, low);

      gtk_adjustment_set_upper (levels_tool->low_input,    high);
      gtk_adjustment_set_upper (levels_tool->gamma_linear, high);

      levels_update_input_bar (levels_tool);

      delta = (high - low) / 2.0;
      mid   = low + delta;
      tmp   = log10 (1.0 / levels_config->gamma[levels_config->channel]);
      value = mid + delta * tmp;

      gtk_adjustment_set_value (levels_tool->gamma_linear, value);
    }
}

static gboolean
gimp_levels_tool_settings_import (GimpFilterTool  *filter_tool,
                                  GInputStream    *input,
                                  GError         **error)
{
  GimpLevelsConfig *config = GIMP_LEVELS_CONFIG (filter_tool->config);
  gchar             header[64];
  gsize             bytes_read;

  if (! g_input_stream_read_all (input, header, sizeof (header),
                                 &bytes_read, NULL, error) ||
      bytes_read != sizeof (header))
    {
      if (error && *error)
        g_prefix_error (error, _("Could not read header: "));
      else
        g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
                     _("Could not read header: "));
      return FALSE;
    }

  g_seekable_seek (G_SEEKABLE (input), 0, G_SEEK_SET, NULL, NULL);

  if (g_str_has_prefix (header, "# GIMP Levels File\n"))
    return gimp_levels_config_load_cruft (config, input, error);

  /* Check if we're loading a Photoshop Levels preset .alv file */
  if (bytes_read > 2 && header[0] == 0 && (header[1] == 2))
    return gimp_levels_config_load_alv (config, input, error);

  return GIMP_FILTER_TOOL_CLASS (parent_class)->settings_import (filter_tool,
                                                                 input,
                                                                 error);
}

static gboolean
gimp_levels_tool_settings_export (GimpFilterTool  *filter_tool,
                                  GOutputStream   *output,
                                  GError         **error)
{
  GimpLevelsTool   *tool   = GIMP_LEVELS_TOOL (filter_tool);
  GimpLevelsConfig *config = GIMP_LEVELS_CONFIG (filter_tool->config);

  if (tool->export_old_format)
    return gimp_levels_config_save_cruft (config, output, error);

  return GIMP_FILTER_TOOL_CLASS (parent_class)->settings_export (filter_tool,
                                                                 output,
                                                                 error);
}

static void
levels_input_adjust_by_color (GimpLevelsConfig     *config,
                              guint                 value,
                              GimpHistogramChannel  channel,
                              const Babl           *target_space,
                              GeglColor            *color)
{
  switch (value & 0xF)
    {
    case PICK_LOW_INPUT:
      gimp_levels_config_adjust_by_colors (config, channel, target_space, color, NULL, NULL);
      break;
    case PICK_GAMMA:
      gimp_levels_config_adjust_by_colors (config, channel, target_space, NULL, color, NULL);
      break;
    case PICK_HIGH_INPUT:
      gimp_levels_config_adjust_by_colors (config, channel, target_space, NULL, NULL, color);
      break;
    default:
      break;
    }
}

static void
gimp_levels_tool_color_picked (GimpFilterTool *color_tool,
                               gpointer        identifier,
                               gdouble         x,
                               gdouble         y,
                               const Babl     *sample_format,
                               GeglColor      *color)
{
  GimpFilterTool   *filter_tool  = GIMP_FILTER_TOOL (color_tool);
  GimpLevelsConfig *config       = GIMP_LEVELS_CONFIG (filter_tool->config);
  guint             value        = GPOINTER_TO_UINT (identifier);
  const Babl       *target_space = NULL;

  target_space = gimp_drawable_get_space (GIMP_TOOL (filter_tool)->drawables->data);

  if (value & PICK_ALL_CHANNELS &&
      gimp_babl_format_get_base_type (sample_format) == GIMP_RGB)
    {
      GimpHistogramChannel  channel;

      /*  first reset the value channel  */
      switch (value & 0xF)
        {
        case PICK_LOW_INPUT:
          config->low_input[GIMP_HISTOGRAM_VALUE] = 0.0;
          break;
        case PICK_GAMMA:
          config->gamma[GIMP_HISTOGRAM_VALUE] = 1.0;
          break;
        case PICK_HIGH_INPUT:
          config->high_input[GIMP_HISTOGRAM_VALUE] = 1.0;
          break;
        default:
          break;
        }

      /*  then adjust all color channels  */
      for (channel = GIMP_HISTOGRAM_RED;
           channel <= GIMP_HISTOGRAM_BLUE;
           channel++)
        {
          levels_input_adjust_by_color (config, value, channel, target_space, color);
        }
    }
  else
    {
      levels_input_adjust_by_color (config, value, config->channel, target_space, color);
    }
}

static void
gimp_levels_tool_export_setup (GimpSettingsBox      *settings_box,
                               GtkFileChooserDialog *dialog,
                               gboolean              export,
                               GimpLevelsTool       *tool)
{
  GtkWidget *button;

  if (! export)
    return;

  button = gtk_check_button_new_with_mnemonic (_("Use _old levels file format"));
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
                                tool->export_old_format);
  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), button);
  gtk_widget_show (button);

  g_signal_connect (button, "toggled",
                    G_CALLBACK (gimp_toggle_button_update),
                    &tool->export_old_format);
}

static void
levels_update_input_bar (GimpLevelsTool *tool)
{
  GimpFilterTool   *filter_tool = GIMP_FILTER_TOOL (tool);
  GimpLevelsConfig *config      = GIMP_LEVELS_CONFIG (filter_tool->config);

  switch (config->channel)
    {
      gdouble value;

    case GIMP_HISTOGRAM_VALUE:
    case GIMP_HISTOGRAM_ALPHA:
    case GIMP_HISTOGRAM_RGB:
    case GIMP_HISTOGRAM_LUMINANCE:
      {
        guchar v[256];
        gint   i;

        for (i = 0; i < 256; i++)
          {
            value = gimp_operation_levels_map_input (config,
                                                     config->channel,
                                                     i / 255.0);
            v[i] = CLAMP (value, 0.0, 1.0) * 255.999;
          }

        gimp_color_bar_set_buffers (GIMP_COLOR_BAR (tool->input_bar),
                                    v, v, v);
      }
      break;

    case GIMP_HISTOGRAM_RED:
    case GIMP_HISTOGRAM_GREEN:
    case GIMP_HISTOGRAM_BLUE:
      {
        guchar r[256];
        guchar g[256];
        guchar b[256];
        gint   i;

        for (i = 0; i < 256; i++)
          {
            value = gimp_operation_levels_map_input (config,
                                                     GIMP_HISTOGRAM_RED,
                                                     i / 255.0);
            r[i] = CLAMP (value, 0.0, 1.0) * 255.999;

            value = gimp_operation_levels_map_input (config,
                                                     GIMP_HISTOGRAM_GREEN,
                                                     i / 255.0);
            g[i] = CLAMP (value, 0.0, 1.0) * 255.999;

            value = gimp_operation_levels_map_input (config,
                                                     GIMP_HISTOGRAM_BLUE,
                                                     i / 255.0);
            b[i] = CLAMP (value, 0.0, 1.0) * 255.999;
          }

        gimp_color_bar_set_buffers (GIMP_COLOR_BAR (tool->input_bar),
                                    r, g, b);
      }
      break;
    }
}

static void
levels_channel_callback (GtkWidget      *widget,
                         GimpFilterTool *filter_tool)
{
  GimpLevelsConfig *config = GIMP_LEVELS_CONFIG (filter_tool->config);
  gint              value;

  if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value) &&
      config->channel != value)
    {
      g_object_set (config,
                    "channel", value,
                    NULL);
    }
}

static void
levels_channel_reset_callback (GtkWidget      *widget,
                               GimpFilterTool *filter_tool)
{
  gimp_levels_config_reset_channel (GIMP_LEVELS_CONFIG (filter_tool->config));
}

static gboolean
levels_menu_sensitivity (gint      value,
                         gpointer  data)
{
  GimpDrawable         *drawable;
  GimpHistogramChannel  channel  = value;

  if (! GIMP_TOOL (data)->drawables)
    return FALSE;

  drawable = GIMP_TOOL (data)->drawables->data;

  switch (channel)
    {
    case GIMP_HISTOGRAM_VALUE:
      return TRUE;

    case GIMP_HISTOGRAM_RED:
    case GIMP_HISTOGRAM_GREEN:
    case GIMP_HISTOGRAM_BLUE:
      return gimp_drawable_is_rgb (drawable);

    case GIMP_HISTOGRAM_ALPHA:
      return gimp_drawable_has_alpha (drawable);

    case GIMP_HISTOGRAM_RGB:
      return FALSE;

    case GIMP_HISTOGRAM_LUMINANCE:
      return FALSE;
    }

  return FALSE;
}

static void
levels_stretch_callback (GtkWidget      *widget,
                         GimpLevelsTool *levels_tool)
{
  GimpTool       *tool        = GIMP_TOOL (levels_tool);
  GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (levels_tool);
  GimpWaitable   *waitable;

  waitable = gimp_trivially_cancelable_waitable_new (
    GIMP_WAITABLE (levels_tool->histogram_async));

  gimp_wait (tool->tool_info->gimp, waitable, _("Calculating histogram..."));

  g_object_unref (waitable);

  if (gimp_async_is_synced   (levels_tool->histogram_async) &&
      gimp_async_is_finished (levels_tool->histogram_async))
    {
      gimp_levels_config_stretch (GIMP_LEVELS_CONFIG (filter_tool->config),
                                  levels_tool->histogram,
                                  gimp_drawable_is_rgb (tool->drawables->data));
    }
}

static void
levels_linear_gamma_changed (GtkAdjustment  *adjustment,
                             GimpLevelsTool *tool)
{
  gdouble low_input  = gtk_adjustment_get_value (tool->low_input);
  gdouble high_input = gtk_adjustment_get_value (tool->high_input);
  gdouble delta, mid, tmp, value;

  delta = (high_input - low_input) / 2.0;

  if (delta >= 0.5)
    {
      mid   = low_input + delta;
      tmp   = (gtk_adjustment_get_value (adjustment) - mid) / delta;
      value = 1.0 / pow (10, tmp);

      /*  round the gamma value to the nearest 1/100th  */
      value = floor (value * 100 + 0.5) / 100.0;

      gtk_adjustment_set_value (tool->gamma, value);
    }
}

static void
levels_to_curves_callback (GtkWidget      *widget,
                           GimpFilterTool *filter_tool)
{
  GimpLevelsConfig *config = GIMP_LEVELS_CONFIG (filter_tool->config);
  GimpCurvesConfig *curves;

  curves = gimp_levels_config_to_curves_config (config);

  gimp_filter_tool_edit_as (filter_tool,
                            "gimp-curves-tool",
                            GIMP_CONFIG (curves));

  g_object_unref (curves);
}

Messung
CHZG
839710093

¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104848
#Domains=416967