From c6655c2eac59a47a6b1dc3410f26e933033d8ba9 Mon Sep 17 00:00:00 2001 From: Alx Sa Date: Tue, 17 Jun 2025 00:09:33 +0000 Subject: [PATCH] plug-ins: Correct Legacy PSD layer style loading format Per Wormnest, the 4 bytes allocated to PSD Legacy Dropshadow properties are meant to be used for fixed floating point values rather than integers. This patch corrects the PSD layer resource struct and how the data is loaded, based on prior work by Wormnest. --- plug-ins/file-psd/psd-layer-res-load.c | 93 ++++++++++++++------------ plug-ins/file-psd/psd.h | 8 +-- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/plug-ins/file-psd/psd-layer-res-load.c b/plug-ins/file-psd/psd-layer-res-load.c index 6904157179..2b4ee6cc7a 100644 --- a/plug-ins/file-psd/psd-layer-res-load.c +++ b/plug-ins/file-psd/psd-layer-res-load.c @@ -734,6 +734,10 @@ load_resource_lsct (const PSDlayerres *res_a, return 0; } +/* Adobe uses fixed point ints which consist of four bytes: a 16-bit number and + * 16-bit fraction */ +#define FIXED_TO_FLOAT(num,fract) (gfloat) num + fract / 65535.0f + static gint load_resource_lrfx (const PSDlayerres *res_a, PSDlayer *lyr_a, @@ -789,35 +793,35 @@ load_resource_lrfx (const PSDlayerres *res_a, else if (memcmp (effectname, "dsdw", 4) == 0) { gchar bim[4]; - guint16 spacer16; + guint16 temp[8]; - if (psd_read (input, &ls_a->dsdw.size, 4, error) < 4 || - psd_read (input, &ls_a->dsdw.ver, 4, error) < 4 || - psd_read (input, &ls_a->dsdw.blur, 2, error) < 2 || - psd_read (input, &ls_a->dsdw.intensity, 4, error) < 4 || - psd_read (input, &ls_a->dsdw.angle, 4, error) < 4 || - psd_read (input, &ls_a->dsdw.distance, 4, error) < 4 || - psd_read (input, &spacer16, 2, error) < 2 || - psd_read (input, &ls_a->dsdw.color[0], 2, error) < 2 || - psd_read (input, &ls_a->dsdw.color[1], 2, error) < 2 || - psd_read (input, &ls_a->dsdw.color[2], 2, error) < 2 || - psd_read (input, &ls_a->dsdw.color[3], 2, error) < 2 || - psd_read (input, &ls_a->dsdw.color[4], 2, error) < 2 || - psd_read (input, &bim, 4, error) < 4 || - psd_read (input, &ls_a->dsdw.blendsig, 4, error) < 4 || - psd_read (input, &ls_a->dsdw.effecton, 1, error) < 1 || - psd_read (input, &ls_a->dsdw.anglefx, 1, error) < 1 || - psd_read (input, &ls_a->dsdw.opacity, 1, error) < 1) + if (psd_read (input, &ls_a->dsdw.size, 4, error) < 4 || + psd_read (input, &ls_a->dsdw.ver, 4, error) < 4 || + psd_read (input, &temp, 16, error) < 2 || + psd_read (input, &ls_a->dsdw.color[0], 2, error) < 2 || + psd_read (input, &ls_a->dsdw.color[1], 2, error) < 2 || + psd_read (input, &ls_a->dsdw.color[2], 2, error) < 2 || + psd_read (input, &ls_a->dsdw.color[3], 2, error) < 2 || + psd_read (input, &ls_a->dsdw.color[4], 2, error) < 2 || + psd_read (input, &bim, 4, error) < 4 || + psd_read (input, &ls_a->dsdw.blendsig, 4, error) < 4 || + psd_read (input, &ls_a->dsdw.effecton, 1, error) < 1 || + psd_read (input, &ls_a->dsdw.anglefx, 1, error) < 1 || + psd_read (input, &ls_a->dsdw.opacity, 1, error) < 1) { psd_set_error (error); return -1; } ls_a->dsdw.size = GUINT32_TO_BE (ls_a->dsdw.size); ls_a->dsdw.ver = GUINT32_TO_BE (ls_a->dsdw.ver); - ls_a->dsdw.blur = GUINT16_TO_BE (ls_a->dsdw.blur); - ls_a->dsdw.intensity = GUINT32_TO_BE (ls_a->dsdw.intensity); - ls_a->dsdw.angle = GINT32_TO_BE (ls_a->dsdw.angle); - ls_a->dsdw.distance = GUINT32_TO_BE (ls_a->dsdw.distance); + ls_a->dsdw.blur = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[0]), + GUINT16_TO_BE (temp[1])); + ls_a->dsdw.intensity = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[2]), + GUINT16_TO_BE (temp[3])); + ls_a->dsdw.angle = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[4]), + GUINT16_TO_BE (temp[5])); + ls_a->dsdw.distance = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[6]), + GUINT16_TO_BE (temp[7])); if (ls_a->dsdw.ver == 2) { @@ -835,35 +839,35 @@ load_resource_lrfx (const PSDlayerres *res_a, else if (memcmp (effectname, "isdw", 4) == 0) { gchar bim[4]; - guint16 spacer16; + guint16 temp[8]; - if (psd_read (input, &ls_a->isdw.size, 4, error) < 4 || - psd_read (input, &ls_a->isdw.ver, 4, error) < 4 || - psd_read (input, &ls_a->isdw.blur, 2, error) < 2 || - psd_read (input, &ls_a->isdw.intensity, 4, error) < 4 || - psd_read (input, &ls_a->isdw.angle, 4, error) < 4 || - psd_read (input, &ls_a->isdw.distance, 4, error) < 4 || - psd_read (input, &spacer16, 2, error) < 2 || - psd_read (input, &ls_a->isdw.color[0], 2, error) < 2 || - psd_read (input, &ls_a->isdw.color[1], 2, error) < 2 || - psd_read (input, &ls_a->isdw.color[2], 2, error) < 2 || - psd_read (input, &ls_a->isdw.color[3], 2, error) < 2 || - psd_read (input, &ls_a->isdw.color[4], 2, error) < 2 || - psd_read (input, &bim, 4, error) < 4 || - psd_read (input, &ls_a->isdw.blendsig, 4, error) < 4 || - psd_read (input, &ls_a->isdw.effecton, 1, error) < 1 || - psd_read (input, &ls_a->isdw.anglefx, 1, error) < 1 || - psd_read (input, &ls_a->isdw.opacity, 1, error) < 1) + if (psd_read (input, &ls_a->isdw.size, 4, error) < 4 || + psd_read (input, &ls_a->isdw.ver, 4, error) < 4 || + psd_read (input, &temp, 16, error) < 2 || + psd_read (input, &ls_a->isdw.color[0], 2, error) < 2 || + psd_read (input, &ls_a->isdw.color[1], 2, error) < 2 || + psd_read (input, &ls_a->isdw.color[2], 2, error) < 2 || + psd_read (input, &ls_a->isdw.color[3], 2, error) < 2 || + psd_read (input, &ls_a->isdw.color[4], 2, error) < 2 || + psd_read (input, &bim, 4, error) < 4 || + psd_read (input, &ls_a->isdw.blendsig, 4, error) < 4 || + psd_read (input, &ls_a->isdw.effecton, 1, error) < 1 || + psd_read (input, &ls_a->isdw.anglefx, 1, error) < 1 || + psd_read (input, &ls_a->isdw.opacity, 1, error) < 1) { psd_set_error (error); return -1; } ls_a->isdw.size = GUINT32_TO_BE (ls_a->isdw.size); ls_a->isdw.ver = GUINT32_TO_BE (ls_a->isdw.ver); - ls_a->isdw.blur = GUINT16_TO_BE (ls_a->isdw.blur); - ls_a->isdw.intensity = GUINT32_TO_BE (ls_a->isdw.intensity); - ls_a->isdw.angle = GINT32_TO_BE (ls_a->isdw.angle); - ls_a->isdw.distance = GUINT32_TO_BE (ls_a->isdw.distance); + ls_a->isdw.blur = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[0]), + GUINT16_TO_BE (temp[1])); + ls_a->isdw.intensity = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[2]), + GUINT16_TO_BE (temp[3])); + ls_a->isdw.angle = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[4]), + GUINT16_TO_BE (temp[5])); + ls_a->isdw.distance = FIXED_TO_FLOAT (GUINT16_TO_BE (temp[6]), + GUINT16_TO_BE (temp[7])); if (ls_a->isdw.ver == 2) { @@ -1035,6 +1039,7 @@ load_resource_lrfx (const PSDlayerres *res_a, return 0; } +#undef FIXED_TO_FLOAT static gint load_resource_lyvr (const PSDlayerres *res_a, diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h index 059fb1d666..92723ba59f 100644 --- a/plug-ins/file-psd/psd.h +++ b/plug-ins/file-psd/psd.h @@ -593,10 +593,10 @@ typedef struct { guint32 size; guint32 ver; - guint16 blur; - guint32 intensity; - gint32 angle; - guint32 distance; + gfloat blur; + gfloat intensity; + gfloat angle; + gfloat distance; guint16 color[5]; gchar blendsig[4]; guchar effecton;