diff --git a/app/actions/image-actions.c b/app/actions/image-actions.c index cdfdef7d4b..7ef19056e9 100644 --- a/app/actions/image-actions.c +++ b/app/actions/image-actions.c @@ -20,6 +20,7 @@ #include #include +#include "libgimpconfig/gimpconfig.h" #include "libgimpwidgets/gimpwidgets.h" #include "actions-types.h" @@ -35,6 +36,9 @@ #include "core/gimpimage-color-profile.h" #include "core/gimpitemstack.h" +#include "display/gimpdisplay.h" +#include "display/gimpdisplayshell.h" + #include "widgets/gimpactiongroup.h" #include "widgets/gimphelp-ids.h" @@ -102,12 +106,21 @@ static const GimpActionEntry image_actions[] = image_color_profile_discard_cmd_callback, GIMP_HELP_IMAGE_COLOR_PROFILE_DISCARD }, + { "image-softproof-profile", NULL, + NC_("image-action", "_Softproof Profile..."), NULL, + NC_("image-action", "Set the softproofing profile"), + image_softproof_profile_cmd_callback, + GIMP_HELP_VIEW_COLOR_MANAGEMENT }, + { "image-color-profile-save", NULL, NC_("image-action", "_Save Color Profile to File..."), NULL, NC_("image-action", "Save the image's color profile to an ICC file"), image_color_profile_save_cmd_callback, GIMP_HELP_IMAGE_COLOR_PROFILE_SAVE }, + { "image-softproof-intent-menu", NULL, + NC_("image-action", "Soft-Proofing Re_ndering Intent") }, + { "image-resize", GIMP_ICON_OBJECT_RESIZE, NC_("image-action", "Can_vas Size..."), NULL, NC_("image-action", "Adjust the image dimensions"), @@ -184,7 +197,14 @@ static const GimpToggleActionEntry image_toggle_actions[] = "allows to easily restore the profile."), image_color_profile_use_srgb_cmd_callback, TRUE, - GIMP_HELP_IMAGE_COLOR_PROFILE_USE_SRGB } + GIMP_HELP_IMAGE_COLOR_PROFILE_USE_SRGB }, + + { "image-softproof-black-point-compensation", NULL, + NC_("image-action", "_Black Point Compensation"), NULL, + NC_("image-action", "Use black point compensation for soft-proofing"), + image_softproof_bpc_cmd_callback, + TRUE, + GIMP_HELP_VIEW_COLOR_MANAGEMENT } }; static const GimpRadioActionEntry image_convert_base_type_actions[] = @@ -301,6 +321,33 @@ static const GimpEnumActionEntry image_rotate_actions[] = GIMP_HELP_IMAGE_ROTATE_270 } }; +static const GimpRadioActionEntry image_softproof_intent_actions[] = +{ + { "image-softproof-intent-perceptual", NULL, + NC_("image-action", "_Perceptual"), NULL, + NC_("image-action", "Soft-proofing rendering intent is perceptual"), + GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, + GIMP_HELP_VIEW_COLOR_MANAGEMENT }, + + { "image-softproof-intent-relative-colorimetric", NULL, + NC_("image-action", "_Relative Colorimetric"), NULL, + NC_("image-action", "Soft-proofing rendering intent is relative colorimetric"), + GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, + GIMP_HELP_VIEW_COLOR_MANAGEMENT }, + + { "image-softproof-intent-saturation", NULL, + NC_("image-action", "_Saturation"), NULL, + NC_("image-action", "Soft-proofing rendering intent is saturation"), + GIMP_COLOR_RENDERING_INTENT_SATURATION, + GIMP_HELP_VIEW_COLOR_MANAGEMENT }, + + { "image-softproof-intent-absolute-colorimetric", NULL, + NC_("image-action", "_Absolute Colorimetric"), NULL, + NC_("image-action", "Soft-proofing rendering intent is absolute colorimetric"), + GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC, + GIMP_HELP_VIEW_COLOR_MANAGEMENT } +}; + void image_actions_setup (GimpActionGroup *group) @@ -313,6 +360,13 @@ image_actions_setup (GimpActionGroup *group) image_toggle_actions, G_N_ELEMENTS (image_toggle_actions)); + gimp_action_group_add_radio_actions (group, "image-action", + image_softproof_intent_actions, + G_N_ELEMENTS (image_softproof_intent_actions), + NULL, + GIMP_COLOR_MANAGEMENT_DISPLAY, + image_softproof_intent_cmd_callback); + gimp_action_group_add_radio_actions (group, "image-convert-action", image_convert_base_type_actions, G_N_ELEMENTS (image_convert_base_type_actions), @@ -355,17 +409,21 @@ void image_actions_update (GimpActionGroup *group, gpointer data) { - GimpImage *image = action_data_get_image (data); - gboolean is_indexed = FALSE; - gboolean is_u8_gamma = FALSE; - gboolean is_double = FALSE; - gboolean aux = FALSE; - gboolean lp = FALSE; - gboolean sel = FALSE; - gboolean groups = FALSE; - gboolean profile_srgb = FALSE; - gboolean profile_hidden = FALSE; - gboolean profile = FALSE; + GimpImage *image = action_data_get_image (data); + GimpDisplay *display = action_data_get_display (data); + GimpDisplayShell *shell = NULL; + GimpColorConfig *color_config = NULL; + gboolean is_indexed = FALSE; + gboolean is_u8_gamma = FALSE; + gboolean is_double = FALSE; + gboolean aux = FALSE; + gboolean lp = FALSE; + gboolean sel = FALSE; + gboolean groups = FALSE; + gboolean profile_srgb = FALSE; + gboolean profile_hidden = FALSE; + gboolean profile = FALSE; + gboolean s_bpc = FALSE; #define SET_LABEL(action,label) \ gimp_action_group_set_action_label (group, action, (label)) @@ -445,6 +503,35 @@ image_actions_update (GimpActionGroup *group, profile_srgb = gimp_image_get_use_srgb_profile (image, &profile_hidden); profile = (gimp_image_get_color_profile (image) != NULL); + + if (display) + { + shell = gimp_display_get_shell (display); + color_config = gimp_display_shell_get_color_config (shell); + + switch (gimp_color_config_get_simulation_intent (color_config)) + { + case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL: + action = "image-softproof-intent-perceptual"; + break; + + case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC: + action = "image-softproof-intent-relative-colorimetric"; + break; + + case GIMP_COLOR_RENDERING_INTENT_SATURATION: + action = "image-softproof-intent-saturation"; + break; + + case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: + action = "image-softproof-intent-absolute-colorimetric"; + break; + } + + gimp_action_group_set_action_active (group, action, TRUE); + + s_bpc = gimp_color_config_get_simulation_bpc (color_config); + } } else { @@ -472,6 +559,14 @@ image_actions_update (GimpActionGroup *group, SET_SENSITIVE ("image-convert-grayscale", image); SET_SENSITIVE ("image-convert-indexed", image && !groups && is_u8_gamma); + SET_SENSITIVE ("image-softproof-profile", image); + SET_SENSITIVE ("image-softproof-intent-perceptual", image); + SET_SENSITIVE ("image-softproof-intent-relative-colorimetric", image); + SET_SENSITIVE ("image-softproof-intent-saturation", image); + SET_SENSITIVE ("image-softproof-intent-absolute-colorimetric", image); + SET_SENSITIVE ("image-softproof-black-point-compensation", image); + SET_ACTIVE ("image-softproof-black-point-compensation", s_bpc); + SET_SENSITIVE ("image-convert-u8", image); SET_SENSITIVE ("image-convert-u16", image && !is_indexed); SET_SENSITIVE ("image-convert-u32", image && !is_indexed); diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c index 323cc60158..7857c2f3a1 100644 --- a/app/actions/image-commands.c +++ b/app/actions/image-commands.c @@ -22,6 +22,7 @@ #include "libgimpbase/gimpbase.h" #include "libgimpcolor/gimpcolor.h" +#include "libgimpconfig/gimpconfig.h" #include "libgimpwidgets/gimpwidgets.h" #include "actions-types.h" @@ -172,6 +173,15 @@ static void image_merge_layers_callback (GtkWidget *dialog, 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 */ @@ -1563,3 +1573,105 @@ image_merge_layers_callback (GtkWidget *dialog, 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) +{ + GimpDisplayShell *shell; + GimpColorConfig *color_config; + GimpColorRenderingIntent intent; + return_if_no_shell (shell, data); + + intent = (GimpColorRenderingIntent) g_variant_get_int32 (value); + + color_config = gimp_display_shell_get_color_config (shell); + + if (intent != gimp_color_config_get_simulation_intent (color_config)) + { + g_object_set (color_config, + "simulation-rendering-intent", intent, + NULL); + shell->color_config_set = TRUE; + } +} + +void +image_softproof_bpc_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplayShell *shell; + GimpColorConfig *color_config; + gboolean active; + return_if_no_shell (shell, data); + + color_config = gimp_display_shell_get_color_config (shell); + + active = g_variant_get_boolean (value); + + if (active != gimp_color_config_get_simulation_bpc (color_config)) + { + g_object_set (color_config, + "simulation-use-black-point-compensation", active, + NULL); + shell->color_config_set = TRUE; + } +} diff --git a/app/actions/image-commands.h b/app/actions/image-commands.h index 964ffb2ec5..0cc6f5abc7 100644 --- a/app/actions/image-commands.h +++ b/app/actions/image-commands.h @@ -97,5 +97,14 @@ void image_properties_cmd_callback (GimpAction *action, GVariant *value, gpointer data); +void image_softproof_profile_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_softproof_intent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_softproof_bpc_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __IMAGE_COMMANDS_H__ */ diff --git a/app/actions/view-actions.c b/app/actions/view-actions.c index 3943eec056..e738ca90b5 100644 --- a/app/actions/view-actions.c +++ b/app/actions/view-actions.c @@ -77,9 +77,6 @@ static const GimpActionEntry view_actions[] = { "view-display-intent-menu", NULL, NC_("view-action", "Display _Rendering Intent") }, - { "view-softproof-intent-menu", NULL, - NC_("view-action", "Soft-Proofing Re_ndering Intent") }, - { "view-move-to-screen-menu", GIMP_ICON_WINDOW_MOVE_TO_SCREEN, NC_("view-action", "Move to Screen"), NULL, NULL, NULL, GIMP_HELP_VIEW_CHANGE_SCREEN }, @@ -165,12 +162,6 @@ static const GimpActionEntry view_actions[] = view_color_management_reset_cmd_callback, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - { "view-softproof-profile", NULL, - NC_("view-action", "Soft-_Proofing Profile..."), NULL, - NC_("view-action", "Set the soft-proofing profile"), - view_softproof_profile_cmd_callback, - GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - { "view-shrink-wrap", GIMP_ICON_ZOOM_FIT_BEST, NC_("view-action", "Shrink _Wrap"), "J", NC_("view-action", "Reduce the image window to the size of the image display"), @@ -222,13 +213,6 @@ static const GimpToggleActionEntry view_toggle_actions[] = TRUE, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - { "view-softproof-black-point-compensation", NULL, - NC_("view-action", "_Black Point Compensation"), NULL, - NC_("view-action", "Use black point compensation for soft-proofing"), - view_softproof_bpc_cmd_callback, - TRUE, - GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - { "view-softproof-gamut-check", NULL, NC_("view-action", "_Mark Out Of Gamut Colors"), NULL, NC_("view-action", "When soft-proofing, mark colors which cannot " @@ -580,33 +564,6 @@ static const GimpRadioActionEntry view_display_intent_actions[] = GIMP_HELP_VIEW_COLOR_MANAGEMENT } }; -static const GimpRadioActionEntry view_softproof_intent_actions[] = -{ - { "view-softproof-intent-perceptual", NULL, - NC_("view-action", "_Perceptual"), NULL, - NC_("view-action", "Soft-proofing rendering intent is perceptual"), - GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, - GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - - { "view-softproof-intent-relative-colorimetric", NULL, - NC_("view-action", "_Relative Colorimetric"), NULL, - NC_("view-action", "Soft-proofing rendering intent is relative colorimetric"), - GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, - GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - - { "view-softproof-intent-saturation", NULL, - NC_("view-action", "_Saturation"), NULL, - NC_("view-action", "Soft-proofing rendering intent is saturation"), - GIMP_COLOR_RENDERING_INTENT_SATURATION, - GIMP_HELP_VIEW_COLOR_MANAGEMENT }, - - { "view-softproof-intent-absolute-colorimetric", NULL, - NC_("view-action", "_Absolute Colorimetric"), NULL, - NC_("view-action", "Soft-proofing rendering intent is absolute colorimetric"), - GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC, - GIMP_HELP_VIEW_COLOR_MANAGEMENT } -}; - static const GimpEnumActionEntry view_padding_color_actions[] = { { "view-padding-color-theme", NULL, @@ -775,13 +732,6 @@ view_actions_setup (GimpActionGroup *group) GIMP_COLOR_MANAGEMENT_DISPLAY, view_display_intent_cmd_callback); - gimp_action_group_add_radio_actions (group, "view-action", - view_softproof_intent_actions, - G_N_ELEMENTS (view_softproof_intent_actions), - NULL, - GIMP_COLOR_MANAGEMENT_DISPLAY, - view_softproof_intent_cmd_callback); - gimp_action_group_add_enum_actions (group, "view-padding-color", view_padding_color_actions, G_N_ELEMENTS (view_padding_color_actions), @@ -813,12 +763,6 @@ view_actions_setup (GimpActionGroup *group) g_signal_connect_object (group->gimp->config, "notify::check-type", G_CALLBACK (view_actions_check_type_notify), group, 0); - g_signal_connect_object (group->gimp->config, "notify::check-custom-color1", - G_CALLBACK (view_actions_check_type_notify), - group, 0); - g_signal_connect_object (group->gimp->config, "notify::check-custom-color2", - G_CALLBACK (view_actions_check_type_notify), - group, 0); view_actions_check_type_notify (GIMP_DISPLAY_CONFIG (group->gimp->config), NULL, group); @@ -851,8 +795,7 @@ view_actions_update (GimpActionGroup *group, gboolean cm = FALSE; gboolean sp = FALSE; gboolean d_bpc = FALSE; - gboolean s_bpc = FALSE; - gboolean gammut = FALSE; + gboolean gamut = FALSE; if (display) { @@ -913,30 +856,8 @@ view_actions_update (GimpActionGroup *group, gimp_action_group_set_action_active (group, action, TRUE); - switch (gimp_color_config_get_simulation_intent (color_config)) - { - case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL: - action = "view-softproof-intent-perceptual"; - break; - - case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC: - action = "view-softproof-intent-relative-colorimetric"; - break; - - case GIMP_COLOR_RENDERING_INTENT_SATURATION: - action = "view-softproof-intent-saturation"; - break; - - case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: - action = "view-softproof-intent-absolute-colorimetric"; - break; - } - - gimp_action_group_set_action_active (group, action, TRUE); - d_bpc = gimp_color_config_get_display_bpc (color_config); - s_bpc = gimp_color_config_get_simulation_bpc (color_config); - gammut = gimp_color_config_get_simulation_gamut_check (color_config); + gamut = gimp_color_config_get_simulation_gamut_check (color_config); } #define SET_ACTIVE(action,condition) \ @@ -1038,15 +959,7 @@ view_actions_update (GimpActionGroup *group, SET_SENSITIVE ("view-display-intent-absolute-colorimetric", cm); SET_SENSITIVE ("view-display-black-point-compensation", cm); SET_ACTIVE ("view-display-black-point-compensation", d_bpc); - SET_SENSITIVE ("view-softproof-profile", sp); - SET_SENSITIVE ("view-softproof-intent-perceptual", sp); - SET_SENSITIVE ("view-softproof-intent-relative-colorimetric", sp); - SET_SENSITIVE ("view-softproof-intent-saturation", sp); - SET_SENSITIVE ("view-softproof-intent-absolute-colorimetric", sp); - SET_SENSITIVE ("view-softproof-black-point-compensation", sp); - SET_ACTIVE ("view-softproof-black-point-compensation", s_bpc); - SET_SENSITIVE ("view-softproof-gamut-check", sp); - SET_ACTIVE ("view-softproof-gamut-check", gammut); + SET_ACTIVE ("view-softproof-gamut-check", gamut); SET_SENSITIVE ("view-color-management-reset", image); SET_SENSITIVE ("view-show-selection", image); diff --git a/app/actions/view-commands.c b/app/actions/view-commands.c index 0f6fdc0b7e..ecb0f4a129 100644 --- a/app/actions/view-commands.c +++ b/app/actions/view-commands.c @@ -76,13 +76,6 @@ /* local function prototypes */ -static void view_softproof_profile_callback (GtkWidget *dialog, - GimpImage *image, - GimpColorProfile *new_profile, - GFile *new_file, - GimpColorRenderingIntent intent, - gboolean bpc, - gpointer user_data); static void view_padding_color_dialog_update (GimpColorDialog *dialog, const GimpRGB *color, GimpColorDialogState state, @@ -737,94 +730,6 @@ view_display_bpc_cmd_callback (GimpAction *action, } } -void -view_softproof_profile_cmd_callback (GimpAction *action, - GVariant *value, - gpointer data) -{ - GimpImage *image; - GimpDisplayShell *shell; - GimpColorConfig *color_config; - GtkWidget *dialog; - return_if_no_image (image, data); - return_if_no_shell (shell, data); - - color_config = gimp_display_shell_get_color_config (shell); - -#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_color_config_get_simulation_color_profile (color_config, - NULL); - - 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, - view_softproof_profile_callback, - shell); - - dialogs_attach_dialog (G_OBJECT (shell), - SOFTPROOF_PROFILE_DIALOG_KEY, dialog); - } - - gtk_window_present (GTK_WINDOW (dialog)); -} - -void -view_softproof_intent_cmd_callback (GimpAction *action, - GVariant *value, - gpointer data) -{ - GimpDisplayShell *shell; - GimpColorConfig *color_config; - GimpColorRenderingIntent intent; - return_if_no_shell (shell, data); - - intent = (GimpColorRenderingIntent) g_variant_get_int32 (value); - - color_config = gimp_display_shell_get_color_config (shell); - - if (intent != gimp_color_config_get_simulation_intent (color_config)) - { - g_object_set (color_config, - "simulation-rendering-intent", intent, - NULL); - shell->color_config_set = TRUE; - } -} - -void -view_softproof_bpc_cmd_callback (GimpAction *action, - GVariant *value, - gpointer data) -{ - GimpDisplayShell *shell; - GimpColorConfig *color_config; - gboolean active; - return_if_no_shell (shell, data); - - color_config = gimp_display_shell_get_color_config (shell); - - active = g_variant_get_boolean (value); - - if (active != gimp_color_config_get_simulation_bpc (color_config)) - { - g_object_set (color_config, - "simulation-use-black-point-compensation", active, - NULL); - shell->color_config_set = TRUE; - } -} - void view_softproof_gamut_check_cmd_callback (GimpAction *action, GVariant *value, @@ -1247,32 +1152,6 @@ view_fullscreen_cmd_callback (GimpAction *action, /* private functions */ -static void -view_softproof_profile_callback (GtkWidget *dialog, - GimpImage *image, - GimpColorProfile *new_profile, - GFile *new_file, - GimpColorRenderingIntent intent, - gboolean bpc, - gpointer user_data) -{ - GimpDisplayShell *shell = user_data; - GimpColorConfig *color_config; - gchar *path = NULL; - - color_config = gimp_display_shell_get_color_config (shell); - - if (new_file) - path = g_file_get_path (new_file); - - g_object_set (color_config, - "simulation-profile", path, - NULL); - shell->color_config_set = TRUE; - - gtk_widget_destroy (dialog); -} - static void view_padding_color_dialog_update (GimpColorDialog *dialog, const GimpRGB *color, diff --git a/app/actions/view-commands.h b/app/actions/view-commands.h index b1c8d36679..51af901bb7 100644 --- a/app/actions/view-commands.h +++ b/app/actions/view-commands.h @@ -114,15 +114,6 @@ void view_display_intent_cmd_callback (GimpAction *action, void view_display_bpc_cmd_callback (GimpAction *action, GVariant *value, gpointer data); -void view_softproof_profile_cmd_callback (GimpAction *action, - GVariant *value, - gpointer data); -void view_softproof_intent_cmd_callback (GimpAction *action, - GVariant *value, - gpointer data); -void view_softproof_bpc_cmd_callback (GimpAction *action, - GVariant *value, - gpointer data); void view_softproof_gamut_check_cmd_callback (GimpAction *action, GVariant *value, gpointer data); diff --git a/app/core/gimpimage-color-profile.c b/app/core/gimpimage-color-profile.c index f3e5c8dfdd..64f868818d 100644 --- a/app/core/gimpimage-color-profile.c +++ b/app/core/gimpimage-color-profile.c @@ -391,6 +391,32 @@ gimp_image_set_color_profile (GimpImage *image, return gimp_image_set_icc_profile (image, data, length, error); } +GimpColorProfile * +gimp_image_get_simulation_profile (GimpImage *image) +{ + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + + return GIMP_IMAGE_GET_PRIVATE (image)->simulation_profile; +} + +void +gimp_image_set_simulation_profile (GimpImage *image, + GimpColorProfile *profile) +{ + GimpImagePrivate *private; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (profile == NULL || GIMP_IS_COLOR_PROFILE (profile)); + + private = GIMP_IMAGE_GET_PRIVATE (image); + + if (profile != private->simulation_profile) + { + g_set_object (&private->simulation_profile, profile); + gimp_color_managed_simulation_profile_changed (GIMP_COLOR_MANAGED (image)); + } +} + gboolean gimp_image_validate_color_profile_by_format (const Babl *format, GimpColorProfile *profile, diff --git a/app/core/gimpimage-color-profile.h b/app/core/gimpimage-color-profile.h index 863c41bda7..6548d36c1e 100644 --- a/app/core/gimpimage-color-profile.h +++ b/app/core/gimpimage-color-profile.h @@ -64,6 +64,10 @@ gboolean gimp_image_set_color_profile (GimpImage *ima GimpColorProfile *profile, GError **error); +GimpColorProfile * gimp_image_get_simulation_profile (GimpImage *image); +void gimp_image_set_simulation_profile (GimpImage *image, + GimpColorProfile *profile); + gboolean gimp_image_validate_color_profile_by_format (const Babl *format, GimpColorProfile *profile, diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h index 80e42dbd32..2beda44946 100644 --- a/app/core/gimpimage-private.h +++ b/app/core/gimpimage-private.h @@ -63,6 +63,7 @@ struct _GimpImagePrivate GimpColorProfile *color_profile; /* image's color profile */ const Babl *layer_space; /* image's Babl layer space */ GimpColorProfile *hidden_profile; /* hidden by "use sRGB" */ + GimpColorProfile *simulation_profile; /* image's softproof profile */ /* Cached color transforms: from layer to sRGB u8 and double, and back */ gboolean color_transforms_created; diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index a249e3dc4d..1e5d4d9b00 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -198,6 +198,11 @@ static GimpColorProfile * static void gimp_image_color_managed_profile_changed (GimpColorManaged *managed); +static GimpColorProfile * + gimp_image_color_managed_get_simulation_profile (GimpColorManaged *managed); +static void + gimp_image_color_managed_simulation_profile_changed (GimpColorManaged *managed); + static void gimp_image_projectable_flush (GimpProjectable *projectable, gboolean invalidate_preview); static GeglRectangle gimp_image_get_bounding_box (GimpProjectable *projectable); @@ -697,9 +702,11 @@ gimp_image_class_init (GimpImageClass *klass) static void gimp_color_managed_iface_init (GimpColorManagedInterface *iface) { - iface->get_icc_profile = gimp_image_color_managed_get_icc_profile; - iface->get_color_profile = gimp_image_color_managed_get_color_profile; - iface->profile_changed = gimp_image_color_managed_profile_changed; + iface->get_icc_profile = gimp_image_color_managed_get_icc_profile; + iface->get_color_profile = gimp_image_color_managed_get_color_profile; + iface->profile_changed = gimp_image_color_managed_profile_changed; + iface->get_simulation_profile = gimp_image_color_managed_get_simulation_profile; + iface->simulation_profile_changed = gimp_image_color_managed_simulation_profile_changed; } static void @@ -1438,6 +1445,26 @@ gimp_image_color_managed_profile_changed (GimpColorManaged *managed) gimp_item_stack_profile_changed (layers); } +static GimpColorProfile * +gimp_image_color_managed_get_simulation_profile (GimpColorManaged *managed) +{ + GimpImage *image = GIMP_IMAGE (managed); + GimpColorProfile *profile; + + profile = gimp_image_get_simulation_profile (image); + + return profile; +} + +static void +gimp_image_color_managed_simulation_profile_changed (GimpColorManaged *managed) +{ + GimpImage *image = GIMP_IMAGE (managed); + + gimp_projectable_structure_changed (GIMP_PROJECTABLE (image)); + gimp_viewable_invalidate_preview (GIMP_VIEWABLE (image)); +} + static void gimp_image_projectable_flush (GimpProjectable *projectable, gboolean invalidate_preview) diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c index 0cc0915456..ad8f69b0e0 100644 --- a/app/display/gimpdisplayshell-handlers.c +++ b/app/display/gimpdisplayshell-handlers.c @@ -129,6 +129,9 @@ static void gimp_display_shell_precision_changed_handler (GimpImage *i GimpDisplayShell *shell); static void gimp_display_shell_profile_changed_handler (GimpColorManaged *image, GimpDisplayShell *shell); +static void gimp_display_shell_simulation_profile_changed_handler + (GimpColorManaged *image, + GimpDisplayShell *shell); static void gimp_display_shell_saved_handler (GimpImage *image, GFile *file, GimpDisplayShell *shell); @@ -282,6 +285,9 @@ gimp_display_shell_connect (GimpDisplayShell *shell) g_signal_connect (image, "profile-changed", G_CALLBACK (gimp_display_shell_profile_changed_handler), shell); + g_signal_connect (image, "simulation-profile-changed", + G_CALLBACK (gimp_display_shell_simulation_profile_changed_handler), + shell); g_signal_connect (image, "saved", G_CALLBACK (gimp_display_shell_saved_handler), shell); @@ -519,6 +525,9 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell) g_signal_handlers_disconnect_by_func (image, gimp_display_shell_profile_changed_handler, shell); + g_signal_handlers_disconnect_by_func (image, + gimp_display_shell_simulation_profile_changed_handler, + shell); g_signal_handlers_disconnect_by_func (image, gimp_display_shell_precision_changed_handler, shell); @@ -923,6 +932,14 @@ gimp_display_shell_profile_changed_handler (GimpColorManaged *image, gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell)); } +static void +gimp_display_shell_simulation_profile_changed_handler (GimpColorManaged *image, + GimpDisplayShell *shell) +{ + gimp_display_shell_profile_update (shell); + gimp_color_managed_simulation_profile_changed (GIMP_COLOR_MANAGED (shell)); +} + static void gimp_display_shell_saved_handler (GimpImage *image, GFile *file, @@ -1190,7 +1207,6 @@ gimp_display_shell_color_config_notify_handler (GObject *config, if (! strcmp (param_spec->name, "mode") || ! strcmp (param_spec->name, "display-rendering-intent") || ! strcmp (param_spec->name, "display-use-black-point-compensation") || - ! strcmp (param_spec->name, "simulation-profile") || ! strcmp (param_spec->name, "simulation-rendering-intent") || ! strcmp (param_spec->name, "simulation-use-black-point-compensation") || ! strcmp (param_spec->name, "simulation-gamut-check")) diff --git a/app/display/gimpdisplayshell-profile.c b/app/display/gimpdisplayshell-profile.c index df6c4b144b..2eb457bde3 100644 --- a/app/display/gimpdisplayshell-profile.c +++ b/app/display/gimpdisplayshell-profile.c @@ -89,6 +89,7 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell) GimpColorProfile *filter_profile; const Babl *filter_format; const Babl *dest_format; + GimpColorProfile *proof_profile; gimp_display_shell_profile_free (shell); @@ -102,6 +103,8 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell) if (! src_profile) return; + proof_profile = gimp_color_managed_get_simulation_profile (GIMP_COLOR_MANAGED (image)); + src_format = gimp_projectable_get_format (GIMP_PROJECTABLE (image)); if (gimp_display_shell_has_filter (shell)) @@ -154,7 +157,8 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell) gimp_display_shell_get_color_config (shell), filter_profile, filter_format, - dest_format); + dest_format, + proof_profile); if (shell->filter_transform || shell->profile_transform) { @@ -261,7 +265,7 @@ gimp_display_shell_color_config_notify (GimpColorConfig *config, break; } - SET_ACTIVE ("view-color-management-enable", managed); + SET_ACTIVE ("view-color-management-enable", managed); SET_ACTIVE ("view-color-management-softproof", softproof); switch (gimp_color_config_get_display_intent (config)) @@ -293,39 +297,6 @@ gimp_display_shell_color_config_notify (GimpColorConfig *config, SET_SENSITIVE ("view-display-black-point-compensation", managed); SET_ACTIVE ("view-display-black-point-compensation", gimp_color_config_get_display_bpc (config)); - - SET_SENSITIVE ("view-softproof-profile", softproof); - - switch (gimp_color_config_get_simulation_intent (config)) - { - case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL: - action = "view-softproof-intent-perceptual"; - break; - - case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC: - action = "view-softproof-intent-relative-colorimetric"; - break; - - case GIMP_COLOR_RENDERING_INTENT_SATURATION: - action = "view-softproof-intent-saturation"; - break; - - case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: - action = "view-softproof-intent-absolute-colorimetric"; - break; - } - - SET_SENSITIVE ("view-softproof-intent-perceptual", softproof); - SET_SENSITIVE ("view-softproof-intent-relative-colorimetric", softproof); - SET_SENSITIVE ("view-softproof-intent-saturation", softproof); - SET_SENSITIVE ("view-softproof-intent-absolute-colorimetric", softproof); - - SET_ACTIVE (action, TRUE); - - SET_SENSITIVE ("view-softproof-black-point-compensation", softproof); - SET_ACTIVE ("view-softproof-black-point-compensation", - gimp_color_config_get_simulation_bpc (config)); - SET_SENSITIVE ("view-softproof-gamut-check", softproof); SET_ACTIVE ("view-softproof-gamut-check", gimp_color_config_get_simulation_gamut_check (config)); diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 066d935c25..1cd00c5c21 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -162,6 +162,8 @@ static const guint8 * static GimpColorProfile * gimp_display_shell_get_color_profile(GimpColorManaged *managed); static void gimp_display_shell_profile_changed(GimpColorManaged *managed); +static void gimp_display_shell_simulation_profile_changed + (GimpColorManaged *managed); static void gimp_display_shell_zoom_button_callback (GimpDisplayShell *shell, @@ -303,9 +305,10 @@ gimp_display_shell_class_init (GimpDisplayShellClass *klass) static void gimp_color_managed_iface_init (GimpColorManagedInterface *iface) { - iface->get_icc_profile = gimp_display_shell_get_icc_profile; - iface->get_color_profile = gimp_display_shell_get_color_profile; - iface->profile_changed = gimp_display_shell_profile_changed; + iface->get_icc_profile = gimp_display_shell_get_icc_profile; + iface->get_color_profile = gimp_display_shell_get_color_profile; + iface->profile_changed = gimp_display_shell_profile_changed; + iface->simulation_profile_changed = gimp_display_shell_simulation_profile_changed; } static void @@ -1084,6 +1087,15 @@ gimp_display_shell_profile_changed (GimpColorManaged *managed) gimp_display_shell_render_invalidate_full (shell); } +static void +gimp_display_shell_simulation_profile_changed (GimpColorManaged *managed) +{ + GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (managed); + + gimp_display_shell_expose_full (shell); + gimp_display_shell_render_invalidate_full (shell); +} + static void gimp_display_shell_zoom_button_callback (GimpDisplayShell *shell, GtkWidget *zoom_button) @@ -1356,6 +1368,7 @@ gimp_display_shell_reconnect (GimpDisplayShell *shell) g_signal_emit (shell, display_shell_signals[RECONNECT], 0); gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell)); + gimp_display_shell_simulation_profile_changed (GIMP_COLOR_MANAGED (shell)); gimp_display_shell_scroll_clamp_and_update (shell); diff --git a/app/pdb/image-color-profile-cmds.c b/app/pdb/image-color-profile-cmds.c index ba57055d31..bba265d574 100644 --- a/app/pdb/image-color-profile-cmds.c +++ b/app/pdb/image-color-profile-cmds.c @@ -226,6 +226,142 @@ image_set_color_profile_from_file_invoker (GimpProcedure *procedure, error ? *error : NULL); } +static GimpValueArray * +image_get_simulation_profile_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpValueArray *return_vals; + GimpImage *image; + gint num_bytes = 0; + guint8 *profile_data = NULL; + + image = g_value_get_object (gimp_value_array_index (args, 0)); + + if (success) + { + GimpColorProfile *profile; + + profile = gimp_image_get_simulation_profile (image); + + if (profile) + { + const guint8 *data; + gsize length; + + data = gimp_color_profile_get_icc_profile (profile, &length); + + profile_data = g_memdup2 (data, length); + num_bytes = length; + } + } + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + if (success) + { + g_value_set_int (gimp_value_array_index (return_vals, 1), num_bytes); + gimp_value_take_uint8_array (gimp_value_array_index (return_vals, 2), profile_data, num_bytes); + } + + return return_vals; +} + +static GimpValueArray * +image_set_simulation_profile_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpImage *image; + gint num_bytes; + const guint8 *color_profile; + + image = g_value_get_object (gimp_value_array_index (args, 0)); + num_bytes = g_value_get_int (gimp_value_array_index (args, 1)); + color_profile = gimp_value_get_uint8_array (gimp_value_array_index (args, 2)); + + if (success) + { + if (color_profile) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_icc_profile (color_profile, + num_bytes, + error); + + if (profile) + { + gimp_image_set_simulation_profile (image, profile); + g_object_unref (profile); + } + else + { + success = FALSE; + } + } + else + { + gimp_image_set_simulation_profile (image, NULL); + } + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + +static GimpValueArray * +image_set_simulation_profile_from_file_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpImage *image; + GFile *file; + + image = g_value_get_object (gimp_value_array_index (args, 0)); + file = g_value_get_object (gimp_value_array_index (args, 1)); + + if (success) + { + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + gimp_image_set_simulation_profile (image, profile); + g_object_unref (profile); + } + else + { + success = FALSE; + } + } + else + { + gimp_image_set_simulation_profile (image, NULL); + } + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + static GimpValueArray * image_convert_color_profile_invoker (GimpProcedure *procedure, Gimp *gimp, @@ -456,6 +592,103 @@ register_image_color_profile_procs (GimpPDB *pdb) gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + /* + * gimp-image-get-simulation-profile + */ + procedure = gimp_procedure_new (image_get_simulation_profile_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-image-get-simulation-profile"); + gimp_procedure_set_static_help (procedure, + "Returns the image's simulation color profile", + "This procedure returns the image's simulation color profile, or NULL if the image has no simulation color profile assigned.", + NULL); + gimp_procedure_set_static_attribution (procedure, + "Alex S.", + "Alex S.", + "2022"); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image ("image", + "image", + "The image", + FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + g_param_spec_int ("num-bytes", + "num bytes", + "Number of bytes in the color_profile array", + 0, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + gimp_param_spec_uint8_array ("profile-data", + "profile data", + "The image's serialized simulation color profile.", + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-image-set-simulation-profile + */ + procedure = gimp_procedure_new (image_set_simulation_profile_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-image-set-simulation-profile"); + gimp_procedure_set_static_help (procedure, + "Sets the image's simulation color profile", + "This procedure sets the image's simulation color profile, or unsets it if NULL is passed as 'color_profile'. This procedure does no color conversion.", + NULL); + gimp_procedure_set_static_attribution (procedure, + "Alex S.", + "Alex S.", + "2022"); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image ("image", + "image", + "The image", + FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_int ("num-bytes", + "num bytes", + "Number of bytes in the color_profile array", + 0, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_uint8_array ("color-profile", + "color profile", + "The new serialized simulation color profile", + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-image-set-simulation-profile-from-file + */ + procedure = gimp_procedure_new (image_set_simulation_profile_from_file_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-image-set-simulation-profile-from-file"); + gimp_procedure_set_static_help (procedure, + "Sets the image's simulation color profile from an ICC file", + "This procedure sets the image's simulation color profile from a file containing an ICC profile, or unsets it if NULL is passed as 'file'. This procedure does no color conversion.", + NULL); + gimp_procedure_set_static_attribution (procedure, + "Alex S.", + "Alex S.", + "2022"); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image ("image", + "image", + "The image", + FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_object ("file", + "file", + "The file containing the new simulation color profile", + G_TYPE_FILE, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + /* * gimp-image-convert-color-profile */ diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c index 9671f5263b..1fa6c26fde 100644 --- a/app/pdb/internal-procs.c +++ b/app/pdb/internal-procs.c @@ -30,7 +30,7 @@ #include "internal-procs.h" -/* 762 procedures registered total */ +/* 765 procedures registered total */ void internal_procs_init (GimpPDB *pdb) diff --git a/app/widgets/gimpfgbgeditor.c b/app/widgets/gimpfgbgeditor.c index c7f319292a..b0d51df77d 100644 --- a/app/widgets/gimpfgbgeditor.c +++ b/app/widgets/gimpfgbgeditor.c @@ -794,7 +794,8 @@ gimp_fg_bg_editor_create_transform (GimpFgBgEditor *editor) editor->color_config, profile, babl_format ("R'G'B'A double"), - babl_format ("R'G'B'A double")); + babl_format ("R'G'B'A double"), + NULL); } } diff --git a/app/widgets/gimpfgbgview.c b/app/widgets/gimpfgbgview.c index 9c60418211..7da1803dc6 100644 --- a/app/widgets/gimpfgbgview.c +++ b/app/widgets/gimpfgbgview.c @@ -255,7 +255,8 @@ gimp_fg_bg_view_create_transform (GimpFgBgView *view) view->color_config, profile, babl_format ("R'G'B'A double"), - babl_format ("R'G'B'A double")); + babl_format ("R'G'B'A double"), + NULL); } } diff --git a/app/widgets/gimpviewrenderer.c b/app/widgets/gimpviewrenderer.c index a5061f90b8..8edfe4d547 100644 --- a/app/widgets/gimpviewrenderer.c +++ b/app/widgets/gimpviewrenderer.c @@ -1029,6 +1029,8 @@ gimp_view_renderer_get_color_transform (GimpViewRenderer *renderer, const Babl *dest_format) { GimpColorProfile *profile; + GimpColorProfile *proof_profile = NULL; + GimpImage *image; g_return_val_if_fail (GIMP_IS_VIEW_RENDERER (renderer), NULL); g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); @@ -1060,12 +1062,21 @@ gimp_view_renderer_get_color_transform (GimpViewRenderer *renderer, profile = srgb_profile; } + if (renderer->context) + { + image = gimp_context_get_image (GIMP_CONTEXT (renderer->context)); + if (image) + proof_profile = + gimp_color_managed_get_simulation_profile (GIMP_COLOR_MANAGED (image)); + } + renderer->priv->profile_transform = gimp_widget_get_color_transform (widget, renderer->priv->color_config, profile, src_format, - dest_format); + dest_format, + proof_profile); return renderer->priv->profile_transform; } diff --git a/libgimp/gimp.def b/libgimp/gimp.def index b05044bb11..0cde15376d 100644 --- a/libgimp/gimp.def +++ b/libgimp/gimp.def @@ -420,6 +420,7 @@ EXPORTS gimp_image_get_sample_point_position gimp_image_get_selected_layers gimp_image_get_selection + gimp_image_get_simulation_profile gimp_image_get_tattoo_state gimp_image_get_thumbnail gimp_image_get_thumbnail_data @@ -498,6 +499,8 @@ EXPORTS gimp_image_set_metadata gimp_image_set_resolution gimp_image_set_selected_layers + gimp_image_set_simulation_profile + gimp_image_set_simulation_profile_from_file gimp_image_set_tattoo_state gimp_image_set_unit gimp_image_take_selected_layers diff --git a/libgimp/gimpimagecolorprofile.c b/libgimp/gimpimagecolorprofile.c index bb22bd5ce8..4c9f5b5140 100644 --- a/libgimp/gimpimagecolorprofile.c +++ b/libgimp/gimpimagecolorprofile.c @@ -92,6 +92,75 @@ gimp_image_set_color_profile (GimpImage *image, return _gimp_image_set_color_profile (image, length, data); } +/** + * gimp_image_get_simulation_profile: + * @image: The image. + * + * Returns the image's simulation color profile + * + * This procedure returns the image's simulation color profile, or NULL if + * the image has no simulation color profile assigned. + * + * Returns: (transfer full): The image's simulation color profile. The + * returned value must be freed with g_object_unref(). + * + * Since: 3.0 + **/ +GimpColorProfile * +gimp_image_get_simulation_profile (GimpImage *image) +{ + guint8 *data; + gint length; + + data = _gimp_image_get_simulation_profile (image, &length); + + if (data) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_icc_profile (data, length, NULL); + g_free (data); + + return profile; + } + + return NULL; +} + +/** + * gimp_image_set_simulation_profile: + * @image: The image. + * @profile: A #GimpColorProfile, or %NULL. + * + * Sets the image's simulation color profile + * + * This procedure sets the image's simulation color profile. + * + * Returns: %TRUE on success. + * + * Since: 3.0 + **/ +gboolean +gimp_image_set_simulation_profile (GimpImage *image, + GimpColorProfile *profile) +{ + const guint8 *data = NULL; + gint length = 0; + + g_return_val_if_fail (profile == NULL || GIMP_IS_COLOR_PROFILE (profile), + FALSE); + + if (profile) + { + gsize l; + + data = gimp_color_profile_get_icc_profile (profile, &l); + length = l; + } + + return _gimp_image_set_simulation_profile (image, length, data); +} + /** * gimp_image_get_effective_color_profile: * @image: The image. diff --git a/libgimp/gimpimagecolorprofile.h b/libgimp/gimpimagecolorprofile.h index 63ae015f04..92e4e60123 100644 --- a/libgimp/gimpimagecolorprofile.h +++ b/libgimp/gimpimagecolorprofile.h @@ -34,6 +34,10 @@ GimpColorProfile * gimp_image_get_color_profile (GimpImage gboolean gimp_image_set_color_profile (GimpImage *image, GimpColorProfile *profile); +GimpColorProfile * gimp_image_get_simulation_profile (GimpImage *image); +gboolean gimp_image_set_simulation_profile (GimpImage *image, + GimpColorProfile *profile); + GimpColorProfile * gimp_image_get_effective_color_profile (GimpImage *image); gboolean gimp_image_convert_color_profile (GimpImage *image, diff --git a/libgimp/gimpimagecolorprofile_pdb.c b/libgimp/gimpimagecolorprofile_pdb.c index e2f761d40b..08504f6e01 100644 --- a/libgimp/gimpimagecolorprofile_pdb.c +++ b/libgimp/gimpimagecolorprofile_pdb.c @@ -220,6 +220,136 @@ gimp_image_set_color_profile_from_file (GimpImage *image, return success; } +/** + * _gimp_image_get_simulation_profile: + * @image: The image. + * @num_bytes: (out): Number of bytes in the color_profile array. + * + * Returns the image's simulation color profile + * + * This procedure returns the image's simulation color profile, or NULL + * if the image has no simulation color profile assigned. + * + * Returns: (array length=num_bytes) (element-type guint8) (transfer full): + * The image's serialized simulation color profile. + * The returned value must be freed with g_free(). + * + * Since: 3.0 + **/ +guint8 * +_gimp_image_get_simulation_profile (GimpImage *image, + gint *num_bytes) +{ + GimpValueArray *args; + GimpValueArray *return_vals; + guint8 *profile_data = NULL; + + args = gimp_value_array_new_from_types (NULL, + GIMP_TYPE_IMAGE, image, + G_TYPE_NONE); + + return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (), + "gimp-image-get-simulation-profile", + args); + gimp_value_array_unref (args); + + *num_bytes = 0; + + if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS) + { + *num_bytes = GIMP_VALUES_GET_INT (return_vals, 1); + profile_data = GIMP_VALUES_DUP_UINT8_ARRAY (return_vals, 2); + } + + gimp_value_array_unref (return_vals); + + return profile_data; +} + +/** + * _gimp_image_set_simulation_profile: + * @image: The image. + * @num_bytes: Number of bytes in the color_profile array. + * @color_profile: (array length=num_bytes) (element-type guint8): The new serialized simulation color profile. + * + * Sets the image's simulation color profile + * + * This procedure sets the image's simulation color profile, or unsets + * it if NULL is passed as 'color_profile'. This procedure does no + * color conversion. + * + * Returns: TRUE on success. + * + * Since: 3.0 + **/ +gboolean +_gimp_image_set_simulation_profile (GimpImage *image, + gint num_bytes, + const guint8 *color_profile) +{ + GimpValueArray *args; + GimpValueArray *return_vals; + gboolean success = TRUE; + + args = gimp_value_array_new_from_types (NULL, + GIMP_TYPE_IMAGE, image, + G_TYPE_INT, num_bytes, + GIMP_TYPE_UINT8_ARRAY, NULL, + G_TYPE_NONE); + gimp_value_set_uint8_array (gimp_value_array_index (args, 2), color_profile, num_bytes); + + return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (), + "gimp-image-set-simulation-profile", + args); + gimp_value_array_unref (args); + + success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS; + + gimp_value_array_unref (return_vals); + + return success; +} + +/** + * gimp_image_set_simulation_profile_from_file: + * @image: The image. + * @file: The file containing the new simulation color profile. + * + * Sets the image's simulation color profile from an ICC file + * + * This procedure sets the image's simulation color profile from a file + * containing an ICC profile, or unsets it if NULL is passed as 'file'. + * This procedure does no color conversion. + * + * Returns: TRUE on success. + * + * Since: 3.0 + **/ +gboolean +gimp_image_set_simulation_profile_from_file (GimpImage *image, + GFile *file) +{ + GimpValueArray *args; + GimpValueArray *return_vals; + gboolean success = TRUE; + + args = gimp_value_array_new_from_types (NULL, + GIMP_TYPE_IMAGE, image, + G_TYPE_FILE, file, + G_TYPE_NONE); + + return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (), + "gimp-image-set-simulation-profile-from-file", + args); + gimp_value_array_unref (args); + + success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS; + + gimp_value_array_unref (return_vals); + + return success; +} + /** * _gimp_image_convert_color_profile: * @image: The image. diff --git a/libgimp/gimpimagecolorprofile_pdb.h b/libgimp/gimpimagecolorprofile_pdb.h index 0731a9eb1e..ac49fc8f9f 100644 --- a/libgimp/gimpimagecolorprofile_pdb.h +++ b/libgimp/gimpimagecolorprofile_pdb.h @@ -32,24 +32,31 @@ G_BEGIN_DECLS /* For information look into the C source or the html documentation */ -G_GNUC_INTERNAL guint8* _gimp_image_get_color_profile (GimpImage *image, - gint *num_bytes); -G_GNUC_INTERNAL guint8* _gimp_image_get_effective_color_profile (GimpImage *image, - gint *num_bytes); -G_GNUC_INTERNAL gboolean _gimp_image_set_color_profile (GimpImage *image, - gint num_bytes, - const guint8 *color_profile); -gboolean gimp_image_set_color_profile_from_file (GimpImage *image, - GFile *file); -G_GNUC_INTERNAL gboolean _gimp_image_convert_color_profile (GimpImage *image, - gint num_bytes, - const guint8 *color_profile, - GimpColorRenderingIntent intent, - gboolean bpc); -gboolean gimp_image_convert_color_profile_from_file (GimpImage *image, - GFile *file, - GimpColorRenderingIntent intent, - gboolean bpc); +G_GNUC_INTERNAL guint8* _gimp_image_get_color_profile (GimpImage *image, + gint *num_bytes); +G_GNUC_INTERNAL guint8* _gimp_image_get_effective_color_profile (GimpImage *image, + gint *num_bytes); +G_GNUC_INTERNAL gboolean _gimp_image_set_color_profile (GimpImage *image, + gint num_bytes, + const guint8 *color_profile); +gboolean gimp_image_set_color_profile_from_file (GimpImage *image, + GFile *file); +G_GNUC_INTERNAL guint8* _gimp_image_get_simulation_profile (GimpImage *image, + gint *num_bytes); +G_GNUC_INTERNAL gboolean _gimp_image_set_simulation_profile (GimpImage *image, + gint num_bytes, + const guint8 *color_profile); +gboolean gimp_image_set_simulation_profile_from_file (GimpImage *image, + GFile *file); +G_GNUC_INTERNAL gboolean _gimp_image_convert_color_profile (GimpImage *image, + gint num_bytes, + const guint8 *color_profile, + GimpColorRenderingIntent intent, + gboolean bpc); +gboolean gimp_image_convert_color_profile_from_file (GimpImage *image, + GFile *file, + GimpColorRenderingIntent intent, + gboolean bpc); G_END_DECLS diff --git a/libgimpcolor/gimpcolor.def b/libgimpcolor/gimpcolor.def index 47dbb99c57..7b40b20570 100644 --- a/libgimpcolor/gimpcolor.def +++ b/libgimpcolor/gimpcolor.def @@ -21,8 +21,10 @@ EXPORTS gimp_cmyka_set_uchar gimp_color_managed_get_color_profile gimp_color_managed_get_icc_profile + gimp_color_managed_get_simulation_profile gimp_color_managed_get_type gimp_color_managed_profile_changed + gimp_color_managed_simulation_profile_changed gimp_color_profile_get_copyright gimp_color_profile_get_description gimp_color_profile_get_format diff --git a/libgimpcolor/gimpcolormanaged.c b/libgimpcolor/gimpcolormanaged.c index dca1fdbae8..4dc5a3e213 100644 --- a/libgimpcolor/gimpcolormanaged.c +++ b/libgimpcolor/gimpcolormanaged.c @@ -42,6 +42,7 @@ enum { PROFILE_CHANGED, + SIMULATION_PROFILE_CHANGED, LAST_SIGNAL }; @@ -66,6 +67,15 @@ gimp_color_managed_default_init (GimpColorManagedInterface *iface) profile_changed), NULL, NULL, NULL, G_TYPE_NONE, 0); + + gimp_color_managed_signals[SIMULATION_PROFILE_CHANGED] = + g_signal_new ("simulation-profile-changed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpColorManagedInterface, + simulation_profile_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 0); } @@ -128,9 +138,34 @@ gimp_color_managed_get_color_profile (GimpColorManaged *managed) } /** - * gimp_color_managed_profile_changed: + * gimp_color_managed_get_simulation_profile: * @managed: an object the implements the #GimpColorManaged interface * + * This function always returns a #GimpColorProfile + * + * Returns: (transfer full): The @managed's simulation #GimpColorProfile. + * + * Since: 3.0 + **/ +GimpColorProfile * +gimp_color_managed_get_simulation_profile (GimpColorManaged *managed) +{ + GimpColorManagedInterface *iface; + + g_return_val_if_fail (GIMP_IS_COLOR_MANAGED (managed), NULL); + + iface = GIMP_COLOR_MANAGED_GET_IFACE (managed); + + if (iface->get_simulation_profile) + return iface->get_simulation_profile (managed); + + return NULL; +} + +/** + * gimp_color_managed_profile_changed: + * @managed: an object that implements the #GimpColorManaged interface + * * Emits the "profile-changed" signal. * * Since: 2.4 @@ -142,3 +177,19 @@ gimp_color_managed_profile_changed (GimpColorManaged *managed) g_signal_emit (managed, gimp_color_managed_signals[PROFILE_CHANGED], 0); } + +/** + * gimp_color_managed_simulation_profile_changed: + * @managed: an object that implements the #GimpColorManaged interface + * + * Emits the "simulation-profile-changed" signal. + * + * Since: 3.0 + **/ +void +gimp_color_managed_simulation_profile_changed (GimpColorManaged *managed) +{ + g_return_if_fail (GIMP_IS_COLOR_MANAGED (managed)); + + g_signal_emit (managed, gimp_color_managed_signals[SIMULATION_PROFILE_CHANGED], 0); +} diff --git a/libgimpcolor/gimpcolormanaged.h b/libgimpcolor/gimpcolormanaged.h index b6a473b509..cf36ffad7c 100644 --- a/libgimpcolor/gimpcolormanaged.h +++ b/libgimpcolor/gimpcolormanaged.h @@ -43,6 +43,8 @@ G_DECLARE_INTERFACE (GimpColorManaged, gimp_color_managed, GIMP, COLOR_MANAGED, * has changed * @get_color_profile: Returns the #GimpColorProfile of the pixels managed * by the object + * @get_simulation_profile: Returns the simulation #GimpColorProfile of the + * pixels managed by the object **/ struct _GimpColorManagedInterface { @@ -58,22 +60,29 @@ struct _GimpColorManagedInterface * * Since: 2.4 */ - const guint8 * (* get_icc_profile) (GimpColorManaged *managed, - gsize *len); + const guint8 * (* get_icc_profile) (GimpColorManaged *managed, + gsize *len); /* signals */ - void (* profile_changed) (GimpColorManaged *managed); + void (* profile_changed) (GimpColorManaged *managed); + + void (* simulation_profile_changed) (GimpColorManaged *managed); /* virtual functions */ - GimpColorProfile * (* get_color_profile) (GimpColorManaged *managed); + GimpColorProfile * (* get_color_profile) (GimpColorManaged *managed); + GimpColorProfile * (* get_simulation_profile) (GimpColorManaged *managed); }; -const guint8 * gimp_color_managed_get_icc_profile (GimpColorManaged *managed, - gsize *len); -GimpColorProfile * gimp_color_managed_get_color_profile (GimpColorManaged *managed); +const guint8 * gimp_color_managed_get_icc_profile (GimpColorManaged *managed, + gsize *len); +GimpColorProfile * gimp_color_managed_get_color_profile (GimpColorManaged *managed); -void gimp_color_managed_profile_changed (GimpColorManaged *managed); +GimpColorProfile * gimp_color_managed_get_simulation_profile (GimpColorManaged *managed); + +void gimp_color_managed_profile_changed (GimpColorManaged *managed); + +void gimp_color_managed_simulation_profile_changed (GimpColorManaged *managed); G_END_DECLS diff --git a/libgimpwidgets/gimpcolorarea.c b/libgimpwidgets/gimpcolorarea.c index 0ea20d82ba..604d2e9c23 100644 --- a/libgimpwidgets/gimpcolorarea.c +++ b/libgimpwidgets/gimpcolorarea.c @@ -1024,7 +1024,8 @@ gimp_color_area_create_transform (GimpColorArea *area) priv->config, profile, format, - format); + format, + NULL); } } diff --git a/libgimpwidgets/gimpcolorscale.c b/libgimpwidgets/gimpcolorscale.c index 7d4f6ffc45..0bf7f665fe 100644 --- a/libgimpwidgets/gimpcolorscale.c +++ b/libgimpwidgets/gimpcolorscale.c @@ -942,7 +942,8 @@ gimp_color_scale_create_transform (GimpColorScale *scale) priv->config, profile, format, - format); + format, + NULL); } } diff --git a/libgimpwidgets/gimpcolorselect.c b/libgimpwidgets/gimpcolorselect.c index d4b2b1ad03..af7a119f29 100644 --- a/libgimpwidgets/gimpcolorselect.c +++ b/libgimpwidgets/gimpcolorselect.c @@ -1956,7 +1956,8 @@ gimp_color_select_create_transform (GimpColorSelect *select) select->config, profile, format, - format); + format, + NULL); } } diff --git a/libgimpwidgets/gimppreviewarea.c b/libgimpwidgets/gimppreviewarea.c index 7bc7bc393b..424d0c1246 100644 --- a/libgimpwidgets/gimppreviewarea.c +++ b/libgimpwidgets/gimppreviewarea.c @@ -437,7 +437,8 @@ gimp_preview_area_create_transform (GimpPreviewArea *area) priv->config, profile, format, - format); + format, + NULL); } } diff --git a/libgimpwidgets/gimpwidgetsutils.c b/libgimpwidgets/gimpwidgetsutils.c index 4c46e83d04..bc7038bf9a 100644 --- a/libgimpwidgets/gimpwidgetsutils.c +++ b/libgimpwidgets/gimpwidgetsutils.c @@ -870,11 +870,12 @@ gimp_widget_get_color_transform (GtkWidget *widget, GimpColorConfig *config, GimpColorProfile *src_profile, const Babl *src_format, - const Babl *dest_format) + const Babl *dest_format, + GimpColorProfile *softproof_profile) { static gboolean initialized = FALSE; - GimpColorProfile *dest_profile = NULL; GimpColorProfile *proof_profile = NULL; + GimpColorProfile *dest_profile = NULL; TransformCache *cache; g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL); @@ -896,8 +897,11 @@ gimp_widget_get_color_transform (GtkWidget *widget, return NULL; case GIMP_COLOR_MANAGEMENT_SOFTPROOF: - proof_profile = gimp_color_config_get_simulation_color_profile (config, - NULL); + if (! softproof_profile) + proof_profile = gimp_color_config_get_simulation_color_profile (config, + NULL); + else + proof_profile = softproof_profile; /* fallthru */ case GIMP_COLOR_MANAGEMENT_DISPLAY: @@ -943,7 +947,7 @@ gimp_widget_get_color_transform (GtkWidget *widget, cache->src_format = src_format; cache->dest_profile = dest_profile; cache->dest_format = dest_format; - cache->proof_profile = proof_profile; + cache->proof_profile = g_object_ref (proof_profile); cache->notify_id = g_signal_connect (cache->config, "notify", diff --git a/libgimpwidgets/gimpwidgetsutils.h b/libgimpwidgets/gimpwidgetsutils.h index b75d60808a..7de3e18cd4 100644 --- a/libgimpwidgets/gimpwidgetsutils.h +++ b/libgimpwidgets/gimpwidgetsutils.h @@ -60,7 +60,8 @@ GimpColorTransform * gimp_widget_get_color_transform (GtkWidget *widget, GimpColorConfig *config, GimpColorProfile *src_profile, const Babl *src_format, - const Babl *dest_format); + const Babl *dest_format, + GimpColorProfile *softproof_profile); G_END_DECLS diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in index f9b7b5c262..4216acf6b3 100644 --- a/menus/image-menu.xml.in +++ b/menus/image-menu.xml.in @@ -320,16 +320,7 @@ - - - - - - - - - @@ -394,6 +385,16 @@ + + + + + + + + + + diff --git a/modules/color-selector-water.c b/modules/color-selector-water.c index 65a207486d..ee04e6e48b 100644 --- a/modules/color-selector-water.c +++ b/modules/color-selector-water.c @@ -268,7 +268,8 @@ colorsel_water_create_transform (ColorselWater *water) water->config, profile, format, - format); + format, + NULL); } } diff --git a/modules/gimpcolorwheel.c b/modules/gimpcolorwheel.c index 90d1ee95b2..3f35ef86bd 100644 --- a/modules/gimpcolorwheel.c +++ b/modules/gimpcolorwheel.c @@ -1551,7 +1551,8 @@ gimp_color_wheel_create_transform (GimpColorWheel *wheel) priv->config, profile, format, - format); + format, + NULL); } } diff --git a/pdb/groups/image_color_profile.pdb b/pdb/groups/image_color_profile.pdb index 1f9231ca13..3bf8e9abb0 100644 --- a/pdb/groups/image_color_profile.pdb +++ b/pdb/groups/image_color_profile.pdb @@ -213,6 +213,149 @@ CODE ); } +sub image_get_simulation_profile { + $blurb = "Returns the image's simulation color profile"; + + $help = <<'HELP'; +This procedure returns the image's simulation color profile, or NULL if the image +has no simulation color profile assigned. +HELP + + &alxsa_pdb_misc('2022', '3.0'); + + $lib_private = 1; + + @inargs = ( + { name => 'image', type => 'image', + desc => 'The image' } + ); + + @outargs = ( + { name => 'profile_data', type => 'int8array', + desc => "The image's serialized simulation color profile.", + array => { name => 'num_bytes', + desc => 'Number of bytes in the color_profile array' } } + ); + + %invoke = ( + code => <<'CODE' +{ + GimpColorProfile *profile; + + profile = gimp_image_get_simulation_profile (image); + + if (profile) + { + const guint8 *data; + gsize length; + + data = gimp_color_profile_get_icc_profile (profile, &length); + + profile_data = g_memdup2 (data, length); + num_bytes = length; + } +} +CODE + ); +} + +sub image_set_simulation_profile { + $blurb = "Sets the image's simulation color profile"; + + $help = <<'HELP'; +This procedure sets the image's simulation color profile, or unsets it if NULL is +passed as 'color_profile'. This procedure does no color conversion. +HELP + + &alxsa_pdb_misc('2022', '3.0'); + + $lib_private = 1; + + @inargs = ( + { name => 'image', type => 'image', + desc => 'The image' }, + { name => 'color_profile', type => 'int8array', + desc => 'The new serialized simulation color profile', + array => { name => 'num_bytes', + desc => 'Number of bytes in the color_profile array' } } + ); + + %invoke = ( + code => <<'CODE' +{ + if (color_profile) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_icc_profile (color_profile, + num_bytes, + error); + + if (profile) + { + gimp_image_set_simulation_profile (image, profile); + g_object_unref (profile); + } + else + { + success = FALSE; + } + } + else + { + gimp_image_set_simulation_profile (image, NULL); + } +} +CODE + ); +} + +sub image_set_simulation_profile_from_file { + $blurb = "Sets the image's simulation color profile from an ICC file"; + + $help = <<'HELP'; +This procedure sets the image's simulation color profile from a file containing +an ICC profile, or unsets it if NULL is passed as 'file'. This +procedure does no color conversion. +HELP + + &alxsa_pdb_misc('2022', '3.0'); + + @inargs = ( + { name => 'image', type => 'image', + desc => 'The image' }, + { name => 'file', type => 'file', + desc => 'The file containing the new simulation color profile' } + ); + + %invoke = ( + code => <<'CODE' +{ + if (file) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_file (file, error); + + if (profile) + { + gimp_image_set_simulation_profile (image, profile); + g_object_unref (profile); + } + else + { + success = FALSE; + } + } + else + { + gimp_image_set_simulation_profile (image, NULL); + } +} +CODE + ); +} + sub image_convert_color_profile { $blurb = "Convert the image's layers to a color profile"; @@ -326,6 +469,9 @@ CODE image_get_effective_color_profile image_set_color_profile image_set_color_profile_from_file + image_get_simulation_profile + image_set_simulation_profile + image_set_simulation_profile_from_file image_convert_color_profile image_convert_color_profile_from_file); diff --git a/pdb/stddefs.pdb b/pdb/stddefs.pdb index 9c7a7ac49d..6e9fd4ce9c 100644 --- a/pdb/stddefs.pdb +++ b/pdb/stddefs.pdb @@ -165,6 +165,10 @@ sub yosh_pdb_misc { contrib_pdb_misc('Manish Singh', '', @_); } +sub alxsa_pdb_misc { + contrib_pdb_misc('Alex S.', '', @_); +} + sub std_pdb_deprecated { if (@_) { $blurb = $help = '';