Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gimp/app/actions/   (Gimp Bildeditor Version 3.2.0©)  Datei vom 14.2.2026 mit Größe 58 kB image not shown  

Quelle  image-commands.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 "libgimpcolor/gimpcolor.h"
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "actions-types.h"

#include "config/gimpdialogconfig.h"

#include "gegl/gimp-babl.h"

#include "core/core-enums.h"
#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimpimage-color-profile.h"
#include "core/gimpimage-convert-indexed.h"
#include "core/gimpimage-convert-precision.h"
#include "core/gimpimage-convert-type.h"
#include "core/gimpimage-crop.h"
#include "core/gimpimage-duplicate.h"
#include "core/gimpimage-flip.h"
#include "core/gimpimage-merge.h"
#include "core/gimpimage-resize.h"
#include "core/gimpimage-rotate.h"
#include "core/gimpimage-scale.h"
#include "core/gimpimage-undo.h"
#include "core/gimpitem.h"
#include "core/gimppickable.h"
#include "core/gimppickable-auto-shrink.h"
#include "core/gimpprogress.h"

#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdock.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpwidgets-utils.h"

#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"

#include "dialogs/dialogs.h"
#include "dialogs/color-profile-dialog.h"
#include "dialogs/convert-indexed-dialog.h"
#include "dialogs/convert-precision-dialog.h"
#include "dialogs/grid-dialog.h"
#include "dialogs/image-merge-layers-dialog.h"
#include "dialogs/image-new-dialog.h"
#include "dialogs/image-properties-dialog.h"
#include "dialogs/image-scale-dialog.h"
#include "dialogs/print-size-dialog.h"
#include "dialogs/resize-dialog.h"

#include "actions.h"
#include "image-commands.h"

#include "gimp-intl.h"


/*  local function prototypes  */

static void   image_convert_rgb_callback       (GtkWidget                *dialog,
                                                GimpImage                *image,
                                                GimpColorProfile         *new_profile,
                                                GFile                    *new_file,
                                                GimpColorRenderingIntent  intent,
                                                gboolean                  bpc,
                                                gpointer                  user_data);

static void   image_convert_gray_callback      (GtkWidget                *dialog,
                                                GimpImage                *image,
                                                GimpColorProfile         *new_profile,
                                                GFile                    *new_file,
                                                GimpColorRenderingIntent  intent,
                                                gboolean                  bpc,
                                                gpointer                  user_data);

static void   image_convert_indexed_callback   (GtkWidget              *dialog,
                                                GimpImage              *image,
                                                GimpConvertPaletteType  palette_type,
                                                gint                    max_colors,
                                                gboolean                remove_duplicates,
                                                GimpConvertDitherType   dither_type,
                                                gboolean                dither_alpha,
                                                gboolean                dither_text_layers,
                                                GimpPalette            *custom_palette,
                                                gpointer                user_data);

static void   image_convert_precision_callback (GtkWidget              *dialog,
                                                GimpImage              *image,
                                                GimpPrecision           precision,
                                                GeglDitherMethod        layer_dither_method,
                                                GeglDitherMethod        text_layer_dither_method,
                                                GeglDitherMethod        mask_dither_method,
                                                gpointer                user_data);

static void   image_profile_assign_callback    (GtkWidget                *dialog,
                                                GimpImage                *image,
                                                GimpColorProfile         *new_profile,
                                                GFile                    *new_file,
                                                GimpColorRenderingIntent  intent,
                                                gboolean                  bpc,
                                                gpointer                  user_data);

static void   image_profile_convert_callback   (GtkWidget                *dialog,
                                                GimpImage                *image,
                                                GimpColorProfile         *new_profile,
                                                GFile                    *new_file,
                                                GimpColorRenderingIntent  intent,
                                                gboolean                  bpc,
                                                gpointer                  user_data);

static void   image_resize_callback            (GtkWidget              *dialog,
                                                GimpViewable           *viewable,
                                                GimpContext            *context,
                                                gint                    width,
                                                gint                    height,
                                                GimpUnit               *unit,
                                                gint                    offset_x,
                                                gint                    offset_y,
                                                gdouble                 xres,
                                                gdouble                 yres,
                                                GimpUnit               *res_unit,
                                                GimpFillType            fill_type,
                                                GimpItemSet             layer_set,
                                                gboolean                resize_text_layers,
                                                gpointer                user_data);

static void   image_print_size_callback        (GtkWidget              *dialog,
                                                GimpImage              *image,
                                                gdouble                 xresolution,
                                                gdouble                 yresolution,
                                                GimpUnit               *resolution_unit,
                                                gpointer                user_data);

static void   image_scale_callback             (GtkWidget              *dialog,
                                                GimpViewable           *viewable,
                                                gint                    width,
                                                gint                    height,
                                                GimpUnit               *unit,
                                                GimpInterpolationType   interpolation,
                                                gdouble                 xresolution,
                                                gdouble                 yresolution,
                                                GimpUnit               *resolution_unit,
                                                gpointer                user_data);

static void   image_merge_layers_callback      (GtkWidget              *dialog,
                                                GimpImage              *image,
                                                GimpContext            *context,
                                                GimpMergeType           merge_type,
                                                gboolean                merge_active_group,
                                                gboolean                discard_invisible,
                                                gpointer                user_data);

static void   image_softproof_profile_callback  (GtkWidget                *dialog,
                                                 GimpImage                *image,
                                                 GimpColorProfile         *new_profile,
                                                 GFile                    *new_file,
                                                 GimpColorRenderingIntent  intent,
                                                 gboolean                  bpc,
                                                 gpointer                  user_data);



