[gimp/wip/Jehan/PSD-multi-layer] plug-ins: multi-layer support in PSD load/export.




commit dc33e101bca2e5ec0f41a2106a08579fe902b3fe
Author: Jehan <jehan girinstud io>
Date:   Sun Feb 21 23:24:54 2021 +0100

    plug-ins: multi-layer support in PSD load/export.

 plug-ins/file-psd/psd-image-res-load.c |  7 ++++--
 plug-ins/file-psd/psd-load.c           | 34 ++++++++++++++++++--------
 plug-ins/file-psd/psd-save.c           | 44 +++++++++++++++++++---------------
 plug-ins/file-psd/psd.h                |  2 +-
 4 files changed, 55 insertions(+), 32 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-image-res-load.c b/plug-ins/file-psd/psd-image-res-load.c
index 7be157e730..9f6ccf1ec1 100644
--- a/plug-ins/file-psd/psd-image-res-load.c
+++ b/plug-ins/file-psd/psd-image-res-load.c
@@ -810,15 +810,18 @@ load_resource_1024 (const PSDimageres  *res_a,
                     FILE               *f,
                     GError            **error)
 {
+  guint16 layer_state;
+
   /* Load image layer state - current active layer counting from bottom up */
   IFDBG(2) g_debug ("Process image resource block: 1024: Layer State");
 
-  if (fread (&img_a->layer_state, 2, 1, f) < 1)
+  if (fread (&layer_state, 2, 1, f) < 1)
     {
       psd_set_error (feof (f), errno, error);
       return -1;
     }
-  img_a->layer_state = GUINT16_FROM_BE (img_a->layer_state);
+  layer_state = GUINT16_FROM_BE (layer_state);
+  img_a->layer_states = g_list_prepend (img_a->layer_states, GINT_TO_POINTER (layer_state));
 
   return 0;
 }
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index e5695f8403..7ecf0334ef 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -1166,7 +1166,7 @@ add_image_resources (GimpImage *image,
 
   /* Initialise image resource variables */
   img_a->no_icc = FALSE;
-  img_a->layer_state = 0;
+  img_a->layer_states = NULL;
   img_a->alpha_names = NULL;
   img_a->alpha_display_info = NULL;
   img_a->alpha_display_count = 0;
@@ -1287,9 +1287,9 @@ add_layers (GimpImage *image,
   gint32                lm_y;                  /* Layer mask y */
   gint32                lm_w;                  /* Layer mask width */
   gint32                lm_h;                  /* Layer mask height */
-  GimpLayer            *layer        = NULL;
-  GimpLayerMask        *mask         = NULL;
-  GimpLayer            *active_layer = NULL;
+  GimpLayer            *layer           = NULL;
+  GimpLayerMask        *mask            = NULL;
+  GList                *selected_layers = NULL;
   gint                  lidx;                  /* Layer index */
   gint                  cidx;                  /* Channel index */
   gint                  rowi;                  /* Row index */
@@ -1660,10 +1660,10 @@ add_layers (GimpImage *image,
                     }
                 }
 
-              /* Remember the active layer ID */
-              if (lidx == img_a->layer_state)
+              /* Remember the selected layers */
+              if (g_list_find (img_a->layer_states, GINT_TO_POINTER (lidx)) != NULL)
                 {
-                  active_layer = layer;
+                  selected_layers = g_list_prepend (selected_layers, layer);
                 }
 
               /* Set the layer data */
@@ -1846,9 +1846,23 @@ add_layers (GimpImage *image,
   g_free (lyr_a);
   g_array_free (parent_group_stack, FALSE);
 
-  /* Set the active layer */
-  if (active_layer != NULL)
-    gimp_image_set_active_layer (image, active_layer);
+  /* Set the selected layers */
+  if (selected_layers)
+    {
+      GimpLayer **sel_layers;
+      GList      *list;
+      gint        i;
+
+      sel_layers = g_new0 (GimpLayer *, g_list_length (selected_layers));
+      for (list = selected_layers, i = 0; list; list = list->next, i++)
+        sel_layers[i] = list->data;
+      gimp_image_set_selected_layers (image, g_list_length (selected_layers),
+                                      (const GimpLayer **) sel_layers);
+
+      g_list_free (selected_layers);
+      g_free (sel_layers);
+    }
+  g_list_free (img_a->layer_states);
 
   return 0;
 }
diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c
index 97b5194fe5..bced384ea4 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -603,9 +603,8 @@ save_resources (FILE      *fd,
   GList        *iter;
   gint          i;
   gchar        *fileName;            /* Image file name */
-  GimpLayer    *ActLayer;            /* The active layer */
-  guint         nActiveLayer = 0;    /* Number of the active layer */
-  gboolean      ActiveLayerPresent;  /* TRUE if there's an active layer */
+  GList        *SelLayers;           /* The selected layers */
+  GList        *nSelLayers = NULL;   /* Numbers of the selected layers */
 
   glong         eof_pos;             /* Position for End of file */
   glong         rsc_pos;             /* Position for Lengths of Resources section */
@@ -624,35 +623,41 @@ save_resources (FILE      *fd,
   fileName = g_file_get_path (gimp_image_get_file (image));
   IFDBG printf ("\tImage title: %s\n", fileName);
 
-  /* Get the active layer number id */
+  /* Get the selected layers */
 
-  ActLayer = gimp_image_get_active_layer (image);
-  IFDBG printf ("\tCurrent layer id: %d\n",
-                gimp_item_get_id (GIMP_ITEM (ActLayer)));
+  SelLayers = gimp_image_list_selected_layers (image);
+
+  IFDBG printf ("\tSelected layer ids:");
+  IFDBG for (iter = SelLayers; iter; iter = iter->next)
+    IFDBG printf (" %d", gimp_item_get_id (GIMP_ITEM (iter->data)));
+  IFDBG printf ("\n");
 
-  ActiveLayerPresent = FALSE;
   for (iter = PSDImageData.lLayers, i = 0;
        iter;
        iter = g_list_next (iter), i++)
     {
-      if (ActLayer == ((PSD_Layer *) iter->data)->layer)
+      if (g_list_find (SelLayers, ((PSD_Layer *) iter->data)->layer) != NULL)
         {
-          nActiveLayer = PSDImageData.nLayers - i - 1;
-          ActiveLayerPresent = TRUE;
-          break;
+          /* Map layers to their index in PSD. */
+          nSelLayers = g_list_prepend (nSelLayers,
+                                       GINT_TO_POINTER (PSDImageData.nLayers - i - 1));
+          if (g_list_length (nSelLayers) == g_list_length (SelLayers))
+            break;
         }
     }
+  g_list_free (SelLayers);
 
-  if (ActiveLayerPresent)
+  if (nSelLayers)
     {
-      IFDBG printf ("\t\tActive layer is number %d\n", nActiveLayer);
+      IFDBG printf ("\t\tSelected layers are numbers:");
+      IFDBG for (iter = nSelLayers; iter; iter = iter->next)
+        IFDBG printf (" %d", GPOINTER_TO_INT (iter->data));
     }
   else
     {
-      IFDBG printf ("\t\tNo active layer\n");
+      IFDBG printf ("\t\tNo selected layers\n");
     }
 
-
   /* Here's where actual writing starts */
 
   rsc_pos = ftell (fd);
@@ -848,9 +853,9 @@ save_resources (FILE      *fd,
     write_gint16 (fd, psd_unit, "height unit");
   }
 
-  /* --------------- Write Active Layer Number --------------- */
+  /* --------------- Write Selected Layer Number --------------- */
 
-  if (ActiveLayerPresent)
+  for (iter = nSelLayers; iter; iter = iter->next)
     {
       xfwrite (fd, "8BIM", 4, "imageresources signature");
       write_gint16 (fd, 0x0400, "0x0400 Id"); /* 1024 */
@@ -860,10 +865,11 @@ save_resources (FILE      *fd,
 
       /* Save title as gint16 (length always even) */
 
-      write_gint16 (fd, nActiveLayer, "active layer");
+      write_gint16 (fd, GPOINTER_TO_INT (iter->data), "active layer");
 
       IFDBG printf ("\tTotal length of 0x0400 resource: %d\n", (int) sizeof (gint16));
     }
+  g_list_free (nSelLayers);
 
   /* --------------- Write ICC profile data ------------------- */
   {
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index b2fe6d885f..e2a74f77aa 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -668,7 +668,7 @@ typedef struct
   guint32               merged_image_start;     /* Merged image pixel data block start address */
   guint32               merged_image_len;       /* Merged image pixel data block length */
   gboolean              no_icc;                 /* Do not use ICC profile */
-  guint16               layer_state;            /* Active layer number counting from bottom up */
+  GList                *layer_states;           /* Selected layer numbers counting from bottom up */
   GPtrArray            *alpha_names;            /* Alpha channel names */
   PSDchanneldata      **alpha_display_info;     /* Alpha channel display info */
   guint16               alpha_display_count;    /* Number of alpha channel display info recs */


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