[gimp/gimp-2-10] plug-ins: add support for loading merged image data from PSD files
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-10] plug-ins: add support for loading merged image data from PSD files
- Date: Mon, 18 Jun 2018 10:35:35 +0000 (UTC)
commit d49e038ed3611409010fa78a061916b4bdca207a
Author: Ell <ell_se yahoo com>
Date: Mon Jun 18 06:17:04 2018 -0400
plug-ins: add support for loading merged image data from PSD files
PSD files may include a "merged", pre-composited, version of the
image (in Photoshop, this is the case when saving files with
"Maximize Compatibility" enabled; GIMP always saves the merged
image data in exported PSD files.) This commit adds support for
loading the merged image version from PSDs, instead of the full
layer hierarchy. This is useful when loading PSD files that use
features that we don't currently support, and therefore can't
render correctly, such as adjustment layers.
When loading the merged image version, we avoid loading certain
additional data from the file, such as channels, paths, and
guides, while still loading metadata, making this akin to loading
other "flat" image formats.
This option is currently exposed as an additional file type
("Photoshop image (merged)"), which has to be explicitly selected
from the file-type list when opening the image.
(cherry picked from commit 1d9a8a91ab74061f17f1f52fa269ce6aff6e529e)
plug-ins/file-psd/psd-image-res-load.c | 21 +++++---
plug-ins/file-psd/psd-load.c | 88 ++++++++++++++++++++++++++--------
plug-ins/file-psd/psd-load.h | 1 +
plug-ins/file-psd/psd.c | 25 +++++++++-
plug-ins/file-psd/psd.h | 3 ++
5 files changed, 111 insertions(+), 27 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-image-res-load.c b/plug-ins/file-psd/psd-image-res-load.c
index b59c700cfc..ec86dbaa2d 100644
--- a/plug-ins/file-psd/psd-image-res-load.c
+++ b/plug-ins/file-psd/psd-image-res-load.c
@@ -330,7 +330,8 @@ load_image_resource (PSDimageres *res_a,
break;
case PSD_ALPHA_NAMES:
- load_resource_1006 (res_a, image_id, img_a, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_1006 (res_a, image_id, img_a, f, error);
break;
case PSD_DISPLAY_INFO:
@@ -342,15 +343,18 @@ load_image_resource (PSDimageres *res_a,
break;
case PSD_QUICK_MASK:
- load_resource_1022 (res_a, image_id, img_a, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_1022 (res_a, image_id, img_a, f, error);
break;
case PSD_LAYER_STATE:
- load_resource_1024 (res_a, image_id, img_a, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_1024 (res_a, image_id, img_a, f, error);
break;
case PSD_WORKING_PATH:
- load_resource_2000 (res_a, image_id, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_2000 (res_a, image_id, f, error);
break;
case PSD_IPTC_NAA_DATA:
@@ -358,7 +362,8 @@ load_image_resource (PSDimageres *res_a,
break;
case PSD_GRID_GUIDE:
- load_resource_1032 (res_a, image_id, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_1032 (res_a, image_id, f, error);
break;
case PSD_ICC_PROFILE:
@@ -366,7 +371,8 @@ load_image_resource (PSDimageres *res_a,
break;
case PSD_ALPHA_NAMES_UNI:
- load_resource_1045 (res_a, image_id, img_a, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_1045 (res_a, image_id, img_a, f, error);
break;
case PSD_IDX_COL_TAB_CNT:
@@ -374,7 +380,8 @@ load_image_resource (PSDimageres *res_a,
break;
case PSD_ALPHA_ID:
- load_resource_1053 (res_a, image_id, img_a, f, error);
+ if (! img_a->merged_image_only)
+ load_resource_1053 (res_a, image_id, img_a, f, error);
break;
case PSD_EXIF_DATA:
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 87b94a1a81..dc794bc1f7 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -113,6 +113,7 @@ static const Babl* get_mask_format (PSDimage *img_a);
/* Main file load function */
gint32
load_image (const gchar *filename,
+ gboolean merged_image_only,
gboolean *resolution_loaded,
GError **load_error)
{
@@ -140,6 +141,8 @@ load_image (const gchar *filename,
return -1;
}
+ img_a.merged_image_only = merged_image_only;
+
/* ----- Read the PSD file Header block ----- */
IFDBG(2) g_debug ("Read header block");
if (read_header_block (&img_a, f, &error) < 0)
@@ -161,7 +164,7 @@ load_image (const gchar *filename,
/* ----- Read the PSD file Layer & Mask block ----- */
IFDBG(2) g_debug ("Read layer & mask block");
lyr_a = read_layer_block (&img_a, f, &error);
- if (img_a.num_layers != 0 && lyr_a == NULL)
+ if (! img_a.merged_image_only && img_a.num_layers != 0 && lyr_a == NULL)
goto load_error;
gimp_progress_update (0.4);
@@ -496,7 +499,7 @@ read_layer_info (PSDimage *img_a,
img_a->num_layers = -img_a->num_layers;
}
- if (img_a->num_layers)
+ if (! img_a->merged_image_only && img_a->num_layers)
{
/* Read layer records */
PSDlayerres res_a;
@@ -1146,7 +1149,7 @@ add_layers (gint32 image_id,
IFDBG(2) g_debug ("Number of layers: %d", img_a->num_layers);
- if (img_a->num_layers == 0)
+ if (img_a->merged_image_only || img_a->num_layers == 0)
{
IFDBG(2) g_debug ("No layers to process");
return 0;
@@ -1734,9 +1737,16 @@ add_merged_image (gint32 image_id,
extra_channels--;
base_channels = total_channels - extra_channels;
+ if (img_a->merged_image_only)
+ {
+ extra_channels = 0;
+ total_channels = base_channels;
+ }
+
/* ----- Read merged image & extra channel pixel data ----- */
- if (img_a->num_layers == 0
- || extra_channels > 0)
+ if (img_a->merged_image_only ||
+ img_a->num_layers == 0 ||
+ extra_channels > 0)
{
guint32 block_len;
guint32 block_start;
@@ -1790,6 +1800,14 @@ add_merged_image (gint32 image_id,
}
}
+ /* Skip channel length data for unloaded channels */
+ if (fseek (f, (img_a->channels - total_channels) * img_a->rows * 2,
+ SEEK_CUR) < 0)
+ {
+ psd_set_error (feof (f), errno, error);
+ return -1;
+ }
+
IFDBG(3) g_debug ("RLE decode - data");
for (cidx = 0; cidx < total_channels; ++cidx)
{
@@ -1812,7 +1830,8 @@ add_merged_image (gint32 image_id,
}
/* ----- Draw merged image ----- */
- if (img_a->num_layers == 0) /* Merged image - Photoshop 2 style */
+ if (img_a->merged_image_only ||
+ img_a->num_layers == 0) /* Merged image - Photoshop 2 style */
{
image_type = get_gimp_image_type (img_a->base_type, img_a->transparency);
@@ -1836,6 +1855,7 @@ add_merged_image (gint32 image_id,
100,
gimp_image_get_default_new_layer_mode (image_id));
gimp_image_insert_layer (image_id, layer_id, -1, 0);
+
buffer = gimp_drawable_get_buffer (layer_id);
gegl_buffer_set (buffer,
GEGL_RECTANGLE (0, 0,
@@ -1843,6 +1863,36 @@ add_merged_image (gint32 image_id,
gegl_buffer_get_height (buffer)),
0, get_layer_format (img_a, img_a->transparency),
pixels, GEGL_AUTO_ROWSTRIDE);
+
+ /* Merged image data is blended against white. Unblend it. */
+ if (img_a->transparency)
+ {
+ GeglBufferIterator *iter;
+
+ iter = gegl_buffer_iterator_new (buffer, NULL, 0,
+ babl_format ("R'G'B'A float"),
+ GEGL_ACCESS_READWRITE,
+ GEGL_ABYSS_NONE);
+
+ while (gegl_buffer_iterator_next (iter))
+ {
+ gfloat *data = iter->data[0];
+
+ for (i = 0; i < iter->length; i++)
+ {
+ gint c;
+
+ if (data[3])
+ {
+ for (c = 0; c < 3; c++)
+ data[c] = (data[c] + data[3] - 1.0f) / data[3];
+ }
+
+ data += 4;
+ }
+ }
+ }
+
g_object_unref (buffer);
g_free (pixels);
}
@@ -1854,9 +1904,19 @@ add_merged_image (gint32 image_id,
g_free (chn_a[cidx].data);
}
+ if (img_a->transparency)
+ {
+ /* Free "Transparency" channel name */
+ if (img_a->alpha_names)
+ {
+ alpha_name = g_ptr_array_index (img_a->alpha_names, 0);
+ if (alpha_name)
+ g_free (alpha_name);
+ }
+ }
+
/* ----- Draw extra alpha channels ----- */
- if ((extra_channels /* Extra alpha channels */
- || img_a->transparency) /* Transparency alpha channel */
+ if (extra_channels /* Extra alpha channels */
&& image_id > -1)
{
IFDBG(2) g_debug ("Add extra channels");
@@ -1864,17 +1924,7 @@ add_merged_image (gint32 image_id,
/* Get channel resource data */
if (img_a->transparency)
- {
- offset = 1;
-
- /* Free "Transparency" channel name */
- if (img_a->alpha_names)
- {
- alpha_name = g_ptr_array_index (img_a->alpha_names, 0);
- if (alpha_name)
- g_free (alpha_name);
- }
- }
+ offset = 1;
else
offset = 0;
diff --git a/plug-ins/file-psd/psd-load.h b/plug-ins/file-psd/psd-load.h
index 177d74fcac..f8b62c9fc7 100644
--- a/plug-ins/file-psd/psd-load.h
+++ b/plug-ins/file-psd/psd-load.h
@@ -23,6 +23,7 @@
gint32 load_image (const gchar *filename,
+ gboolean merged_image_only,
gboolean *resolution_loaded,
GError **error);
diff --git a/plug-ins/file-psd/psd.c b/plug-ins/file-psd/psd.c
index 0a52c0053a..971736c222 100644
--- a/plug-ins/file-psd/psd.c
+++ b/plug-ins/file-psd/psd.c
@@ -119,6 +119,27 @@ query (void)
"",
"0,string,8BPS");
+ /* File load (merged) */
+ gimp_install_procedure (LOAD_MERGED_PROC,
+ "Loads merged images from the Photoshop PSD file format",
+ "This plug-in loads the merged image data in Adobe "
+ "Photoshop (TM) native PSD format.",
+ "Ell",
+ "Ell",
+ "2018",
+ N_("Photoshop image (merged)"),
+ NULL,
+ GIMP_PLUGIN,
+ G_N_ELEMENTS (load_args),
+ G_N_ELEMENTS (load_return_vals),
+ load_args, load_return_vals);
+
+ gimp_register_file_handler_mime (LOAD_MERGED_PROC, "image/x-psd");
+ gimp_register_magic_load_handler (LOAD_MERGED_PROC,
+ "psd",
+ "",
+ "0,string,8BPS");
+
/* Thumbnail load */
gimp_install_procedure (LOAD_THUMB_PROC,
"Loads thumbnails from the Photoshop PSD file format",
@@ -176,7 +197,8 @@ run (const gchar *name,
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
- if (strcmp (name, LOAD_PROC) == 0)
+ if (strcmp (name, LOAD_PROC) == 0 ||
+ strcmp (name, LOAD_MERGED_PROC) == 0)
{
gboolean resolution_loaded = FALSE;
gboolean interactive;
@@ -194,6 +216,7 @@ run (const gchar *name,
}
image_ID = load_image (param[1].data.d_string,
+ strcmp (name, LOAD_MERGED_PROC) == 0,
&resolution_loaded, &error);
if (image_ID != -1)
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index f7320ac4cc..cb2d887505 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -32,6 +32,7 @@
#define CONVERSION_WARNINGS FALSE
#define LOAD_PROC "file-psd-load"
+#define LOAD_MERGED_PROC "file-psd-load-merged"
#define LOAD_THUMB_PROC "file-psd-load-thumb"
#define SAVE_PROC "file-psd-save"
#define PLUG_IN_BINARY "file-psd"
@@ -642,6 +643,8 @@ typedef struct
/* PSD File data structures */
typedef struct
{
+ gboolean merged_image_only; /* Whether to load only the merged image data */
+
guint16 channels; /* Number of channels: 1- 56 */
gboolean transparency; /* Image has merged transparency alpha channel */
guint32 rows; /* Number of rows: 1 - 30000 */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]