/*  private variables  */

static GimpUnit              *image_resize_unit  = NULL;
static GimpUnit              *image_scale_unit   = NULL;
static GimpInterpolationType  image_scale_interp = -1;
static GimpPalette           *image_convert_indexed_custom_palette = NULL;


/*  public functions  */

void
image_new_cmd_callback (GimpAction *action,
                        GVariant   *value,
                        gpointer    data)
{
  GtkWidget *widget;
  GtkWidget *dialog;
  return_if_no_widget (widget, data);

  dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
                                           gimp_widget_get_monitor (widget),
                                           NULL /*ui_manager*/,
                                           widget,
                                           "gimp-image-new-dialog", -1, FALSE);

  if (dialog)
    {
      GimpImage *image = action_data_get_image (data);

      image_new_dialog_set (dialog, image, NULL);

      gtk_window_present (GTK_WINDOW (dialog));
    }
}

void
image_duplicate_cmd_callback (GimpAction *action,
                              GVariant   *value,
                              gpointer    data)
{
  GimpDisplay      *display;
  GimpImage        *image;
  GimpDisplayShell *shell;
  GimpImage        *new_image;
  return_if_no_display (display, data);

  image = gimp_display_get_image (display);
  shell = gimp_display_get_shell (display);

  new_image = gimp_image_duplicate (image);

  gimp_create_display (new_image->gimp, new_image, shell->unit,
                       gimp_zoom_model_get_factor (shell->zoom),
                       G_OBJECT (gimp_widget_get_monitor (GTK_WIDGET (shell))));

  g_object_unref (new_image);
}

void
image_convert_base_type_cmd_callback (GimpAction *action,
                                      GVariant   *value,
                                      gpointer    data)
{
  GimpImage         *image;
  GimpDisplay       *display;
  GtkWidget         *widget;
  GimpDialogConfig  *config;
  GtkWidget         *dialog;
  GimpImageBaseType  base_type;
  GError            *error = NULL;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

  base_type = (GimpImageBaseType) g_variant_get_int32 (value);

  if (base_type == gimp_image_get_base_type (image))
    return;

#define CONVERT_TYPE_DIALOG_KEY "gimp-convert-type-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_TYPE_DIALOG_KEY);

  if (dialog)
    {
      gtk_widget_destroy (dialog);
      dialog = NULL;
    }

  config = GIMP_DIALOG_CONFIG (image->gimp->config);

  switch (base_type)
    {
    case GIMP_RGB:
    case GIMP_GRAY:
      if (gimp_image_get_color_profile (image))
        {
          ColorProfileDialogType    dialog_type;
          GimpColorProfileCallback  callback;
          GimpColorProfile         *current_profile;
          GimpColorProfile         *default_profile;
          GimpTRCType               trc;

          current_profile =
            gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));

          trc = gimp_babl_trc (gimp_image_get_precision (image));

          if (base_type == GIMP_RGB)
            {
              dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_RGB;
              callback    = image_convert_rgb_callback;

              default_profile = gimp_babl_get_builtin_color_profile (GIMP_RGB,
                                                                     trc);
            }
          else
            {
              dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_GRAY;
              callback    = image_convert_gray_callback;

              default_profile = gimp_babl_get_builtin_color_profile (GIMP_GRAY,
                                                                     trc);
            }

          dialog = color_profile_dialog_new (dialog_type,
                                             image,
                                             action_data_get_context (data),
                                             widget,
                                             current_profile,
                                             default_profile,
                                             0, 0,
                                             callback,
                                             display);
        }
      else if (! gimp_image_convert_type (image, base_type, NULL, NULL, &error))
        {
          gimp_message_literal (image->gimp,
                                G_OBJECT (widget), GIMP_MESSAGE_WARNING,
                                error->message);
          g_clear_error (&error);
        }
      break;

    case GIMP_INDEXED:
      dialog = convert_indexed_dialog_new (image,
                                           action_data_get_context (data),
                                           widget,
                                           config->image_convert_indexed_palette_type,
                                           config->image_convert_indexed_max_colors,
                                           config->image_convert_indexed_remove_duplicates,
                                           config->image_convert_indexed_dither_type,
                                           config->image_convert_indexed_dither_alpha,
                                           config->image_convert_indexed_dither_text_layers,
                                           image_convert_indexed_custom_palette,
                                           image_convert_indexed_callback,
                                           display);
      break;
    }

  if (dialog)
    {
      dialogs_attach_dialog (G_OBJECT (image),
                             CONVERT_TYPE_DIALOG_KEY, dialog);
      gtk_window_present (GTK_WINDOW (dialog));
    }

  /*  always flush, also when only the indexed dialog was shown, so
   *  the menu items get updated back to the current image type
   */

  gimp_image_flush (image);
}

void
image_convert_precision_cmd_callback (GimpAction *action,
                                      GVariant   *value,
                                      gpointer    data)
{
  GimpImage         *image;
  GimpDisplay       *display;
  GtkWidget         *widget;
  GimpDialogConfig  *config;
  GtkWidget         *dialog;
  GimpComponentType  component_type;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

  component_type = (GimpComponentType) g_variant_get_int32 (value);

  if (component_type == gimp_image_get_component_type (image))
    return;

#define CONVERT_PRECISION_DIALOG_KEY "gimp-convert-precision-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_PRECISION_DIALOG_KEY);

  if (dialog)
    {
      gtk_widget_destroy (dialog);
      dialog = NULL;
    }

  config = GIMP_DIALOG_CONFIG (image->gimp->config);

  dialog = convert_precision_dialog_new (image,
                                         action_data_get_context (data),
                                         widget,
                                         component_type,
                                         config->image_convert_precision_layer_dither_method,
                                         config->image_convert_precision_text_layer_dither_method,
                                         config->image_convert_precision_channel_dither_method,
                                         image_convert_precision_callback,
                                         display);

  dialogs_attach_dialog (G_OBJECT (image),
                         CONVERT_PRECISION_DIALOG_KEY, dialog);

  gtk_window_present (GTK_WINDOW (dialog));

  /*  see comment above  */
  gimp_image_flush (image);
}

