Commit 0f0e63ff authored by Jehan's avatar Jehan
Browse files

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

- Store the Layer ID (lyid) block. Use GIMP's layer tattoo as a PSD
  layer ID, hence mirroring PSD load processing (we were already reading
  this block into our layer tattoos but always exporting with no ID).
- Add support for the Layer Selection ID(s) block (0x042D) both on
  import and export in order to store and restore the multi-layer
  selection.
  We were previously using the Layer state information block (0x0400) to
  store the active layer, but it doesn't seem to be usable for multiple
  layer selection. Actually it is even doubtful if this was working fine
  even for single layer selection but I can't be sure (I could only test
  in non-Photoshop software available to me). So the new logics is:
  * If more than 1 layer is selected, store only the Layer Selection
    ID(s) block.
  * If exactly 1 layer is selected, store both the Layer Selection ID(s)
    and Layer state information blocks.
  * Otherwise (no layers selected) do not store any of these blocks.
parent d9840893
Pipeline #260452 passed with stages
in 36 minutes and 34 seconds
......@@ -223,6 +223,12 @@ static gint load_resource_1058 (const PSDimageres *res_a,
FILE *f,
GError **error);
static gint load_resource_1069 (const PSDimageres *res_a,
GimpImage *image,
PSDimage *img_a,
FILE *f,
GError **error);
static gint load_resource_1077 (const PSDimageres *res_a,
GimpImage *image,
PSDimage *img_a,
......@@ -391,6 +397,11 @@ load_image_resource (PSDimageres *res_a,
load_resource_1058 (res_a, image, f, error);
break;
case PSD_LAYER_SELECT_ID:
if (! img_a->merged_image_only)
load_resource_1069 (res_a, image, img_a, f, error);
break;
case PSD_XMP_DATA:
break;
......@@ -1298,6 +1309,47 @@ load_resource_1058 (const PSDimageres *res_a,
return 0;
}
static gint
load_resource_1069 (const PSDimageres *res_a,
GimpImage *image,
PSDimage *img_a,
FILE *f,
GError **error)
{
guint16 layer_count;
gint i;
IFDBG(2) g_debug ("Process image resource block: 1069: Layer Selection ID(s)");
if (fread (&layer_count, 2, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
layer_count = GUINT16_FROM_BE (layer_count);
/* This should probably not happen, but just in case the block is
* duplicated, let's just free the previous selection.
*/
g_list_free (img_a->layer_selection);
img_a->layer_selection = NULL;
for (i = 0; i < layer_count; i++)
{
guint32 layer_id;
if (fread (&layer_id, 4, 1, f) < 1)
{
psd_set_error (feof (f), errno, error);
return -1;
}
layer_id = GUINT32_FROM_BE (layer_id);
img_a->layer_selection = g_list_prepend (img_a->layer_selection, GINT_TO_POINTER (layer_id));
}
return 0;
}
static gint
load_resource_1077 (const PSDimageres *res_a,
GimpImage *image,
......
......@@ -1167,6 +1167,7 @@ add_image_resources (GimpImage *image,
/* Initialise image resource variables */
img_a->no_icc = FALSE;
img_a->layer_state = 0;
img_a->layer_selection = NULL;
img_a->alpha_names = NULL;
img_a->alpha_display_info = NULL;
img_a->alpha_display_count = 0;
......@@ -1287,9 +1288,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 +1661,21 @@ add_layers (GimpImage *image,
}
}
/* Remember the active layer ID */
if (lidx == img_a->layer_state)
/* Remember the selected layers:
* - Layer Selection ID(s) (0x042D) are prioritary;
* - Layer state information (0x0400) is used instead
* otherwise.
*/
if (img_a->layer_selection)
{
active_layer = layer;
if (g_list_find (img_a->layer_selection, GINT_TO_POINTER (lyr_a[lidx]->id)) != NULL)
{
selected_layers = g_list_prepend (selected_layers, layer);
}
}
else if (lidx == img_a->layer_state)
{
selected_layers = g_list_prepend (selected_layers, layer);
}
/* Set the layer data */
......@@ -1846,9 +1858,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_selection);
return 0;
}
......
......@@ -603,9 +603,7 @@ 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 */
glong eof_pos; /* Position for End of file */
glong rsc_pos; /* Position for Lengths of Resources section */
......@@ -624,34 +622,9 @@ 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 */
ActLayer = gimp_image_get_active_layer (image);
IFDBG printf ("\tCurrent layer id: %d\n",
gimp_item_get_id (GIMP_ITEM (ActLayer)));
ActiveLayerPresent = FALSE;
for (iter = PSDImageData.lLayers, i = 0;
iter;
iter = g_list_next (iter), i++)
{
if (ActLayer == ((PSD_Layer *) iter->data)->layer)
{
nActiveLayer = PSDImageData.nLayers - i - 1;
ActiveLayerPresent = TRUE;
break;
}
}
if (ActiveLayerPresent)
{
IFDBG printf ("\t\tActive layer is number %d\n", nActiveLayer);
}
else
{
IFDBG printf ("\t\tNo active layer\n");
}
/* Get the selected layers */
SelLayers = gimp_image_list_selected_layers (image);
/* Here's where actual writing starts */
......@@ -848,22 +821,53 @@ save_resources (FILE *fd,
write_gint16 (fd, psd_unit, "height unit");
}
/* --------------- Write Active Layer Number --------------- */
/* --------------- Write Selected Layers --------------- */
if (ActiveLayerPresent)
if (SelLayers)
{
xfwrite (fd, "8BIM", 4, "imageresources signature");
write_gint16 (fd, 0x0400, "0x0400 Id"); /* 1024 */
/* write_pascalstring (fd, Name, "Id name"); */
write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
write_gint32 (fd, sizeof (gint16), "0x0400 resource size");
if (g_list_length (SelLayers) == 1)
{
/* Write the Layer State Information (0x0400) if and only if
* there is exactly one selected layer.
* Unless mistaken, this block does not seem used for multiple
* layer selected. It seems anyway redundant with the Layer
* Selection ID(s) block (0x042D) which is more recent
* (Photoshop CS2) but it's probably a good idea to store both
* information.
*/
for (iter = PSDImageData.lLayers, i = 0;
iter;
iter = g_list_next (iter), i++)
{
if (SelLayers->data == ((PSD_Layer *) iter->data)->layer)
{
xfwrite (fd, "8BIM", 4, "imageresources signature");
write_gint16 (fd, 0x0400, "0x0400 Id"); /* 1024 */
/* write_pascalstring (fd, Name, "Id name"); */
write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
write_gint32 (fd, sizeof (gint16), "0x0400 resource size");
/* Save title as gint16 (length always even) */
/* Layer State Information uses the layer index. */
write_gint16 (fd, PSDImageData.nLayers - i - 1, "active layer");
write_gint16 (fd, nActiveLayer, "active layer");
IFDBG printf ("\tTotal length of 0x0400 resource: %d\n", (int) sizeof (gint16));
break;
}
}
}
IFDBG printf ("\tTotal length of 0x0400 resource: %d\n", (int) sizeof (gint16));
/* Write the Layer Selection ID(s) block when there is at least
* one selected layer or more.
*/
xfwrite (fd, "8BIM", 4, "imageresources signature");
write_gint16 (fd, 0x042D, "0x042D Id"); /* 1069 */
write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
write_gint32 (fd, sizeof (gint16) + sizeof (gint32) * g_list_length (SelLayers), "0x0400 resource size");
write_gint16 (fd, g_list_length (SelLayers), "2 bytes count");
for (iter = SelLayers; iter; iter = iter->next)
write_gint32 (fd, GPOINTER_TO_INT (gimp_item_get_tattoo (iter->data)), "4 bytes layer ID");
}
g_list_free (SelLayers);
/* --------------- Write ICC profile data ------------------- */
{
......@@ -1213,6 +1217,11 @@ save_layer_and_mask (FILE *fd,
g_free (layerName);
/* Layer ID */
xfwrite (fd, "8BIMlyid", 8, "lyid signature");
write_gint32 (fd, 4, "lyid size");
write_gint32 (fd, gimp_item_get_tattoo (GIMP_ITEM (psd_layer->layer)), "Layer ID");
/* Layer color tag */
xfwrite (fd, "8BIMlclr", 8, "sheet color signature");
write_gint32 (fd, 8, "sheet color size");
......
......@@ -668,7 +668,8 @@ 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 */
guint16 layer_state; /* Active layer index counting from bottom up */
GList *layer_selection; /* Selected layer IDs (GIMP layer tattoos) */
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 */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment