[gimp] plug-ins: in file-psd, read and write group-layer masks



commit af6b891b648da83e02d1a6d4820c951047702715
Author: Ell <ell_se yahoo com>
Date:   Mon Feb 5 16:20:01 2018 -0500

    plug-ins: in file-psd, read and write group-layer masks
    
    Add support for loading and saving group-layer masks from/to PSD
    files.

 plug-ins/file-psd/psd-load.c |    7 ++-
 plug-ins/file-psd/psd-save.c |  202 +++++++++++++++++++++++------------------
 2 files changed, 119 insertions(+), 90 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index ddcafd1..2533172 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -1399,6 +1399,11 @@ add_layers (gint32     image_id,
                        */
                       g_array_remove_index (parent_group_stack,
                                             parent_group_stack->len - 1);
+
+                      gimp_drawable_offsets (layer_id, &l_x, &l_y);
+
+                      l_w = gimp_drawable_width  (layer_id);
+                      l_h = gimp_drawable_height (layer_id);
                     }
                   else
                     {
@@ -1529,7 +1534,7 @@ add_layers (gint32     image_id,
                 }
 
               /* Layer mask */
-              if (user_mask && lyr_a[lidx]->group_type == 0)
+              if (user_mask && lyr_a[lidx]->group_type != 3)
                 {
                   if (empty_mask)
                     {
diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c
index ce66081..fa73523 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -191,7 +191,8 @@ static void          write_datablock_luni (FILE          *fd,
 static void          write_pixel_data     (FILE          *fd,
                                            gint32         drawableID,
                                            glong         *ChanLenPosition,
-                                           gint32         rowlenOffset);
+                                           gint32         rowlenOffset,
+                                           gboolean       write_mask);
 
 static gint32        create_merged_image  (gint32         imageID);
 
@@ -959,7 +960,8 @@ save_layer_and_mask (FILE   *fd,
       write_gint32 (fd, offset_y + layerHeight, "Layer bottom");
       write_gint32 (fd, offset_x + layerWidth,  "Layer right");
 
-      hasMask = (gimp_layer_get_mask(PSDImageData.lLayers[i].id) == -1 ) ? 0 : 1;
+      hasMask = (PSDImageData.lLayers[i].type != PSD_LAYER_TYPE_GROUP_END &&
+                 gimp_layer_get_mask (PSDImageData.lLayers[i].id) != -1);
       nChannelsLayer = nChansLayer (PSDImageData.baseType,
                                     gimp_drawable_has_alpha (PSDImageData.lLayers[i].id),
                                     hasMask);
@@ -1022,25 +1024,34 @@ save_layer_and_mask (FILE   *fd,
       ExtraDataPos = ftell (fd); /* Position of Extra Data size */
       write_gint32 (fd, 0, "Extra data size");
 
-      mask = gimp_layer_get_mask (PSDImageData.lLayers[i].id);
-      if (mask  >= 0)
+      if (hasMask)
         {
-          gint     maskWidth  = gimp_drawable_width (mask);
-          gint     maskHeight = gimp_drawable_height (mask);
-          gboolean apply      = gimp_layer_get_apply_mask (PSDImageData.lLayers[i].id);
+          gint     maskOffset_x;
+          gint     maskOffset_y;
+          gint     maskWidth;
+          gint     maskHeight;
+          gboolean apply;
+
+          mask = gimp_layer_get_mask (PSDImageData.lLayers[i].id);
+
+          gimp_drawable_offsets (mask, &maskOffset_x, &maskOffset_y);
+
+          maskWidth  = gimp_drawable_width  (mask);
+          maskHeight = gimp_drawable_height (mask);
+          apply      = gimp_layer_get_apply_mask (PSDImageData.lLayers[i].id);
 
           IFDBG printf ("\t\tLayer mask size: %d\n", 20);
-          write_gint32 (fd, 20,                    "Layer mask size");
-          write_gint32 (fd, offset_y,              "Layer mask top");
-          write_gint32 (fd, offset_x,              "Layer mask left");
-          write_gint32 (fd, offset_y + maskHeight, "Layer mask bottom");
-          write_gint32 (fd, offset_x + maskWidth,  "Layer mask right");
-          write_gchar  (fd, 0,                     "Layer mask default color");
+          write_gint32 (fd, 20,                        "Layer mask size");
+          write_gint32 (fd, maskOffset_y,              "Layer mask top");
+          write_gint32 (fd, maskOffset_x,              "Layer mask left");
+          write_gint32 (fd, maskOffset_y + maskHeight, "Layer mask bottom");
+          write_gint32 (fd, maskOffset_x + maskWidth,  "Layer mask right");
+          write_gchar  (fd, 0,                         "Layer mask default color");
           flags = (0                    |  /* position relative to layer */
                    (apply ? 0 : 1) << 1 |  /* layer mask disabled        */
                    0 << 2);                /* invert layer mask          */
-          write_gchar  (fd, flags,                 "Layer mask flags");
-          write_gint16 (fd, 0,                     "Layer mask Padding");
+          write_gchar  (fd, flags,                     "Layer mask flags");
+          write_gint16 (fd, 0,                         "Layer mask Padding");
         }
       else
         {
@@ -1140,7 +1151,8 @@ save_layer_and_mask (FILE   *fd,
       gimp_progress_update ((PSDImageData.nLayers - i - 1.0) / (PSDImageData.nLayers + 1.0));
 
       IFDBG printf ("\t\tWriting pixel data for layer slot %d\n", i);
-      write_pixel_data(fd, PSDImageData.lLayers[i].id, ChannelLengthPos[i], 0);
+      write_pixel_data (fd, PSDImageData.lLayers[i].id, ChannelLengthPos[i], 0,
+                        PSDImageData.lLayers[i].type != PSD_LAYER_TYPE_GROUP_END);
       g_free (ChannelLengthPos[i]);
     }
 
@@ -1167,13 +1179,15 @@ save_layer_and_mask (FILE   *fd,
 }
 
 static void
-write_pixel_data (FILE   *fd,
-                  gint32  drawableID,
-                  glong  *ChanLenPosition,
-                  gint32  ltable_offset)
+write_pixel_data (FILE     *fd,
+                  gint32    drawableID,
+                  glong    *ChanLenPosition,
+                  gint32    ltable_offset,
+                  gboolean  write_mask)
 {
   GeglBuffer   *buffer = gimp_drawable_get_buffer (drawableID);
   const Babl   *format;
+  gint32        maskID;
   gint32        tile_height = gimp_tile_height ();
   gint32        height = gegl_buffer_get_height (buffer);
   gint32        width  = gegl_buffer_get_width (buffer);
@@ -1190,8 +1204,13 @@ write_pixel_data (FILE   *fd,
   IFDBG printf (" Function: write_pixel_data, drw %d, lto %d\n",
                 drawableID, ltable_offset);
 
-  /* groups have empty channel data */
-  if (gimp_item_is_group (drawableID))
+  if (write_mask)
+    maskID = gimp_layer_get_mask (drawableID);
+  else
+    maskID = -1;
+
+  /* groups have empty channel data, but may have a mask */
+  if (gimp_item_is_group (drawableID) && maskID == -1)
     {
       width  = 0;
       height = 0;
@@ -1216,6 +1235,13 @@ write_pixel_data (FILE   *fd,
 
   data = g_new (guchar, MIN (height, tile_height) * width * bytes);
 
+  /* groups have empty channel data */
+  if (gimp_item_is_group (drawableID))
+    {
+      width  = 0;
+      height = 0;
+    }
+
   for (i = 0; i < bytes; i++)
     {
       gint chan;
@@ -1294,81 +1320,79 @@ write_pixel_data (FILE   *fd,
     }
 
   /* Write layer mask, as last channel, id -2 */
-  if (gimp_item_is_layer (drawableID))
+  if (maskID != -1)
     {
-      gint32 maskID = gimp_layer_get_mask (drawableID);
-
-      if (maskID != -1)
-        {
-          GeglBuffer *mbuffer = gimp_drawable_get_buffer (maskID);
-          const Babl  *mformat = get_mask_format(maskID);
+      GeglBuffer *mbuffer = gimp_drawable_get_buffer (maskID);
+      const Babl *mformat = get_mask_format(maskID);
 
-          len = 0;
+      width  = gegl_buffer_get_width (buffer);
+      height = gegl_buffer_get_height (buffer);
 
-          if (ChanLenPosition)
-            {
-              write_gint16 (fd, 1, "Compression type (RLE)");
-              len += 2;
-              IF_DEEP_DBG printf ("\t\t\t\t. ChanLenPos, len %d\n", len);
-            }
+      len = 0;
 
-          if (ltable_offset > 0)
-            {
-              length_table_pos = ltable_offset + 2 * (bytes+1) * height;
-              IF_DEEP_DBG printf ("\t\t\t\t. ltable, pos %ld\n",
-                                  length_table_pos);
-            }
-          else
-            {
-              length_table_pos = ftell(fd);
+      if (ChanLenPosition)
+        {
+          write_gint16 (fd, 1, "Compression type (RLE)");
+          len += 2;
+          IF_DEEP_DBG printf ("\t\t\t\t. ChanLenPos, len %d\n", len);
+        }
 
-              xfwrite (fd, LengthsTable, height * sizeof(gint16),
-                       "Dummy RLE length");
-              len += height * sizeof(gint16);
-              IF_DEEP_DBG printf ("\t\t\t\t. ltable, pos %ld len %d\n",
-                                  length_table_pos, len);
-            }
+      if (ltable_offset > 0)
+        {
+          length_table_pos = ltable_offset + 2 * (bytes+1) * height;
+          IF_DEEP_DBG printf ("\t\t\t\t. ltable, pos %ld\n",
+                              length_table_pos);
+        }
+      else
+        {
+          length_table_pos = ftell(fd);
 
-          for (y = 0; y < height; y += tile_height)
-            {
-              int tlen;
-              gegl_buffer_get (mbuffer,
-                               GEGL_RECTANGLE (0, y,
-                                               width,
-                                               MIN (height - y, tile_height)),
-                               1.0, mformat, data,
-                               GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-              tlen = get_compress_channel_data (&data[0],
-                                                width,
-                                                MIN(height - y, tile_height),
-                                                1,
-                                                &LengthsTable[y],
-                                                rledata);
-              len += tlen;
-              xfwrite (fd, rledata, tlen, "Compressed mask data");
-              IF_DEEP_DBG printf ("\t\t\t\t. Writing compressed mask, stream of %d\n", tlen);
-            }
+          xfwrite (fd, LengthsTable, height * sizeof(gint16),
+                   "Dummy RLE length");
+          len += height * sizeof(gint16);
+          IF_DEEP_DBG printf ("\t\t\t\t. ltable, pos %ld len %d\n",
+                              length_table_pos, len);
+        }
 
-          /* Write compressed lengths table */
-          fseek (fd, length_table_pos, SEEK_SET); /*POS WHERE???*/
-          for (j = 0; j < height; j++) /* write real length table */
-            {
-              write_gint16 (fd, LengthsTable[j], "RLE length");
-              IF_DEEP_DBG printf ("\t\t\t\t. Updating RLE len %d\n",
-                                  LengthsTable[j]);
-            }
+      for (y = 0; y < height; y += tile_height)
+        {
+          int tlen;
+          gegl_buffer_get (mbuffer,
+                           GEGL_RECTANGLE (0, y,
+                                           width,
+                                           MIN (height - y, tile_height)),
+                           1.0, mformat, data,
+                           GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+          tlen = get_compress_channel_data (&data[0],
+                                            width,
+                                            MIN(height - y, tile_height),
+                                            1,
+                                            &LengthsTable[y],
+                                            rledata);
+          len += tlen;
+          xfwrite (fd, rledata, tlen, "Compressed mask data");
+          IF_DEEP_DBG printf ("\t\t\t\t. Writing compressed mask, stream of %d\n", tlen);
+        }
 
-          if (ChanLenPosition)    /* Update total compressed length */
-            {
-              fseek (fd, ChanLenPosition[bytes], SEEK_SET); /*+bytes OR SOMETHING*/
-              write_gint32 (fd, len, "channel data length");
-              IFDBG printf ("\t\tUpdating data len to %d, at %ld\n", len, ftell(fd));
-            }
-          fseek (fd, 0, SEEK_END);
-          IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", ftell(fd));
+      /* Write compressed lengths table */
+      fseek (fd, length_table_pos, SEEK_SET); /*POS WHERE???*/
+      for (j = 0; j < height; j++) /* write real length table */
+        {
+          write_gint16 (fd, LengthsTable[j], "RLE length");
+          IF_DEEP_DBG printf ("\t\t\t\t. Updating RLE len %d\n",
+                              LengthsTable[j]);
+        }
 
-          g_object_unref (mbuffer);
+      if (ChanLenPosition)    /* Update total compressed length */
+        {
+          fseek (fd, ChanLenPosition[bytes], SEEK_SET); /*+bytes OR SOMETHING*/
+          write_gint32 (fd, len, "channel data length");
+          IFDBG printf ("\t\tUpdating data len to %d, at %ld\n", len, ftell(fd));
         }
+      fseek (fd, 0, SEEK_END);
+      IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", ftell(fd));
+
+      g_object_unref (mbuffer);
     }
 
   g_object_unref (buffer);
@@ -1409,7 +1433,7 @@ save_data (FILE   *fd,
 
   IFDBG printf ("\t\tWriting compressed image data\n");
   write_pixel_data (fd, PSDImageData.merged_layer,
-                    NULL, offset);
+                    NULL, offset, FALSE);
 
   chan = nChansLayer (PSDImageData.baseType,
                       gimp_drawable_has_alpha(PSDImageData.merged_layer), 0);
@@ -1419,7 +1443,7 @@ save_data (FILE   *fd,
       IFDBG printf ("\t\tWriting compressed channel data for channel %d\n",
                     i);
       write_pixel_data (fd, PSDImageData.lChannels[i], NULL,
-                        offset + 2*imageHeight*chan); //check how imgs are channels here
+                        offset + 2*imageHeight*chan, FALSE); //check how imgs are channels here
       chan++;
     }
 }


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