diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c index 5a3c69de8e..7dfa256b9f 100644 --- a/plug-ins/file-psd/psd-load.c +++ b/plug-ins/file-psd/psd-load.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "psd.h" #include "psd-util.h" @@ -3268,3 +3269,50 @@ get_mask_format (PSDimage *img_a) return format; } + +void +load_dialog (void) +{ + GtkWidget *dialog; + GtkWidget *label; + GtkWidget *vbox; + gchar *label_text; + + dialog = gimp_dialog_new (_("PSD Compatibility Notice"), + "psd-compatibility-notice", + NULL, 0, NULL, NULL, + _("_OK"), GTK_RESPONSE_OK, + NULL); + + gimp_window_set_transient (GTK_WINDOW (dialog)); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), + vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + /* Duotone import notification */ + label_text = g_strdup_printf ("%s\n%s", _("Duotone Import"), + _("Image will be imported as Grayscale.\n" + "Duotone color space data has been saved\n" + "and can be reapplied on export.")); + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), label_text); + + gtk_label_set_selectable (GTK_LABEL (label), TRUE); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_label_set_yalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); + gtk_widget_show (label); + + g_free (label_text); + + gtk_widget_show (dialog); + + /* run the dialog */ + gimp_dialog_run (GIMP_DIALOG (dialog)); + + gtk_widget_destroy (dialog); +} diff --git a/plug-ins/file-psd/psd-load.h b/plug-ins/file-psd/psd-load.h index 565f9ef750..cd49d95cfd 100644 --- a/plug-ins/file-psd/psd-load.h +++ b/plug-ins/file-psd/psd-load.h @@ -22,11 +22,13 @@ #define __PSD_LOAD_H__ -GimpImage * load_image (GFile *file, - gboolean merged_image_only, - gboolean *resolution_loaded, - gboolean *profile_loaded, - GError **error); +GimpImage * load_image (GFile *file, + gboolean merged_image_only, + gboolean *resolution_loaded, + gboolean *profile_loaded, + GError **error); + +void load_dialog (void); #endif /* __PSD_LOAD_H__ */ diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c index 4419e75c1c..5767384512 100644 --- a/plug-ins/file-psd/psd-save.c +++ b/plug-ins/file-psd/psd-save.c @@ -132,13 +132,16 @@ static const gchar * psd_lmode_layer (GimpLayer *layer, static void reshuffle_cmap_write (guchar *mapGimp); static void save_header (GOutputStream *output, - GimpImage *image); + GimpImage *image, + gboolean export_duotone); static void save_color_mode_data (GOutputStream *output, - GimpImage *image); + GimpImage *image, + gboolean export_duotone); static void save_resources (GOutputStream *output, - GimpImage *image); + GimpImage *image, + gboolean export_duotone); static void save_layer_and_mask (GOutputStream *output, GimpImage *image); @@ -524,7 +527,8 @@ reshuffle_cmap_write (guchar *mapGimp) static void save_header (GOutputStream *output, - GimpImage *image) + GimpImage *image, + gboolean export_duotone) { IFDBG(1) g_debug ("Function: save_header\n" "\tRows: %d\n" @@ -545,20 +549,42 @@ save_header (GOutputStream *output, write_gint32 (output, PSDImageData.image_height, "rows"); write_gint32 (output, PSDImageData.image_width, "columns"); write_gint16 (output, 8 * get_bpc (image), "depth"); - write_gint16 (output, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode"); + if (export_duotone) + write_gint16 (output, PSD_DUOTONE, "mode"); + else + write_gint16 (output, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode"); } static void save_color_mode_data (GOutputStream *output, - GimpImage *image) + GimpImage *image, + gboolean export_duotone) { - guchar *cmap; - guchar *cmap_modified; - gint i; - gint32 nColors; + guchar *cmap; + guchar *cmap_modified; + gint i; + gint32 nColors; + GimpParasite *parasite = NULL; IFDBG(1) g_debug ("Function: save_color_mode_data"); + parasite = gimp_image_get_parasite (image, PSD_PARASITE_DUOTONE_DATA); + if (export_duotone && parasite) + { + const guchar *parasite_data; + guint32 parasite_size; + + IFDBG(1) g_debug ("\tImage type: DUOTONE"); + + parasite_data = (const guchar *) gimp_parasite_get_data (parasite, ¶site_size); + + write_gint32 (output, parasite_size, "color data length"); + xfwrite (output, parasite_data, parasite_size, "colormap"); + + gimp_parasite_free (parasite); + return; + } + switch (PSDImageData.baseType) { case GIMP_INDEXED: @@ -607,7 +633,8 @@ save_color_mode_data (GOutputStream *output, static void save_resources (GOutputStream *output, - GimpImage *image) + GimpImage *image, + gboolean export_duotone) { GList *iter; gint i; @@ -885,9 +912,10 @@ save_resources (GOutputStream *output, /* --------------- Write ICC profile data ------------------- */ { - GimpColorProfile *profile; + GimpColorProfile *profile = NULL; - profile = gimp_image_get_effective_color_profile (image); + if (! export_duotone) + profile = gimp_image_get_effective_color_profile (image); if (profile) { @@ -1754,12 +1782,19 @@ clear_image_data (void) gboolean save_image (GFile *file, GimpImage *image, + GObject *config, GError **error) { GOutputStream *output; GeglBuffer *buffer; GList *iter; GError *local_error = NULL; + GimpParasite *parasite = NULL; + gboolean config_duotone; + + g_object_get (config, + "duotone", &config_duotone, + NULL); IFDBG(1) g_debug ("Function: save_image"); @@ -1777,6 +1812,22 @@ save_image (GFile *file, gimp_progress_init_printf (_("Exporting '%s'"), gimp_file_get_utf8_name (file)); + /* If image is not grayscale or lacks Duotone color space parasite, + * turn off "Export as Duotone". + */ + parasite = gimp_image_get_parasite (image, PSD_PARASITE_DUOTONE_DATA); + if (parasite) + { + if (gimp_image_get_base_type (image) != GIMP_GRAY) + config_duotone = FALSE; + + gimp_parasite_free (parasite); + } + else + { + config_duotone = FALSE; + } + get_image_data (image); /* Need to check each of the layers size individually also */ @@ -1828,9 +1879,9 @@ save_image (GFile *file, IFDBG(1) g_debug ("\tFile '%s' has been opened", gimp_file_get_utf8_name (file)); - save_header (output, image); - save_color_mode_data (output, image); - save_resources (output, image); + save_header (output, image, config_duotone); + save_color_mode_data (output, image, config_duotone); + save_resources (output, image, config_duotone); /* PSD format does not support layers in indexed images */ @@ -2025,3 +2076,45 @@ image_get_all_layers (GimpImage *image, return psd_layers; } + +gboolean +save_dialog (GimpImage *image, + GimpProcedure *procedure, + GObject *config) +{ + GtkWidget *dialog; + GtkWidget *duotone_notice; + gboolean run; + + dialog = gimp_procedure_dialog_new (procedure, + GIMP_PROCEDURE_CONFIG (config), + _("Export Image as PSD")); + + /* Profile label */ + duotone_notice = gimp_procedure_dialog_get_label (GIMP_PROCEDURE_DIALOG (dialog), + "duotone-notice", + _("Duotone color space information " + "from the original\nimported image " + "will be used.")); + gtk_label_set_xalign (GTK_LABEL (duotone_notice), 0.0); + gtk_label_set_ellipsize (GTK_LABEL (duotone_notice), PANGO_ELLIPSIZE_END); + gimp_label_set_attributes (GTK_LABEL (duotone_notice), + PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, + -1); + + gimp_procedure_dialog_fill_frame (GIMP_PROCEDURE_DIALOG (dialog), + "duotone-frame", "duotone", FALSE, + "duotone-notice"); + + gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), + "duotone-frame", + NULL); + + gtk_widget_show (dialog); + + run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + + return run; +} diff --git a/plug-ins/file-psd/psd-save.h b/plug-ins/file-psd/psd-save.h index a55792ea8b..26d735df74 100644 --- a/plug-ins/file-psd/psd-save.h +++ b/plug-ins/file-psd/psd-save.h @@ -19,9 +19,13 @@ #define __PSD_SAVE_H__ -gboolean save_image (GFile *file, - GimpImage *image, - GError **error); +gboolean save_image (GFile *file, + GimpImage *image, + GObject *config, + GError **error); +gboolean save_dialog (GimpImage *image, + GimpProcedure *procedure, + GObject *config); #endif /* __PSD_SAVE_H__ */ diff --git a/plug-ins/file-psd/psd.c b/plug-ins/file-psd/psd.c index 4e5b60e2f6..14e63872ac 100644 --- a/plug-ins/file-psd/psd.c +++ b/plug-ins/file-psd/psd.c @@ -223,6 +223,13 @@ psd_create_procedure (GimpPlugIn *plug_in, "image/x-psd"); gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), "psd"); + + GIMP_PROC_ARG_BOOLEAN (procedure, "duotone", + "Export as _Duotone", + "Export as a Duotone PSD file if Duotone color space information " + "was attached to the image when originally imported.", + FALSE, + G_PARAM_READWRITE); } return procedure; @@ -240,6 +247,7 @@ psd_load (GimpProcedure *procedure, gboolean profile_loaded = FALSE; GimpImage *image; GimpMetadata *metadata; + GimpParasite *parasite = NULL; GError *error = NULL; gegl_init (NULL, NULL); @@ -266,6 +274,17 @@ psd_load (GimpProcedure *procedure, GIMP_PDB_EXECUTION_ERROR, error); + /* If image was Duotone, notify user of compatibility */ + if (run_mode == GIMP_RUN_INTERACTIVE) + { + parasite = gimp_image_get_parasite (image, PSD_PARASITE_DUOTONE_DATA); + if (parasite) + { + load_dialog (); + gimp_parasite_free (parasite); + } + } + metadata = gimp_image_metadata_load_prepare (image, "image/x-psd", file, NULL); if (metadata) @@ -338,14 +357,21 @@ psd_save (GimpProcedure *procedure, const GimpValueArray *args, gpointer run_data) { + GimpProcedureConfig *config; GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpMetadata *metadata; GimpMetadataSaveFlags metadata_flags; GimpExportReturn export = GIMP_EXPORT_IGNORE; + GimpParasite *parasite = NULL; GError *error = NULL; gegl_init (NULL, NULL); + config = gimp_procedure_create_config (procedure); + metadata = gimp_image_metadata_save_prepare (image, + "image/x-psd", + &metadata_flags); + switch (run_mode) { case GIMP_RUN_INTERACTIVE: @@ -369,11 +395,25 @@ psd_save (GimpProcedure *procedure, break; } - metadata = gimp_image_metadata_save_prepare (image, - "image/x-psd", - &metadata_flags); + if (run_mode == GIMP_RUN_INTERACTIVE) + { + /* Only show dialog if image is grayscale and duotone color space + * information was attached from the original image imported + */ + parasite = gimp_image_get_parasite (image, PSD_PARASITE_DUOTONE_DATA); + if (parasite) + { + if (gimp_image_get_base_type (image) == GIMP_GRAY) + { + if (! save_dialog (image, procedure, G_OBJECT (config))) + return gimp_procedure_new_return_values (procedure, GIMP_PDB_CANCEL, + NULL); + } + gimp_parasite_free (parasite); + } + } - if (save_image (file, image, &error)) + if (save_image (file, image, G_OBJECT (config), &error)) { if (metadata) {