[gimp] plug-ins: fix loading of 32-bit per channel psd images
- From: Jacob Boerema <jboerema src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: fix loading of 32-bit per channel psd images
- Date: Mon, 15 Nov 2021 22:15:39 +0000 (UTC)
commit 82b7fa84bd455ab90c6cab8fc080e69b934c65e7
Author: Jacob Boerema <jgboerema gmail com>
Date: Mon Nov 15 17:15:08 2021 -0500
plug-ins: fix loading of 32-bit per channel psd images
Although there was code to load 32-bit per channel psd images. It is
unlikely that it ever worked, because:
- We tried to load them as u32 instead of float.
- While we did some decoding of the zip predictor data, for float values
we also need to restore the byte order from 111222333 to 123123123.
- We did the endian conversion first while it should be done on the
restored values.
With these things fixed I can load the few samples I have.
plug-ins/file-psd/psd-load.c | 101 +++++++++++++++++++++++++++++++++++--------
1 file changed, 84 insertions(+), 17 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 03d630df19..7d2db5d376 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -112,6 +112,11 @@ static gint read_channel_data (PSDchannel *channel,
guint32 comp_len,
GError **error);
+static void decode_32_bit_predictor (gchar *src,
+ gchar *dst,
+ guint32 rows,
+ guint32 columns);
+
static void convert_1_bit (const gchar *src,
gchar *dst,
guint32 rows,
@@ -1301,7 +1306,7 @@ create_gimp_image (PSDimage *img_a,
switch (img_a->bps)
{
case 32:
- precision = GIMP_PRECISION_U32_NON_LINEAR;
+ precision = GIMP_PRECISION_FLOAT_NON_LINEAR;
break;
case 16:
@@ -1846,6 +1851,7 @@ add_layers (GimpImage *image,
IFDBG(3) g_debug ("Re-hash channel indices");
for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx)
{
+ IFDBG(3) g_debug ("Channel: %d - id: %d", cidx, lyr_chn[cidx]->id);
if (lyr_chn[cidx]->id == PSD_CHANNEL_MASK)
{
user_mask = TRUE;
@@ -2844,20 +2850,27 @@ read_channel_data (PSDchannel *channel,
{
case 32:
{
- guint32 *data = (guint32*) raw_data;
-
- channel->data = raw_data;
- raw_data = NULL;
-
- for (i = 0; i < channel->rows * channel->columns; ++i)
- data[i] = GUINT32_FROM_BE (data[i]);
+ guint32 *data;
+ guint64 pos;
if (compression == PSD_COMP_ZIP_PRED)
{
- for (i = 0; i < channel->rows; ++i)
- for (j = 1; j < channel->columns; ++j)
- data[i * channel->columns + j] += data[i * channel->columns + j - 1];
+ IFDBG(3) g_debug ("Converting 32 bit predictor data");
+ channel->data = (gchar *) g_malloc0 (channel->rows * channel->columns * 4);
+ decode_32_bit_predictor (raw_data, channel->data,
+ channel->rows, channel->columns);
+ }
+ else
+ {
+ IFDBG(3) g_debug ("32 bit channel data without predictor");
+ channel->data = raw_data;
+ raw_data = NULL;
}
+
+ data = (guint32*) channel->data;
+ for (pos = 0; pos < channel->rows * channel->columns; ++pos)
+ data[pos] = GUINT32_FROM_BE (data[pos]);
+
break;
}
@@ -2873,6 +2886,7 @@ read_channel_data (PSDchannel *channel,
if (compression == PSD_COMP_ZIP_PRED)
{
+ IFDBG(3) g_debug ("Converting 16 bit predictor data");
for (i = 0; i < channel->rows; ++i)
for (j = 1; j < channel->columns; ++j)
data[i * channel->columns + j] += data[i * channel->columns + j - 1];
@@ -2886,6 +2900,7 @@ read_channel_data (PSDchannel *channel,
if (compression == PSD_COMP_ZIP_PRED)
{
+ IFDBG(3) g_debug ("Converting 8 bit predictor data");
for (i = 0; i < channel->rows; ++i)
for (j = 1; j < channel->columns; ++j)
channel->data[i * channel->columns + j] += channel->data[i * channel->columns + j - 1];
@@ -2908,6 +2923,58 @@ read_channel_data (PSDchannel *channel,
return 1;
}
+/*
+ * For reference on zip predictor see:
+ * - TIFFTN3d1.pdf
+ * - psd_tools
+ */
+
+static void
+decode_32_bit_predictor (gchar *src,
+ gchar *dst,
+ guint32 rows,
+ guint32 columns)
+{
+ guint32 rowsize;
+ guint64 row, dstpos;
+
+ rowsize = columns * 4;
+
+ /* decode delta */
+ for (row = 0; row < rows; ++row)
+ {
+ guint32 j;
+ guint64 offset;
+
+ offset = row * rowsize;
+ for (j = 0; j < rowsize-1; ++j)
+ {
+ guint64 pos;
+
+ pos = offset + j;
+ src[pos + 1] += src[pos];
+ }
+ }
+
+ /* restore byte order */
+ dstpos = 0;
+ for (row = 0; row < rows * rowsize; row += rowsize)
+ {
+ guint64 offset;
+
+ for (offset = row; offset < row + columns; offset++)
+ {
+ guint64 x;
+
+ for (x = offset; x < offset + rowsize; x += columns)
+ {
+ dst[dstpos] = src[x];
+ dstpos++;
+ }
+ }
+ }
+}
+
static void
convert_1_bit (const gchar *src,
gchar *dst,
@@ -2953,7 +3020,7 @@ get_layer_format (PSDimage *img_a,
switch (img_a->bps)
{
case 32:
- format = babl_format ("Y' u32");
+ format = babl_format ("Y' float");
break;
case 16:
@@ -2976,7 +3043,7 @@ get_layer_format (PSDimage *img_a,
switch (img_a->bps)
{
case 32:
- format = babl_format ("Y'A u32");
+ format = babl_format ("Y'A float");
break;
case 16:
@@ -2998,7 +3065,7 @@ get_layer_format (PSDimage *img_a,
switch (img_a->bps)
{
case 32:
- format = babl_format ("R'G'B' u32");
+ format = babl_format ("R'G'B' float");
break;
case 16:
@@ -3021,7 +3088,7 @@ get_layer_format (PSDimage *img_a,
switch (img_a->bps)
{
case 32:
- format = babl_format ("R'G'B'A u32");
+ format = babl_format ("R'G'B'A float");
break;
case 16:
@@ -3056,7 +3123,7 @@ get_channel_format (PSDimage *img_a)
switch (img_a->bps)
{
case 32:
- format = babl_format ("Y u32");
+ format = babl_format ("Y float");
break;
case 16:
@@ -3084,7 +3151,7 @@ get_mask_format (PSDimage *img_a)
switch (img_a->bps)
{
case 32:
- format = babl_format ("Y u32");
+ format = babl_format ("Y float");
break;
case 16:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]