void
image_convert_trc_cmd_callback (GimpAction *action,
                                GVariant   *value,
                                gpointer    data)
{
  GimpImage     *image;
  GimpDisplay   *display;
  GimpTRCType    trc_type;
  GimpPrecision  precision;
  return_if_no_image (image, data);
  return_if_no_display (display, data);

  trc_type = (GimpTRCType) g_variant_get_int32 (value);

  if (trc_type == gimp_babl_format_get_trc (gimp_image_get_layer_format (image,
                                                                         FALSE)))
    return;

  precision = gimp_babl_precision (gimp_image_get_component_type (image),
                                   trc_type);

  gimp_image_convert_precision (image, precision,
                                GEGL_DITHER_NONE,
                                GEGL_DITHER_NONE,
                                GEGL_DITHER_NONE,
                                GIMP_PROGRESS (display));
  gimp_image_flush (image);
}

void
image_color_profile_use_srgb_cmd_callback (GimpAction *action,
                                           GVariant   *value,
                                           gpointer    data)
{
  GimpImage *image;
  gboolean   use_srgb;
  return_if_no_image (image, data);

  use_srgb = g_variant_get_boolean (value);

  if (use_srgb != gimp_image_get_use_srgb_profile (image, NULL))
    {
      gimp_image_set_use_srgb_profile (image, use_srgb);
      gimp_image_flush (image);
    }
}

