[gimp/alxsa-duotone-psd-export] plug-ins: Enable export of original Duotone data



commit e0aa5b31f6829a3fa9727d8b23054697c8ea6e5c
Author: Alx Sa <cmyk student gmail com>
Date:   Sun Jul 24 16:36:35 2022 +0000

    plug-ins: Enable export of original Duotone data
    
    Optionally includes the previously saved
    Duotone color space data on PSD export.
    New load dialogue alerts user if duotone data was imported.
    New export dialogue appears if the image is still grayscale and
    the parasite exists.
    If selected, the mode is set to PSD_DUOTONE in the header and
    the original duotone data is written in the color space section.

 plug-ins/file-psd/psd-load.c |  48 +++++++++++++++++++
 plug-ins/file-psd/psd-load.h |  12 +++--
 plug-ins/file-psd/psd-save.c | 112 ++++++++++++++++++++++++++++++++++++++-----
 plug-ins/file-psd/psd-save.h |  10 ++--
 plug-ins/file-psd/psd.c      |  48 +++++++++++++++++--
 5 files changed, 207 insertions(+), 23 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 3ead2ff199..816d015bf4 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -26,6 +26,7 @@
 #include <glib/gstdio.h>
 #include <zlib.h>
 #include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
 
 #include "psd.h"
 #include "psd-util.h"
@@ -3221,3 +3222,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 ("<b>%s</b>\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..279bbc0a46 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -132,10 +132,12 @@ 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);
@@ -524,7 +526,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 +548,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, &parasite_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:
@@ -1754,12 +1779,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 +1809,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,8 +1876,8 @@ 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_header (output, image, config_duotone);
+  save_color_mode_data (output, image, config_duotone);
   save_resources (output, image);
 
   /* PSD format does not support layers in indexed images */
@@ -2025,3 +2073,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)
         {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]