[gimp] Bug 569550 - Can not handle PSD layers/groups
- From: Mikael Magnusson <mikachu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 569550 - Can not handle PSD layers/groups
- Date: Mon, 23 May 2011 18:03:48 +0000 (UTC)
commit ba324c06f54ad351f1fd22193a9a97ea63b08fb1
Author: Dave Lichterman <laviddichterman gmail com>
Date: Fri Apr 8 02:38:40 2011 -0700
Bug 569550 - Can not handle PSD layers/groups
Add support to file-psd plugin for layer group reading.
plug-ins/file-psd/psd-layer-res-load.c | 30 ++++----------
plug-ins/file-psd/psd-load.c | 68 +++++++++++++++++++++++++++++--
plug-ins/file-psd/psd.h | 5 +-
3 files changed, 74 insertions(+), 29 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-layer-res-load.c b/plug-ins/file-psd/psd-layer-res-load.c
index 8249c96..f98377f 100644
--- a/plug-ins/file-psd/psd-layer-res-load.c
+++ b/plug-ins/file-psd/psd-layer-res-load.c
@@ -72,8 +72,8 @@
* Other *
PSD_LOTH_PATTERN "Patt" - * Patterns (PS6) *
PSD_LOTH_GRADIENT "grdm" - * Gradient settings (PS6) *
- PSD_LOTH_SECTION "lsct" Drop Layer * Section divider setting (PS6) (Layer Groups) *
- PSD_LOTH_RESTRICT "brst" - * Channel blending restirction setting (PS6) *
+ PSD_LOTH_SECTION "lsct" Loaded * Section divider setting (PS6) (Layer Groups) *
+ PSD_LOTH_RESTRICT "brst" - * Channel blending restriction setting (PS6) *
PSD_LOTH_FOREIGN_FX "ffxi" - * Foreign effect ID (PS6) *
PSD_LOTH_PATT_DATA "shpa" - * Pattern data (PS6) *
PSD_LOTH_META_DATA "shmd" - * Meta data setting (PS6) *
@@ -452,8 +452,11 @@ load_resource_lsct (const PSDlayerres *res_a,
FILE *f,
GError **error)
{
- /* Load adjustment layer */
- static gboolean msg_flag = FALSE;
+ /* Load layer group & type information
+ * Type 0: not a group
+ * Type 1: Open folder
+ * Type 2: Closed folder
+ * Type 3: End of most recent group */
guint32 type;
IFDBG(2) g_debug ("Process layer resource block %.4s: Section divider", res_a->key);
@@ -465,24 +468,7 @@ load_resource_lsct (const PSDlayerres *res_a,
type = GUINT32_FROM_BE (type);
IFDBG(3) g_debug ("Section divider type: %i", type);
- if (type == 1 || /* Layer group start - open folder */
- type == 2) /* Layer group start - closed folder */
- {
- lyr_a->drop = TRUE;
- if (! msg_flag && CONVERSION_WARNINGS)
- {
- g_message ("Warning:\n"
- "The image file contains layer groups. "
- "These are not supported by the GIMP and will "
- "be dropped.");
- msg_flag = TRUE;
- }
- }
-
- if (type == 3) /* End of layer group - hidden in UI */
- lyr_a->drop = TRUE;
-
-
+ lyr_a->group_type = type;
return 0;
}
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 969a266..3529bae 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -531,6 +531,7 @@ read_layer_block (PSDimage *img_a,
/* Initialise record */
lyr_a[lidx]->drop = FALSE;
lyr_a[lidx]->id = 0;
+ lyr_a[lidx]->group_type = 0;
if (fread (&lyr_a[lidx]->top, 4, 1, f) < 1
|| fread (&lyr_a[lidx]->left, 4, 1, f) < 1
@@ -1012,6 +1013,8 @@ add_layers (const gint32 image_id,
GError **error)
{
PSDchannel **lyr_chn;
+ GArray *parent_group_stack;
+ gint32 parent_group_id = -1;
guchar *pixels;
guint16 alpha_chn;
guint16 user_mask_chn;
@@ -1059,6 +1062,10 @@ add_layers (const gint32 image_id,
return -1;
}
+ /* set the root of the group hierarchy */
+ parent_group_stack = g_array_new (FALSE, FALSE, sizeof(gint32));
+ g_array_append_val (parent_group_stack, parent_group_id);
+
for (lidx = 0; lidx < img_a->num_layers; ++lidx)
{
IFDBG(2) g_debug ("Process Layer No %d.", lidx);
@@ -1079,9 +1086,28 @@ add_layers (const gint32 image_id,
g_free (lyr_a[lidx]->chn_info);
g_free (lyr_a[lidx]->name);
}
-
else
{
+ if (lyr_a[lidx]->group_type != 0)
+ {
+ if (lyr_a[lidx]->group_type == 3)
+ {
+ /* the </Layer group> marker layers are used to
+ assemble the layer structure in a single pass */
+ layer_id = gimp_layer_group_new (image_id);
+ }
+ else /* group-type == 1 || group_type == 2 */
+ {
+ layer_id = g_array_index (parent_group_stack, gint32,
+ parent_group_stack->len-1);
+ /* since the layers are stored in reverse, the group
+ layer start marker actually means we're done with
+ that layer group */
+ g_array_remove_index (parent_group_stack,
+ parent_group_stack->len-1);
+ }
+ }
+
/* Empty layer */
if (lyr_a[lidx]->bottom - lyr_a[lidx]->top == 0
|| lyr_a[lidx]->right - lyr_a[lidx]->left == 0)
@@ -1221,6 +1247,8 @@ add_layers (const gint32 image_id,
l_y = 0;
l_w = img_a->columns;
l_h = img_a->rows;
+ parent_group_id = g_array_index (parent_group_stack, gint32,
+ parent_group_stack->len-1);
IFDBG(3) g_debug ("Re-hash channel indices");
for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx)
@@ -1247,7 +1275,36 @@ add_layers (const gint32 image_id,
layer_channels++;
}
- if (empty)
+ if (lyr_a[lidx]->group_type != 0)
+ {
+ if (lyr_a[lidx]->group_type == 3)
+ {
+ IFDBG(2) g_debug ("Create placeholder group layer");
+ g_free (lyr_a[lidx]->name);
+ gimp_image_insert_layer (image_id, layer_id, parent_group_id, 0);
+ /* add this group layer as the new parent */
+ g_array_append_val (parent_group_stack, layer_id);
+ }
+ else
+ {
+ IFDBG(2) g_debug ("End group layer id %d.", layer_id);
+ drawable = gimp_drawable_get (layer_id);
+ layer_mode = psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode);
+ gimp_layer_set_mode (layer_id, layer_mode);
+ gimp_layer_set_opacity (layer_id,
+ lyr_a[lidx]->opacity * 100 / 255);
+ gimp_item_set_name (drawable->drawable_id, lyr_a[lidx]->name);
+ g_free (lyr_a[lidx]->name);
+ gimp_item_set_visible (drawable->drawable_id,
+ lyr_a[lidx]->layer_flags.visible);
+ if (lyr_a[lidx]->id)
+ gimp_item_set_tattoo (drawable->drawable_id,
+ lyr_a[lidx]->id);
+ gimp_drawable_flush (drawable);
+ gimp_drawable_detach (drawable);
+ }
+ }
+ else if (empty)
{
IFDBG(2) g_debug ("Create blank layer");
image_type = get_gimp_image_type (img_a->base_type, TRUE);
@@ -1255,7 +1312,7 @@ add_layers (const gint32 image_id,
img_a->columns, img_a->rows,
image_type, 0, GIMP_NORMAL_MODE);
g_free (lyr_a[lidx]->name);
- gimp_image_insert_layer (image_id, layer_id, -1, -1);
+ gimp_image_insert_layer (image_id, layer_id, parent_group_id, -1);
drawable = gimp_drawable_get (layer_id);
gimp_drawable_fill (drawable->drawable_id, GIMP_TRANSPARENT_FILL);
gimp_item_set_visible (drawable->drawable_id, lyr_a[lidx]->layer_flags.visible);
@@ -1292,7 +1349,7 @@ add_layers (const gint32 image_id,
layer_mode);
IFDBG(3) g_debug ("Layer tattoo: %d", layer_id);
g_free (lyr_a[lidx]->name);
- gimp_image_insert_layer (image_id, layer_id, -1, -1);
+ gimp_image_insert_layer (image_id, layer_id, parent_group_id, -1);
gimp_layer_set_offsets (layer_id, l_x, l_y);
gimp_layer_set_lock_alpha (layer_id, lyr_a[lidx]->layer_flags.trans_prot);
drawable = gimp_drawable_get (layer_id);
@@ -1309,7 +1366,7 @@ add_layers (const gint32 image_id,
}
/* Layer mask */
- if (user_mask)
+ if (user_mask && lyr_a[lidx]->group_type == 0)
{
if (empty_mask)
{
@@ -1421,6 +1478,7 @@ add_layers (const gint32 image_id,
g_free (lyr_a[lidx]);
}
g_free (lyr_a);
+ g_array_free (parent_group_stack, FALSE);
return 0;
}
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index e07c7b6..926c349 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -115,10 +115,10 @@
#define PSD_LPAR_ANNOTATE "Anno" /* Annotation (PS6) */
/* Other */
-#define PSD_LOTH_SECTION "lsct" /* Section divider setting - Layer goups (PS6) */
+#define PSD_LOTH_SECTION "lsct" /* Section divider setting - Layer groups (PS6) */
#define PSD_LOTH_PATTERN "Patt" /* Patterns (PS6) */
#define PSD_LOTH_GRADIENT "grdm" /* Gradient settings (PS6) */
-#define PSD_LOTH_RESTRICT "brst" /* Channel blending restirction setting (PS6) */
+#define PSD_LOTH_RESTRICT "brst" /* Channel blending restriction setting (PS6) */
#define PSD_LOTH_FOREIGN_FX "ffxi" /* Foreign effect ID (PS6) */
#define PSD_LOTH_PATT_DATA "shpa" /* Pattern data (PS6) */
#define PSD_LOTH_META_DATA "shmd" /* Meta data setting (PS6) */
@@ -490,6 +490,7 @@ typedef struct
LayerMaskExtra layer_mask_extra; /* Layer mask extra data */
LayerFlags layer_flags; /* Layer flags */
guint32 id; /* Layer ID (Tattoo) */
+ guchar group_type; /* 0 -> not a group; 1 -> open folder; 2 -> closed folder; 3 -> end of group */
} PSDlayer;
/* PSD Channel data structure */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]