void
image_color_profile_assign_cmd_callback (GimpAction *action,
                                         GVariant   *value,
                                         gpointer    data)
{
  GimpImage   *image;
  GimpDisplay *display;
  GtkWidget   *widget;
  GtkWidget   *dialog;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

#define PROFILE_ASSIGN_DIALOG_KEY "gimp-profile-assign-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_ASSIGN_DIALOG_KEY);

  if (! dialog)
    {
      GimpColorProfile *current_profile;
      GimpColorProfile *default_profile;

      current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
      default_profile = gimp_image_get_builtin_color_profile (image);

      dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_ASSIGN_PROFILE,
                                         image,
                                         action_data_get_context (data),
                                         widget,
                                         current_profile,
                                         default_profile,
                                         0, 0,
                                         image_profile_assign_callback,
                                         display);

      dialogs_attach_dialog (G_OBJECT (image),
                             PROFILE_ASSIGN_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_color_profile_convert_cmd_callback (GimpAction *action,
                                          GVariant   *value,
                                          gpointer    data)
{
  GimpImage   *image;
  GimpDisplay *display;
  GtkWidget   *widget;
  GtkWidget   *dialog;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

#define PROFILE_CONVERT_DIALOG_KEY "gimp-profile-convert-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_CONVERT_DIALOG_KEY);

  if (! dialog)
    {
      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
      GimpColorProfile *current_profile;
      GimpColorProfile *default_profile;

      current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
      default_profile = gimp_image_get_builtin_color_profile (image);

      dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_CONVERT_TO_PROFILE,
                                         image,
                                         action_data_get_context (data),
                                         widget,
                                         current_profile,
                                         default_profile,
                                         config->image_convert_profile_intent,
                                         config->image_convert_profile_bpc,
                                         image_profile_convert_callback,
                                         display);

      dialogs_attach_dialog (G_OBJECT (image),
                             PROFILE_CONVERT_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_color_profile_discard_cmd_callback (GimpAction *action,
                                          GVariant   *value,
                                          gpointer    data)
{
  GimpImage *image;
  return_if_no_image (image, data);

  gimp_image_assign_color_profile (image, NULL, NULL, NULL);
  gimp_image_flush (image);
}

static void
image_profile_save_dialog_response (GtkWidget *dialog,
                                    gint       response_id,
                                    GimpImage *image)
{
  if (response_id == GTK_RESPONSE_ACCEPT)
    {
      GimpColorProfile *profile;
      GFile            *file;
      GError           *error = NULL;

      profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
      file    = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));

      if (! file)
        return;

      if (! gimp_color_profile_save_to_file (profile, file, &error))
        {
          gimp_message (image->gimp, NULL,
                        GIMP_MESSAGE_WARNING,
                        _("Saving color profile failed: %s"),
                        error->message);
          g_clear_error (&error);
          g_object_unref (file);
          return;
        }

      g_object_unref (file);
    }

  gtk_widget_destroy (dialog);
}

void
image_color_profile_save_cmd_callback (GimpAction *action,
                                       GVariant   *value,
                                       gpointer    data)
{
  GimpImage   *image;
  GimpDisplay *display;
  GtkWidget   *widget;
  GtkWidget   *dialog;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

#define PROFILE_SAVE_DIALOG_KEY "gimp-profile-save-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY);

  if (! dialog)
    {
      GtkWindow        *toplevel;
      GimpColorProfile *profile;
      gchar            *basename;

      toplevel = GTK_WINDOW (gtk_widget_get_toplevel (widget));
      profile  = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));

      dialog =
        gimp_color_profile_chooser_dialog_new (_("Save Color Profile"),
                                               toplevel,
                                               GTK_FILE_CHOOSER_ACTION_SAVE);

      gimp_color_profile_chooser_dialog_connect_path (dialog,
                                                      G_OBJECT (image->gimp->config),
                                                      "color-profile-path");

      basename = g_strconcat (gimp_color_profile_get_label (profile),
                              ".icc", NULL);
      gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
      g_free (basename);

      g_signal_connect (dialog, "response",
                        G_CALLBACK (image_profile_save_dialog_response),
                        image);

      dialogs_attach_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_resize_cmd_callback (GimpAction *action,
                           GVariant   *value,
                           gpointer    data)
{
  GimpImage   *image;
  GtkWidget   *widget;
  GimpDisplay *display;
  GtkWidget   *dialog;
  return_if_no_image (image, data);
  return_if_no_widget (widget, data);
  return_if_no_display (display, data);

#define RESIZE_DIALOG_KEY "gimp-resize-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY);

  if (! dialog)
    {
      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);

      if (image_resize_unit != gimp_unit_percent ())
        image_resize_unit = gimp_display_get_shell (display)->unit;

      dialog = resize_dialog_new (GIMP_VIEWABLE (image),
                                  action_data_get_context (data),
                                  _("Set Image Canvas Size"),
                                  "gimp-image-resize",
                                  widget,
                                  gimp_standard_help_func,
                                  GIMP_HELP_IMAGE_RESIZE,
                                  image_resize_unit,
                                  config->image_resize_fill_type,
                                  config->image_resize_layer_set,
                                  config->image_resize_resize_text_layers,
                                  image_resize_callback,
                                  display);

      dialogs_attach_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_resize_to_layers_cmd_callback (GimpAction *action,
                                     GVariant   *value,
                                     gpointer    data)
{
  GimpDisplay  *display;
  GimpImage    *image;
  GimpProgress *progress;
  return_if_no_display (display, data);

  image = gimp_display_get_image (display);

  progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                  _("Resizing"));

  gimp_image_resize_to_layers (image,
                               action_data_get_context (data),
                               NULL, NULL, NULL, NULL, progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);
}

void
image_resize_to_selection_cmd_callback (GimpAction *action,
                                        GVariant   *value,
                                        gpointer    data)
{
  GimpDisplay  *display;
  GimpImage    *image;
  GimpProgress *progress;
  return_if_no_display (display, data);

  image = gimp_display_get_image (display);

  progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                  _("Resizing"));

  gimp_image_resize_to_selection (image,
                                  action_data_get_context (data),
                                  progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);
}

void
image_print_size_cmd_callback (GimpAction *action,
                               GVariant   *value,
                               gpointer    data)
{
  GimpDisplay *display;
  GimpImage   *image;
  GtkWidget   *widget;
  GtkWidget   *dialog;
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

  image = gimp_display_get_image (display);

#define PRINT_SIZE_DIALOG_KEY "gimp-print-size-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY);

  if (! dialog)
    {
      dialog = print_size_dialog_new (image,
                                      action_data_get_context (data),
                                      _("Set Image Print Resolution"),
                                      "gimp-image-print-size",
                                      widget,
                                      gimp_standard_help_func,
                                      GIMP_HELP_IMAGE_PRINT_SIZE,
                                      image_print_size_callback,
                                      NULL);

      dialogs_attach_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_scale_cmd_callback (GimpAction *action,
                          GVariant   *value,
                          gpointer    data)
{
  GimpDisplay *display;
  GimpImage   *image;
  GtkWidget   *widget;
  GtkWidget   *dialog;
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

  image = gimp_display_get_image (display);

#define SCALE_DIALOG_KEY "gimp-scale-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), SCALE_DIALOG_KEY);

  if (! dialog)
    {
      if (image_scale_unit != gimp_unit_percent ())
        image_scale_unit = gimp_display_get_shell (display)->unit;

      if (image_scale_interp == -1)
        image_scale_interp = display->gimp->config->interpolation_type;

      dialog = image_scale_dialog_new (image,
                                       action_data_get_context (data),
                                       widget,
                                       image_scale_unit,
                                       image_scale_interp,
                                       image_scale_callback,
                                       display);

      dialogs_attach_dialog (G_OBJECT (image), SCALE_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_flip_cmd_callback (GimpAction *action,
                         GVariant   *value,
                         gpointer    data)
{
  GimpDisplay         *display;
  GimpImage           *image;
  GimpProgress        *progress;
  GimpOrientationType  orientation;
  return_if_no_display (display, data);

  orientation = (GimpOrientationType) g_variant_get_int32 (value);

  image = gimp_display_get_image (display);

  progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                  _("Flipping"));

  gimp_image_flip (image, action_data_get_context (data),
                   orientation, progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);
}

void
image_rotate_cmd_callback (GimpAction *action,
                           GVariant   *value,
                           gpointer    data)
{
  GimpDisplay      *display;
  GimpImage        *image;
  GimpProgress     *progress;
  GimpRotationType  rotation;
  return_if_no_display (display, data);

  rotation = (GimpRotationType) g_variant_get_int32 (value);

  image = gimp_display_get_image (display);

  progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                  _("Rotating"));

  gimp_image_rotate (image, action_data_get_context (data),
                     rotation, progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);
}

void
image_crop_to_selection_cmd_callback (GimpAction *action,
                                      GVariant   *value,
                                      gpointer    data)
{
  GimpImage *image;
  GtkWidget *widget;
  gint       x, y;
  gint       width, height;
  return_if_no_image (image, data);
  return_if_no_widget (widget, data);

  if (! gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
                          &x, &y, &width, &height))
    {
      gimp_message_literal (image->gimp,
                            G_OBJECT (widget), GIMP_MESSAGE_WARNING,
                            _("Cannot crop because the current selection "
                              "is empty."));
      return;
    }

  gimp_image_crop (image,
                   action_data_get_context (data), GIMP_FILL_TRANSPARENT,
                   x, y, width, height, TRUE);
  gimp_image_flush (image);
}

void
image_crop_to_content_cmd_callback (GimpAction *action,
                                    GVariant   *value,
                                    gpointer    data)
{
  GimpImage *image;
  GtkWidget *widget;
  gint       x, y;
  gint       width, height;
  return_if_no_image (image, data);
  return_if_no_widget (widget, data);

  switch (gimp_pickable_auto_shrink (GIMP_PICKABLE (image),
                                     0, 0,
                                     gimp_image_get_width  (image),
                                     gimp_image_get_height (image),
                                     &x, &y, &width, &height))
    {
    case GIMP_AUTO_SHRINK_SHRINK:
      gimp_image_crop (image,
                       action_data_get_context (data), GIMP_FILL_TRANSPARENT,
                       x, y, width, height, TRUE);
      gimp_image_flush (image);
      break;

    case GIMP_AUTO_SHRINK_EMPTY:
      gimp_message_literal (image->gimp,
                            G_OBJECT (widget), GIMP_MESSAGE_INFO,
                            _("Cannot crop because the image has no content."));
      break;

    case GIMP_AUTO_SHRINK_UNSHRINKABLE:
      gimp_message_literal (image->gimp,
                            G_OBJECT (widget), GIMP_MESSAGE_INFO,
                            _("Cannot crop because the image is already "
                              "cropped to its content."));
      break;
    }
}

void
image_merge_layers_cmd_callback (GimpAction *action,
                                 GVariant   *value,
                                 gpointer    data)
{
  GtkWidget   *dialog;
  GimpImage   *image;
  GimpDisplay *display;
  GtkWidget   *widget;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

#define MERGE_LAYERS_DIALOG_KEY "gimp-merge-layers-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY);

  if (! dialog)
    {
      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);

      dialog = image_merge_layers_dialog_new (image,
                                              action_data_get_context (data),
                                              widget,
                                              config->layer_merge_type,
                                              config->layer_merge_active_group_only,
                                              config->layer_merge_discard_invisible,
                                              image_merge_layers_callback,
                                              display);

      dialogs_attach_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_merge_layers_last_vals_cmd_callback (GimpAction *action,
                                           GVariant   *value,
                                           gpointer    data)
{
  GimpImage        *image;
  GimpDisplay      *display;
  GimpDialogConfig *config;
  return_if_no_image (image, data);
  return_if_no_display (display, data);

  config = GIMP_DIALOG_CONFIG (image->gimp->config);

  image_merge_layers_callback (NULL,
                               image,
                               action_data_get_context (data),
                               config->layer_merge_type,
                               config->layer_merge_active_group_only,
                               config->layer_merge_discard_invisible,
                               display);
}

void
image_flatten_image_cmd_callback (GimpAction *action,
                                  GVariant   *value,
                                  gpointer    data)
{
  GimpImage   *image;
  GimpDisplay *display;
  GtkWidget   *widget;
  GError      *error = NULL;
  return_if_no_image (image, data);
  return_if_no_display (display, data);
  return_if_no_widget (widget, data);

  if (! gimp_image_flatten (image, action_data_get_context (data),
                            GIMP_PROGRESS (display), &error))
    {
      gimp_message_literal (image->gimp,
                            G_OBJECT (widget), GIMP_MESSAGE_WARNING,
                            error->message);
      g_clear_error (&error);
      return;
    }

  gimp_image_flush (image);
}

void
image_configure_grid_cmd_callback (GimpAction *action,
                                   GVariant   *value,
                                   gpointer    data)
{
  GimpDisplay *display;
  GimpImage   *image;
  GtkWidget   *dialog;
  return_if_no_display (display, data);

  image = gimp_display_get_image (display);

#define GRID_DIALOG_KEY "gimp-grid-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), GRID_DIALOG_KEY);

  if (! dialog)
    {
      GimpDisplayShell *shell = gimp_display_get_shell (display);

      dialog = grid_dialog_new (image,
                                action_data_get_context (data),
                                gtk_widget_get_toplevel (GTK_WIDGET (shell)));

      dialogs_attach_dialog (G_OBJECT (image), GRID_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

void
image_properties_cmd_callback (GimpAction *action,
                               GVariant   *value,
                               gpointer    data)
{
  GimpDisplay *display;
  GimpImage   *image;
  GtkWidget   *dialog;
  return_if_no_display (display, data);

  image = gimp_display_get_image (display);

#define PROPERTIES_DIALOG_KEY "gimp-image-properties-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY);

  if (! dialog)
    {
      GimpDisplayShell *shell = gimp_display_get_shell (display);

      dialog = image_properties_dialog_new (image,
                                            action_data_get_context (data),
                                            gtk_widget_get_toplevel (GTK_WIDGET (shell)));

      dialogs_attach_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}


/*  private functions  */

static void
image_convert_rgb_callback (GtkWidget                *dialog,
                            GimpImage                *image,
                            GimpColorProfile         *new_profile,
                            GFile                    *new_file,
                            GimpColorRenderingIntent  intent,
                            gboolean                  bpc,
                            gpointer                  user_data)
{
  GimpProgress *progress = user_data;
  GError       *error    = NULL;

  progress = gimp_progress_start (progress, FALSE,
                                  _("Converting to RGB (%s)"),
                                  gimp_color_profile_get_label (new_profile));

  if (! gimp_image_convert_type (image, GIMP_RGB, new_profile,
                                 progress, &error))
    {
      gimp_message (image->gimp, G_OBJECT (dialog),
                    GIMP_MESSAGE_ERROR,
                    "%s", error->message);
      g_clear_error (&error);

      if (progress)
        gimp_progress_end (progress);

      return;
    }

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);

 gtk_widget_destroy (dialog);
}

static void
image_convert_gray_callback (GtkWidget                *dialog,
                             GimpImage                *image,
                             GimpColorProfile         *new_profile,
                             GFile                    *new_file,
                             GimpColorRenderingIntent  intent,
                             gboolean                  bpc,
                             gpointer                  user_data)
{
  GimpProgress *progress = user_data;
  GError       *error    = NULL;

  progress = gimp_progress_start (progress, FALSE,
                                  _("Converting to grayscale (%s)"),
                                  gimp_color_profile_get_label (new_profile));

  if (! gimp_image_convert_type (image, GIMP_GRAY, new_profile,
                                 progress, &error))
    {
      gimp_message (image->gimp, G_OBJECT (dialog),
                    GIMP_MESSAGE_ERROR,
                    "%s", error->message);
      g_clear_error (&error);

      if (progress)
        gimp_progress_end (progress);

      return;
    }

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);

  gtk_widget_destroy (dialog);
}

static void
image_convert_indexed_callback (GtkWidget              *dialog,
                                GimpImage              *image,
                                GimpConvertPaletteType  palette_type,
                                gint                    max_colors,
                                gboolean                remove_duplicates,
                                GimpConvertDitherType   dither_type,
                                gboolean                dither_alpha,
                                gboolean                dither_text_layers,
                                GimpPalette            *custom_palette,
                                gpointer                user_data)
{
  GimpDialogConfig *config  = GIMP_DIALOG_CONFIG (image->gimp->config);
  GimpDisplay      *display = user_data;
  GimpProgress     *progress;
  GError           *error   = NULL;

  g_object_set (config,
                "image-convert-indexed-palette-type",       palette_type,
                "image-convert-indexed-max-colors",         max_colors,
                "image-convert-indexed-remove-duplicates",  remove_duplicates,
                "image-convert-indexed-dither-type",        dither_type,
                "image-convert-indexed-dither-alpha",       dither_alpha,
                "image-convert-indexed-dither-text-layers", dither_text_layers,
                NULL);

  g_set_weak_pointer (&image_convert_indexed_custom_palette, custom_palette);

  progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                  _("Converting to indexed colors"));

  if (! gimp_image_convert_indexed (image,
                                    config->image_convert_indexed_palette_type,
                                    config->image_convert_indexed_max_colors,
                                    config->image_convert_indexed_remove_duplicates,
                                    config->image_convert_indexed_dither_type,
                                    config->image_convert_indexed_dither_alpha,
                                    config->image_convert_indexed_dither_text_layers,
                                    image_convert_indexed_custom_palette,
                                    progress,
                                    &error))
    {
      gimp_message_literal (image->gimp, G_OBJECT (display),
                            GIMP_MESSAGE_WARNING, error->message);
      g_clear_error (&error);

      if (progress)
        gimp_progress_end (progress);

      return;
    }

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);

  gtk_widget_destroy (dialog);
}

static void
image_convert_precision_callback (GtkWidget        *dialog,
                                  GimpImage        *image,
                                  GimpPrecision     precision,
                                  GeglDitherMethod  layer_dither_method,
                                  GeglDitherMethod  text_layer_dither_method,
                                  GeglDitherMethod  channel_dither_method,
                                  gpointer          user_data)
{
  GimpDialogConfig *config   = GIMP_DIALOG_CONFIG (image->gimp->config);
  GimpProgress     *progress = user_data;
  const gchar      *enum_desc;
  const Babl       *old_format;
  const Babl       *new_format;
  gint              old_bits;
  gint              new_bits;

  g_object_set (config,
                "image-convert-precision-layer-dither-method",
                layer_dither_method,
                "image-convert-precision-text-layer-dither-method",
                text_layer_dither_method,
                "image-convert-precision-channel-dither-method",
                channel_dither_method,
                NULL);

  /*  we do the same dither method checks here *and* in the dialog,
   *  because the dialog leaves the passed dither methods untouched if
   *  dithering is disabled and passes the original values to the
   *  callback, in order not to change the values saved in
   *  GimpDialogConfig.
   */


  /* random formats with the right precision */
  old_format = gimp_image_get_layer_format (image, FALSE);
  new_format = gimp_babl_format (GIMP_RGB, precision, FALSE, NULL);

  old_bits = (babl_format_get_bytes_per_pixel (old_format) * 8 /
              babl_format_get_n_components (old_format));
  new_bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
              babl_format_get_n_components (new_format));

  if (new_bits >= old_bits ||
      new_bits >  CONVERT_PRECISION_DIALOG_MAX_DITHER_BITS)
    {
      /*  don't dither if we are converting to a higher bit depth,
       *  or to more than MAX_DITHER_BITS.
       */

      layer_dither_method      = GEGL_DITHER_NONE;
      text_layer_dither_method = GEGL_DITHER_NONE;
      channel_dither_method    = GEGL_DITHER_NONE;
    }

  gimp_enum_get_value (GIMP_TYPE_PRECISION, precision,
                       NULL, NULL, &enum_desc, NULL);

  progress = gimp_progress_start (progress, FALSE,
                                  _("Converting image to %s"),
                                  enum_desc);

  gimp_image_convert_precision (image,
                                precision,
                                layer_dither_method,
                                text_layer_dither_method,
                                channel_dither_method,
                                progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);

  gtk_widget_destroy (dialog);
}

static void
image_profile_assign_callback (GtkWidget                *dialog,
                               GimpImage                *image,
                               GimpColorProfile         *new_profile,
                               GFile                    *new_file,
                               GimpColorRenderingIntent  intent,
                               gboolean                  bpc,
                               gpointer                  user_data)
{
  GError *error = NULL;

  if (! gimp_image_assign_color_profile (image, new_profile, NULL, &error))
    {
      gimp_message (image->gimp, G_OBJECT (dialog),
                    GIMP_MESSAGE_ERROR,
                    "%s", error->message);
      g_clear_error (&error);

      return;
    }

  gimp_image_flush (image);

  gtk_widget_destroy (dialog);
}

static void
image_profile_convert_callback (GtkWidget                *dialog,
                                GimpImage                *image,
                                GimpColorProfile         *new_profile,
                                GFile                    *new_file,
                                GimpColorRenderingIntent  intent,
                                gboolean                  bpc,
                                gpointer                  user_data)
{
  GimpDialogConfig *config   = GIMP_DIALOG_CONFIG (image->gimp->config);
  GimpProgress     *progress = user_data;
  GError           *error    = NULL;

  g_object_set (config,
                "image-convert-profile-intent",                   intent,
                "image-convert-profile-black-point-compensation", bpc,
                NULL);

  progress = gimp_progress_start (progress, FALSE,
                                  _("Converting to '%s'"),
                                  gimp_color_profile_get_label (new_profile));

  if (! gimp_image_convert_color_profile (image, new_profile,
                                          config->image_convert_profile_intent,
                                          config->image_convert_profile_bpc,
                                          progress, &error))
    {
      gimp_message (image->gimp, G_OBJECT (dialog),
                    GIMP_MESSAGE_ERROR,
                    "%s", error->message);
      g_clear_error (&error);

      if (progress)
        gimp_progress_end (progress);

      return;
    }

  if (progress)
    gimp_progress_end (progress);

  gimp_image_flush (image);

  gtk_widget_destroy (dialog);
}

static void
image_resize_callback (GtkWidget    *dialog,
                       GimpViewable *viewable,
                       GimpContext  *context,
                       gint          width,
                       gint          height,
                       GimpUnit     *unit,
                       gint          offset_x,
                       gint          offset_y,
                       gdouble       xres,
                       gdouble       yres,
                       GimpUnit     *res_unit,
                       GimpFillType  fill_type,
                       GimpItemSet   layer_set,
                       gboolean      resize_text_layers,
                       gpointer      user_data)
{
  GimpDisplay *display = user_data;

  image_resize_unit = unit;

  if (width > 0 && height > 0)
    {
      GimpImage        *image  = GIMP_IMAGE (viewable);
      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
      GimpProgress     *progress;
      gdouble           old_xres;
      gdouble           old_yres;
      GimpUnit         *old_res_unit;
      gboolean          update_resolution;

      g_object_set (config,
                    "image-resize-fill-type",          fill_type,
                    "image-resize-layer-set",          layer_set,
                    "image-resize-resize-text-layers", resize_text_layers,
                    NULL);

      gtk_widget_destroy (dialog);

      if (width  == gimp_image_get_width  (image) &&
          height == gimp_image_get_height (image))
        return;

      progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                      _("Resizing"));

      gimp_image_get_resolution (image, &old_xres, &old_yres);
      old_res_unit = gimp_image_get_unit (image);

      update_resolution = xres     != old_xres ||
                          yres     != old_yres ||
                          res_unit != old_res_unit;

      if (update_resolution)
        {
          gimp_image_undo_group_start (image,
                                       GIMP_UNDO_GROUP_IMAGE_SCALE,
                                       _("Change Canvas Size"));
          gimp_image_set_resolution (image, xres, yres);
          gimp_image_set_unit (image, res_unit);
        }

      gimp_image_resize_with_layers (image,
                                     context, fill_type,
                                     width, height,
                                     offset_x, offset_y,
                                     layer_set,
                                     resize_text_layers,
                                     progress);

      if (progress)
        gimp_progress_end (progress);

      if (update_resolution)
        gimp_image_undo_group_end (image);

      gimp_image_flush (image);
    }
  else
    {
      g_warning ("Resize Error: "
                 "Both width and height must be greater than zero.");
    }
}

static void
image_print_size_callback (GtkWidget *dialog,
                           GimpImage *image,
                           gdouble    xresolution,
                           gdouble    yresolution,
                           GimpUnit  *resolution_unit,
                           gpointer   data)
{
  gdouble xres;
  gdouble yres;

  gtk_widget_destroy (dialog);

  gimp_image_get_resolution (image, &xres, &yres);

  if (xresolution     == xres &&
      yresolution     == yres &&
      resolution_unit == gimp_image_get_unit (image))
    return;

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
                               _("Change Print Size"));

  gimp_image_set_resolution (image, xresolution, yresolution);
  gimp_image_set_unit (image, resolution_unit);

  gimp_image_undo_group_end (image);

  gimp_image_flush (image);
}

static void
image_scale_callback (GtkWidget              *dialog,
                      GimpViewable           *viewable,
                      gint                    width,
                      gint                    height,
                      GimpUnit               *unit,
                      GimpInterpolationType   interpolation,
                      gdouble                 xresolution,
                      gdouble                 yresolution,
                      GimpUnit               *resolution_unit,
                      gpointer                user_data)
{
  GimpProgress *progress = user_data;
  GimpImage    *image    = GIMP_IMAGE (viewable);
  gdouble       xres;
  gdouble       yres;

  image_scale_unit   = unit;
  image_scale_interp = interpolation;

  gimp_image_get_resolution (image, &xres, &yres);

  if (width > 0 && height > 0)
    {
      gtk_widget_destroy (dialog);

      if (width           == gimp_image_get_width  (image) &&
          height          == gimp_image_get_height (image) &&
          xresolution     == xres                          &&
          yresolution     == yres                          &&
          resolution_unit == gimp_image_get_unit (image))
        return;

      gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
                                   _("Scale Image"));

      gimp_image_set_resolution (image, xresolution, yresolution);
      gimp_image_set_unit (image, resolution_unit);

      if (width  != gimp_image_get_width  (image) ||
          height != gimp_image_get_height (image))
        {
          progress = gimp_progress_start (progress, FALSE,
                                          _("Scaling"));

          gimp_image_scale (image, width, height, interpolation, progress);

          if (progress)
            gimp_progress_end (progress);
        }

      gimp_image_undo_group_end (image);

      gimp_image_flush (image);
    }
  else
    {
      g_warning ("Scale Error: "
                 "Both width and height must be greater than zero.");
    }
}

static void
image_merge_layers_callback (GtkWidget     *dialog,
                             GimpImage     *image,
                             GimpContext   *context,
                             GimpMergeType  merge_type,
                             gboolean       merge_active_group,
                             gboolean       discard_invisible,
                             gpointer       user_data)
{
  GimpDialogConfig *config  = GIMP_DIALOG_CONFIG (image->gimp->config);
  GimpDisplay      *display = user_data;

  g_object_set (config,
                "layer-merge-type",              merge_type,
                "layer-merge-active-group-only", merge_active_group,
                "layer-merge-discard-invisible", discard_invisible,
                NULL);

  gimp_image_merge_visible_layers (image,
                                   context,
                                   config->layer_merge_type,
                                   config->layer_merge_active_group_only,
                                   config->layer_merge_discard_invisible,
                                   GIMP_PROGRESS (display));

  gimp_image_flush (image);

  g_clear_pointer (&dialog, gtk_widget_destroy);
}

void
image_softproof_profile_cmd_callback (GimpAction *action,
                                      GVariant   *value,
                                      gpointer    data)
{
  GimpImage        *image;
  GimpDisplayShell *shell;
  GtkWidget        *dialog;
  return_if_no_image (image, data);
  return_if_no_shell (shell, data);

#define SOFTPROOF_PROFILE_DIALOG_KEY "gimp-softproof-profile-dialog"

  dialog = dialogs_get_dialog (G_OBJECT (shell), SOFTPROOF_PROFILE_DIALOG_KEY);

  if (! dialog)
    {
      GimpColorProfile *current_profile;

      current_profile = gimp_image_get_simulation_profile (image);

      dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_SELECT_SOFTPROOF_PROFILE,
                                         image,
                                         action_data_get_context (data),
                                         GTK_WIDGET (shell),
                                         current_profile,
                                         NULL,
                                         0, 0,
                                         image_softproof_profile_callback,
                                         shell);

      dialogs_attach_dialog (G_OBJECT (shell),
                             SOFTPROOF_PROFILE_DIALOG_KEY, dialog);
    }

  gtk_window_present (GTK_WINDOW (dialog));
}

static void
image_softproof_profile_callback (GtkWidget                *dialog,
                                  GimpImage                *image,
                                  GimpColorProfile         *new_profile,
                                  GFile                    *new_file,
                                  GimpColorRenderingIntent  intent,
                                  gboolean                  bpc,
                                  gpointer                  user_data)
{
  GimpDisplayShell *shell = user_data;

  /* Update image's simulation profile */
  gimp_image_set_simulation_profile (image, new_profile);
  gimp_color_managed_simulation_profile_changed (GIMP_COLOR_MANAGED (shell));

  gtk_widget_destroy (dialog);
}

void
image_softproof_intent_cmd_callback (GimpAction *action,
                                     GVariant   *value,
                                     gpointer    data)
{
  GimpImage                 *image;
  GimpDisplayShell          *shell;
  GimpColorRenderingIntent   intent;
  return_if_no_image (image, data);
  return_if_no_shell (shell, data);

  intent = (GimpColorRenderingIntent) g_variant_get_int32 (value);

  if (intent != gimp_image_get_simulation_intent (image))
    {
      gimp_image_set_simulation_intent (image, intent);
      shell->color_config_set = TRUE;
      gimp_color_managed_simulation_intent_changed (GIMP_COLOR_MANAGED (shell));
    }
}

void
image_softproof_bpc_cmd_callback (GimpAction *action,
                                  GVariant   *value,
                                  gpointer    data)
{
  GimpImage                 *image;
  GimpDisplayShell          *shell;
  gboolean                   bpc;
  return_if_no_image (image, data);
  return_if_no_shell (shell, data);

  bpc = g_variant_get_boolean (value);

  if (bpc != gimp_image_get_simulation_bpc (image))
    {
      gimp_image_set_simulation_bpc (image, bpc);
      shell->color_config_set = TRUE;
      gimp_color_managed_simulation_bpc_changed (GIMP_COLOR_MANAGED (shell));
    }
}

Messung
CHZG
801009692

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-11-03) ¤

*© 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.