plug-ins: Load legacy Color Overlay layer style

This patch loads legacy 'sofi' data, which represents
the original Color Overlay layer style. It also sets up
the ability to add the other legacy layer styles once
we've matched the right GEGL operations and properties.
Note that this can not read the modern descriptor format
for layer styles.
This commit is contained in:
Alx Sa 2024-12-23 14:16:35 +00:00
parent 08019d95df
commit d46607f281
5 changed files with 345 additions and 226 deletions

View file

@ -356,8 +356,20 @@ load_layer_resource (PSDlayerres *res_a,
load_resource_lfil (res_a, lyr_a, input, error); load_resource_lfil (res_a, lyr_a, input, error);
} }
else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0 else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0)
|| memcmp (res_a->key, PSD_LFX_FX2, 4) == 0) {
/* TODO: Remove once all legacy layer styles are
* implemented */
if (lyr_a)
{
lyr_a->unsupported_features->layer_effect = TRUE;
lyr_a->unsupported_features->show_gui = TRUE;
}
load_resource_lrfx (res_a, lyr_a, input, error);
}
else if (memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
{ {
if (lyr_a) if (lyr_a)
{ {
@ -401,11 +413,6 @@ load_layer_resource (PSDlayerres *res_a,
load_resource_lsct (res_a, lyr_a, input, error); load_resource_lsct (res_a, lyr_a, input, error);
} }
else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0)
{
load_resource_lrfx (res_a, lyr_a, input, error);
}
else if (memcmp (res_a->key, PSD_LPRP_VERSION, 4) == 0) else if (memcmp (res_a->key, PSD_LPRP_VERSION, 4) == 0)
{ {
load_resource_lyvr (res_a, lyr_a, input, error); load_resource_lyvr (res_a, lyr_a, input, error);
@ -733,22 +740,24 @@ load_resource_lrfx (const PSDlayerres *res_a,
GInputStream *input, GInputStream *input,
GError **error) GError **error)
{ {
gint16 version = 0; PSDLayerStyles *ls_a;
gint16 count = 0; gchar signature[4];
gchar signature[4]; gchar effectname[5];
gchar effectname[4]; gint i;
gint i;
ls_a = lyr_a->layer_styles;
IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key); IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key);
if (psd_read (input, &version, 2, error) < 2 || if (psd_read (input, &ls_a->version, 2, error) < 2 ||
psd_read (input, &count, 2, error) < 2) psd_read (input, &ls_a->count, 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
} }
for (i = 0; i < count; i++) ls_a->count = GUINT16_TO_BE (ls_a->count);
for (i = 0; i < ls_a->count; i++)
{ {
if (psd_read (input, &signature, 4, error) < 4 || if (psd_read (input, &signature, 4, error) < 4 ||
psd_read (input, &effectname, 4, error) < 4) psd_read (input, &effectname, 4, error) < 4)
@ -756,6 +765,7 @@ load_resource_lrfx (const PSDlayerres *res_a,
psd_set_error (error); psd_set_error (error);
return -1; return -1;
} }
effectname[4] = '\0';
/* Not sure if 8B64 is possible here but it won't hurt to check. */ /* Not sure if 8B64 is possible here but it won't hurt to check. */
if (memcmp (signature, "8BIM", 4) != 0 && if (memcmp (signature, "8BIM", 4) != 0 &&
@ -767,15 +777,10 @@ load_resource_lrfx (const PSDlayerres *res_a,
{ {
if (memcmp (effectname, "cmnS", 4) == 0) if (memcmp (effectname, "cmnS", 4) == 0)
{ {
gint32 size; if (psd_read (input, &ls_a->cmns.size, 4, error) < 4 ||
gint32 ver; psd_read (input, &ls_a->cmns.ver, 4, error) < 4 ||
gchar visible; psd_read (input, &ls_a->cmns.visible, 1, error) < 1 ||
gint16 unused; psd_read (input, &ls_a->cmns.unused, 2, error) < 2)
if (psd_read (input, &size, 4, error) < 4 ||
psd_read (input, &ver, 4, error) < 4 ||
psd_read (input, &visible, 1, error) < 1 ||
psd_read (input, &unused, 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
@ -784,41 +789,34 @@ load_resource_lrfx (const PSDlayerres *res_a,
else if (memcmp (effectname, "dsdw", 4) == 0 else if (memcmp (effectname, "dsdw", 4) == 0
|| memcmp (effectname, "isdw", 4) == 0) || memcmp (effectname, "isdw", 4) == 0)
{ {
gint32 size; PSDLayerStyleShadow shadow;
gint32 ver;
gint32 blur;
gint32 intensity;
gint32 angle;
gint32 distance;
gint16 color[5];
gint32 blendsig;
gint32 effect;
gchar effecton;
gchar anglefx;
gchar opacity;
gint16 natcolor[5];
if (psd_read (input, &size, 4, error) < 4 || if (memcmp (effectname, "dsdw", 4) == 0)
psd_read (input, &ver, 4, error) < 4 || shadow = ls_a->dsdw;
psd_read (input, &blur, 4, error) < 4 || else
psd_read (input, &intensity, 4, error) < 4 || shadow = ls_a->isdw;
psd_read (input, &angle, 4, error) < 4 ||
psd_read (input, &distance, 4, error) < 4 || if (psd_read (input, &shadow.size, 4, error) < 4 ||
psd_read (input, &color[0], 2, error) < 2 || psd_read (input, &shadow.ver, 4, error) < 4 ||
psd_read (input, &color[1], 2, error) < 2 || psd_read (input, &shadow.blur, 4, error) < 4 ||
psd_read (input, &color[2], 2, error) < 2 || psd_read (input, &shadow.intensity, 4, error) < 4 ||
psd_read (input, &color[3], 2, error) < 2 || psd_read (input, &shadow.angle, 4, error) < 4 ||
psd_read (input, &color[4], 2, error) < 2 || psd_read (input, &shadow.distance, 4, error) < 4 ||
psd_read (input, &blendsig, 4, error) < 4 || psd_read (input, &shadow.color[0], 2, error) < 2 ||
psd_read (input, &effect, 4, error) < 4 || psd_read (input, &shadow.color[1], 2, error) < 2 ||
psd_read (input, &effecton, 1, error) < 1 || psd_read (input, &shadow.color[2], 2, error) < 2 ||
psd_read (input, &anglefx, 1, error) < 1 || psd_read (input, &shadow.color[3], 2, error) < 2 ||
psd_read (input, &opacity, 1, error) < 1 || psd_read (input, &shadow.color[4], 2, error) < 2 ||
psd_read (input, &natcolor[0], 2, error) < 2 || psd_read (input, &shadow.blendsig, 4, error) < 4 ||
psd_read (input, &natcolor[1], 2, error) < 2 || psd_read (input, &shadow.effect, 4, error) < 4 ||
psd_read (input, &natcolor[2], 2, error) < 2 || psd_read (input, &shadow.effecton, 1, error) < 1 ||
psd_read (input, &natcolor[3], 2, error) < 2 || psd_read (input, &shadow.anglefx, 1, error) < 1 ||
psd_read (input, &natcolor[4], 2, error) < 2) psd_read (input, &shadow.opacity, 1, error) < 1 ||
psd_read (input, &shadow.natcolor[0], 2, error) < 2 ||
psd_read (input, &shadow.natcolor[1], 2, error) < 2 ||
psd_read (input, &shadow.natcolor[2], 2, error) < 2 ||
psd_read (input, &shadow.natcolor[3], 2, error) < 2 ||
psd_read (input, &shadow.natcolor[4], 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
@ -826,42 +824,33 @@ load_resource_lrfx (const PSDlayerres *res_a,
} }
else if (memcmp (effectname, "oglw", 4) == 0) else if (memcmp (effectname, "oglw", 4) == 0)
{ {
gint32 size = 0;
gint32 ver;
gint32 blur;
gint32 intensity;
gint16 color[5];
gint32 blendsig;
gint32 effect;
gchar effecton;
gchar opacity;
gint16 natcolor[5];
if (psd_read (input, &size, 4, error) < 4 || if (psd_read (input, &ls_a->oglw.size, 4, error) < 4 ||
psd_read (input, &ver, 4, error) < 4 || psd_read (input, &ls_a->oglw.ver, 4, error) < 4 ||
psd_read (input, &blur, 4, error) < 4 || psd_read (input, &ls_a->oglw.blur, 4, error) < 4 ||
psd_read (input, &intensity, 4, error) < 4 || psd_read (input, &ls_a->oglw.intensity, 4, error) < 4 ||
psd_read (input, &color[0], 2, error) < 2 || psd_read (input, &ls_a->oglw.color[0], 2, error) < 2 ||
psd_read (input, &color[1], 2, error) < 2 || psd_read (input, &ls_a->oglw.color[1], 2, error) < 2 ||
psd_read (input, &color[2], 2, error) < 2 || psd_read (input, &ls_a->oglw.color[2], 2, error) < 2 ||
psd_read (input, &color[3], 2, error) < 2 || psd_read (input, &ls_a->oglw.color[3], 2, error) < 2 ||
psd_read (input, &color[4], 2, error) < 2 || psd_read (input, &ls_a->oglw.color[4], 2, error) < 2 ||
psd_read (input, &blendsig, 4, error) < 4 || psd_read (input, &ls_a->oglw.blendsig, 4, error) < 4 ||
psd_read (input, &effect, 4, error) < 4 || psd_read (input, &ls_a->oglw.effect, 4, error) < 4 ||
psd_read (input, &effecton, 1, error) < 1 || psd_read (input, &ls_a->oglw.effecton, 1, error) < 1 ||
psd_read (input, &opacity, 1, error) < 1) psd_read (input, &ls_a->oglw.opacity, 1, error) < 1)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
} }
if (size == 42) ls_a->oglw.size = GUINT32_TO_BE (ls_a->oglw.size);
if (ls_a->oglw.size == 42)
{ {
if (psd_read (input, &natcolor[0], 2, error) < 2 || if (psd_read (input, &ls_a->oglw.natcolor[0], 2, error) < 2 ||
psd_read (input, &natcolor[1], 2, error) < 2 || psd_read (input, &ls_a->oglw.natcolor[1], 2, error) < 2 ||
psd_read (input, &natcolor[2], 2, error) < 2 || psd_read (input, &ls_a->oglw.natcolor[2], 2, error) < 2 ||
psd_read (input, &natcolor[3], 2, error) < 2 || psd_read (input, &ls_a->oglw.natcolor[3], 2, error) < 2 ||
psd_read (input, &natcolor[4], 2, error) < 2) psd_read (input, &ls_a->oglw.natcolor[4], 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
@ -870,56 +859,33 @@ load_resource_lrfx (const PSDlayerres *res_a,
} }
else if (memcmp (effectname, "iglw", 4) == 0) else if (memcmp (effectname, "iglw", 4) == 0)
{ {
gint32 size = 0; if (psd_read (input, &ls_a->iglw.size, 4, error) < 4 ||
gint32 ver; psd_read (input, &ls_a->iglw.ver, 4, error) < 4 ||
gint32 blur; psd_read (input, &ls_a->iglw.blur, 4, error) < 4 ||
gint32 intensity; psd_read (input, &ls_a->iglw.intensity, 4, error) < 4 ||
gint32 angle; psd_read (input, &ls_a->iglw.color[0], 2, error) < 2 ||
gint32 distance; psd_read (input, &ls_a->iglw.color[1], 2, error) < 2 ||
gint16 color[5]; psd_read (input, &ls_a->iglw.color[2], 2, error) < 2 ||
gint32 blendsig; psd_read (input, &ls_a->iglw.color[3], 2, error) < 2 ||
gint32 effect; psd_read (input, &ls_a->iglw.color[4], 2, error) < 2 ||
gchar effecton; psd_read (input, &ls_a->iglw.blendsig, 4, error) < 4 ||
gchar anglefx; psd_read (input, &ls_a->iglw.effect, 4, error) < 4 ||
gchar opacity; psd_read (input, &ls_a->iglw.effecton, 1, error) < 1 ||
gchar invert; psd_read (input, &ls_a->iglw.opacity, 1, error) < 1)
gint16 natcolor[5];
if (psd_read (input, &size, 4, error) < 4 ||
psd_read (input, &ver, 4, error) < 4 ||
psd_read (input, &blur, 4, error) < 4 ||
psd_read (input, &intensity, 4, error) < 4 ||
psd_read (input, &angle, 4, error) < 4 ||
psd_read (input, &distance, 4, error) < 4 ||
psd_read (input, &color[0], 2, error) < 2 ||
psd_read (input, &color[1], 2, error) < 2 ||
psd_read (input, &color[2], 2, error) < 2 ||
psd_read (input, &color[3], 2, error) < 2 ||
psd_read (input, &color[4], 2, error) < 2 ||
psd_read (input, &blendsig, 4, error) < 4 ||
psd_read (input, &effect, 4, error) < 4 ||
psd_read (input, &effecton, 1, error) < 1 ||
psd_read (input, &anglefx, 1, error) < 1 ||
psd_read (input, &opacity, 1, error) < 1 ||
psd_read (input, &natcolor[0], 2, error) < 2 ||
psd_read (input, &natcolor[1], 2, error) < 2 ||
psd_read (input, &natcolor[2], 2, error) < 2 ||
psd_read (input, &natcolor[3], 2, error) < 2 ||
psd_read (input, &natcolor[4], 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
} }
if (size == 43) ls_a->iglw.size = GUINT32_TO_BE (ls_a->iglw.size);
if (ls_a->iglw.size == 43)
{ {
if (psd_read (input, &invert, 1, error) < 1 || if (psd_read (input, &ls_a->iglw.invert, 1, error) < 1 ||
psd_read (input, &natcolor[0], 2, error) < 2 || psd_read (input, &ls_a->iglw.natcolor[0], 2, error) < 2 ||
psd_read (input, &natcolor[0], 2, error) < 2 || psd_read (input, &ls_a->iglw.natcolor[1], 2, error) < 2 ||
psd_read (input, &natcolor[1], 2, error) < 2 || psd_read (input, &ls_a->iglw.natcolor[2], 2, error) < 2 ||
psd_read (input, &natcolor[2], 2, error) < 2 || psd_read (input, &ls_a->iglw.natcolor[3], 2, error) < 2 ||
psd_read (input, &natcolor[3], 2, error) < 2 || psd_read (input, &ls_a->iglw.natcolor[4], 2, error) < 2)
psd_read (input, &natcolor[4], 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
@ -928,70 +894,49 @@ load_resource_lrfx (const PSDlayerres *res_a,
} }
else if (memcmp (effectname, "bevl", 4) == 0) else if (memcmp (effectname, "bevl", 4) == 0)
{ {
gint32 size = 0; if (psd_read (input, &ls_a->bevl.size, 4, error) < 4 ||
gint32 ver; psd_read (input, &ls_a->bevl.ver, 4, error) < 4 ||
gint32 angle; psd_read (input, &ls_a->bevl.angle, 4, error) < 4 ||
gint32 strength; psd_read (input, &ls_a->bevl.strength, 4, error) < 4 ||
gint32 blur; psd_read (input, &ls_a->bevl.blur, 4, error) < 4 ||
gint32 highlightsig; psd_read (input, &ls_a->bevl.highlightsig, 4, error) < 4 ||
gint32 highlighteffect; psd_read (input, &ls_a->bevl.highlighteffect, 4, error) < 4 ||
gint32 shadowsig; psd_read (input, &ls_a->bevl.shadowsig, 4, error) < 4 ||
gint32 shadoweffect; psd_read (input, &ls_a->bevl.shadoweffect, 4, error) < 4 ||
gint16 highlightcolor[5]; psd_read (input, &ls_a->bevl.highlightcolor[0], 2, error) < 2 ||
gint16 shadowcolor[5]; psd_read (input, &ls_a->bevl.highlightcolor[1], 2, error) < 2 ||
gchar style; psd_read (input, &ls_a->bevl.highlightcolor[2], 2, error) < 2 ||
gchar highlightopacity; psd_read (input, &ls_a->bevl.highlightcolor[3], 2, error) < 2 ||
gchar shadowopacity; psd_read (input, &ls_a->bevl.highlightcolor[4], 2, error) < 2 ||
gchar enabled; psd_read (input, &ls_a->bevl.shadowcolor[0], 2, error) < 2 ||
gchar global; psd_read (input, &ls_a->bevl.shadowcolor[1], 2, error) < 2 ||
gchar direction; psd_read (input, &ls_a->bevl.shadowcolor[2], 2, error) < 2 ||
gint16 highlightnatcolor[5]; psd_read (input, &ls_a->bevl.shadowcolor[3], 2, error) < 2 ||
gint16 shadownatcolor[5]; psd_read (input, &ls_a->bevl.shadowcolor[4], 2, error) < 2 ||
psd_read (input, &ls_a->bevl.style, 1, error) < 1 ||
if (psd_read (input, &size, 4, error) < 4 || psd_read (input, &ls_a->bevl.highlightopacity, 1, error) < 1 ||
psd_read (input, &ver, 4, error) < 4 || psd_read (input, &ls_a->bevl.shadowopacity, 1, error) < 1 ||
psd_read (input, &angle, 4, error) < 4 || psd_read (input, &ls_a->bevl.enabled, 1, error) < 1 ||
psd_read (input, &strength, 4, error) < 4 || psd_read (input, &ls_a->bevl.global, 1, error) < 1 ||
psd_read (input, &blur, 4, error) < 4 || psd_read (input, &ls_a->bevl.direction, 1, error) < 1)
psd_read (input, &highlightsig, 4, error) < 4 ||
psd_read (input, &highlighteffect, 4, error) < 4 ||
psd_read (input, &shadowsig, 4, error) < 4 ||
psd_read (input, &highlightcolor[0], 2, error) < 2 ||
psd_read (input, &shadoweffect, 4, error) < 4 ||
psd_read (input, &highlightcolor[1], 2, error) < 2 ||
psd_read (input, &highlightcolor[2], 2, error) < 2 ||
psd_read (input, &highlightcolor[3], 2, error) < 2 ||
psd_read (input, &highlightcolor[4], 2, error) < 2 ||
psd_read (input, &shadowcolor[0], 2, error) < 2 ||
psd_read (input, &shadowcolor[1], 2, error) < 2 ||
psd_read (input, &shadowcolor[2], 2, error) < 2 ||
psd_read (input, &shadowcolor[3], 2, error) < 2 ||
psd_read (input, &shadowcolor[4], 2, error) < 2 ||
psd_read (input, &style, 1, error) < 1 ||
psd_read (input, &highlightopacity, 1, error) < 1 ||
psd_read (input, &shadowopacity, 1, error) < 1 ||
psd_read (input, &enabled, 1, error) < 1 ||
psd_read (input, &global, 1, error) < 1 ||
psd_read (input, &direction, 1, error) < 1)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
} }
if (size == 78) ls_a->bevl.size = GUINT32_TO_BE (ls_a->bevl.size);
if (ls_a->bevl.size == 78)
{ {
if (psd_read (input, &highlightnatcolor[0], 2, error) < 2 || if (psd_read (input, &ls_a->bevl.highlightnatcolor[0], 2, error) < 2 ||
psd_read (input, &highlightnatcolor[0], 2, error) < 2 || psd_read (input, &ls_a->bevl.highlightnatcolor[1], 2, error) < 2 ||
psd_read (input, &highlightnatcolor[1], 2, error) < 2 || psd_read (input, &ls_a->bevl.highlightnatcolor[2], 2, error) < 2 ||
psd_read (input, &highlightnatcolor[2], 2, error) < 2 || psd_read (input, &ls_a->bevl.highlightnatcolor[3], 2, error) < 2 ||
psd_read (input, &highlightnatcolor[3], 2, error) < 2 || psd_read (input, &ls_a->bevl.highlightnatcolor[4], 2, error) < 2 ||
psd_read (input, &highlightnatcolor[4], 2, error) < 2 || psd_read (input, &ls_a->bevl.shadownatcolor[0], 2, error) < 2 ||
psd_read (input, &shadownatcolor[0], 2, error) < 2 || psd_read (input, &ls_a->bevl.shadownatcolor[1], 2, error) < 2 ||
psd_read (input, &shadownatcolor[0], 2, error) < 2 || psd_read (input, &ls_a->bevl.shadownatcolor[2], 2, error) < 2 ||
psd_read (input, &shadownatcolor[1], 2, error) < 2 || psd_read (input, &ls_a->bevl.shadownatcolor[3], 2, error) < 2 ||
psd_read (input, &shadownatcolor[2], 2, error) < 2 || psd_read (input, &ls_a->bevl.shadownatcolor[4], 2, error) < 2)
psd_read (input, &shadownatcolor[3], 2, error) < 2 ||
psd_read (input, &shadownatcolor[4], 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;
@ -1000,29 +945,26 @@ load_resource_lrfx (const PSDlayerres *res_a,
} }
else if (memcmp (effectname, "sofi", 4) == 0) else if (memcmp (effectname, "sofi", 4) == 0)
{ {
gint32 size; /* Documentation forgets to include the 4 byte 'bim8' before
gint32 ver; * the blend signature */
gint32 key; gchar blendsig[4];
gint16 color[5];
gchar opacity;
gchar enabled;
gint16 natcolor[5];
if (psd_read (input, &size, 4, error) < 4 || if (psd_read (input, &ls_a->sofi.size, 4, error) < 4 ||
psd_read (input, &ver, 4, error) < 4 || psd_read (input, &ls_a->sofi.ver, 4, error) < 4 ||
psd_read (input, &key, 4, error) < 4 || psd_read (input, &blendsig, 4, error) < 4 ||
psd_read (input, &color[0], 2, error) < 2 || psd_read (input, &ls_a->sofi.blend, 4, error) < 4 ||
psd_read (input, &color[1], 2, error) < 2 || psd_read (input, &ls_a->sofi.color[0], 2, error) < 2 ||
psd_read (input, &color[2], 2, error) < 2 || psd_read (input, &ls_a->sofi.color[1], 2, error) < 2 ||
psd_read (input, &color[3], 2, error) < 2 || psd_read (input, &ls_a->sofi.color[2], 2, error) < 2 ||
psd_read (input, &color[4], 2, error) < 2 || psd_read (input, &ls_a->sofi.color[3], 2, error) < 2 ||
psd_read (input, &opacity, 1, error) < 1 || psd_read (input, &ls_a->sofi.color[4], 2, error) < 2 ||
psd_read (input, &enabled, 1, error) < 1 || psd_read (input, &ls_a->sofi.opacity, 1, error) < 1 ||
psd_read (input, &natcolor[0], 2, error) < 2 || psd_read (input, &ls_a->sofi.enabled, 1, error) < 1 ||
psd_read (input, &natcolor[1], 2, error) < 2 || psd_read (input, &ls_a->sofi.natcolor[0], 2, error) < 2 ||
psd_read (input, &natcolor[2], 2, error) < 2 || psd_read (input, &ls_a->sofi.natcolor[1], 2, error) < 2 ||
psd_read (input, &natcolor[3], 2, error) < 2 || psd_read (input, &ls_a->sofi.natcolor[2], 2, error) < 2 ||
psd_read (input, &natcolor[4], 2, error) < 2) psd_read (input, &ls_a->sofi.natcolor[3], 2, error) < 2 ||
psd_read (input, &ls_a->sofi.natcolor[4], 2, error) < 2)
{ {
psd_set_error (error); psd_set_error (error);
return -1; return -1;

View file

@ -90,6 +90,10 @@ static gint add_layers (GimpImage *image,
GInputStream *input, GInputStream *input,
GError **error); GError **error);
static void add_legacy_layer_effects (GimpLayer *layer,
PSDlayer *lyr_a,
gboolean ibm_pc_format);
static gint add_merged_image (GimpImage *image, static gint add_merged_image (GimpImage *image,
PSDimage *img_a, PSDimage *img_a,
GInputStream *input, GInputStream *input,
@ -106,6 +110,11 @@ static GimpLayer * add_clipping_group (GimpImage *image,
static gchar * get_psd_color_mode_name (PSDColorMode mode); static gchar * get_psd_color_mode_name (PSDColorMode mode);
static void convert_legacy_psd_color (GeglColor *color,
guint16 *psd_color,
const Babl *space,
gboolean ibm_pc_format);
static void psd_to_gimp_color_map (guchar *map256); static void psd_to_gimp_color_map (guchar *map256);
static GimpImageType get_gimp_image_type (GimpImageBaseType image_base_type, static GimpImageType get_gimp_image_type (GimpImageBaseType image_base_type,
@ -1235,6 +1244,8 @@ read_layer_info (PSDimage *img_a,
PSD_TELL(input), block_rem); PSD_TELL(input), block_rem);
/* Adjustment layer info */ /* FIXME */ /* Adjustment layer info */ /* FIXME */
lyr_a[lidx]->layer_styles = g_new (PSDLayerStyles, 1);
lyr_a[lidx]->layer_styles->count = 0;
while (block_rem > 7) while (block_rem > 7)
{ {
@ -2708,6 +2719,13 @@ add_layers (GimpImage *image,
} }
} }
/* Add legacy layer styles if applicable.
* TODO: When we can load modern layer styles, only load these if
* the file doesn't have modern layer style data. */
if (lyr_a[lidx]->layer_styles->count > 0)
add_legacy_layer_effects (layer, lyr_a[lidx],
img_a->ibm_pc_format);
/* Insert the layer */ /* Insert the layer */
if (lyr_a[lidx]->group_type == 0 || /* normal layer */ if (lyr_a[lidx]->group_type == 0 || /* normal layer */
lyr_a[lidx]->group_type == 3 /* group layer end marker */) lyr_a[lidx]->group_type == 3 /* group layer end marker */)
@ -2720,6 +2738,7 @@ add_layers (GimpImage *image,
g_free (lyr_a[lidx]->chn_info); g_free (lyr_a[lidx]->chn_info);
g_free (lyr_a[lidx]->name); g_free (lyr_a[lidx]->name);
g_free (lyr_a[lidx]->layer_styles);
g_free (lyr_a[lidx]); g_free (lyr_a[lidx]);
} }
g_free (lyr_a); g_free (lyr_a);
@ -2732,6 +2751,41 @@ add_layers (GimpImage *image,
return 0; return 0;
} }
static void
add_legacy_layer_effects (GimpLayer *layer,
PSDlayer *lyr_a,
gboolean ibm_pc_format)
{
const Babl *format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
const Babl *space = babl_format_get_space (format);
if (lyr_a->layer_styles->count == 7 &&
lyr_a->layer_styles->sofi.enabled == 1)
{
PSDLayerStyleSolidFill sofi;
GimpLayerMode mode;
GimpDrawableFilter *filter;
GeglColor *color = gegl_color_new ("none");
sofi = lyr_a->layer_styles->sofi;
convert_legacy_psd_color (color, sofi.natcolor, space, ibm_pc_format);
convert_psd_mode (sofi.blend, &mode);
filter = gimp_drawable_append_new_filter (GIMP_DRAWABLE (layer),
"gegl:color-overlay",
NULL,
"value", color,
NULL);
gimp_drawable_filter_set_opacity (filter, sofi.opacity / 255.0);
gimp_drawable_filter_set_blend_mode (filter, mode);
gimp_drawable_filter_update (filter);
g_object_unref (filter);
g_object_unref (color);
}
}
static gint static gint
add_merged_image (GimpImage *image, add_merged_image (GimpImage *image,
PSDimage *img_a, PSDimage *img_a,
@ -3220,6 +3274,26 @@ get_psd_color_mode_name (PSDColorMode mode)
return err_name; return err_name;
} }
static void
convert_legacy_psd_color (GeglColor *color,
guint16 *psd_color,
const Babl *space,
gboolean ibm_pc_format)
{
guint16 pixel[4];
for (gint i = 0; i < 4; i++)
{
pixel[i] = ibm_pc_format ? psd_color[i + 1] :
GUINT16_TO_BE (psd_color[i + 1]);
}
/* This is not specified in the documentation, but based on sample files,
* the color is assumed to be in the drawable's color space. */
gegl_color_set_pixel (color, babl_format_with_space ("R'G'B' u16", space),
pixel);
}
static void static void
psd_to_gimp_color_map (guchar *map256) psd_to_gimp_color_map (guchar *map256)
{ {

View file

@ -787,9 +787,7 @@ void
psd_to_gimp_blend_mode (PSDlayer *psd_layer, psd_to_gimp_blend_mode (PSDlayer *psd_layer,
LayerModeInfo *mode_info) LayerModeInfo *mode_info)
{ {
gint i; mode_info->mode = GIMP_LAYER_MODE_NORMAL;
mode_info->mode = GIMP_LAYER_MODE_NORMAL;
/* FIXME: use the image mode to select the correct color spaces. for now, /* FIXME: use the image mode to select the correct color spaces. for now,
* we use rgb-perceptual blending/compositing unconditionally. * we use rgb-perceptual blending/compositing unconditionally.
*/ */
@ -800,9 +798,27 @@ psd_to_gimp_blend_mode (PSDlayer *psd_layer,
else else
mode_info->composite_mode = GIMP_LAYER_COMPOSITE_UNION; mode_info->composite_mode = GIMP_LAYER_COMPOSITE_UNION;
for (i = 0; i < G_N_ELEMENTS (layer_mode_map); i++) if (! convert_psd_mode (psd_layer->blend_mode, &mode_info->mode))
{ {
if (g_ascii_strncasecmp (psd_layer->blend_mode, layer_mode_map[i].psd_mode, 4) == 0) if (CONVERSION_WARNINGS)
{
gchar *mode_name = g_strndup (psd_layer->blend_mode, 4);
g_message ("Unsupported blend mode: %s. Mode reverts to normal",
mode_name);
g_free (mode_name);
}
}
}
gboolean
convert_psd_mode (const gchar *psd_mode,
GimpLayerMode *mode)
{
*mode = GIMP_LAYER_MODE_NORMAL;
for (gint i = 0; i < G_N_ELEMENTS (layer_mode_map); i++)
{
if (g_ascii_strncasecmp (psd_mode, layer_mode_map[i].psd_mode, 4) == 0)
{ {
if (! layer_mode_map[i].exact && CONVERSION_WARNINGS) if (! layer_mode_map[i].exact && CONVERSION_WARNINGS)
{ {
@ -811,19 +827,12 @@ psd_to_gimp_blend_mode (PSDlayer *psd_layer,
layer_mode_map[i].name); layer_mode_map[i].name);
} }
mode_info->mode = layer_mode_map[i].gimp_mode; *mode = layer_mode_map[i].gimp_mode;
return TRUE;
return;
} }
} }
if (CONVERSION_WARNINGS) return FALSE;
{
gchar *mode_name = g_strndup (psd_layer->blend_mode, 4);
g_message ("Unsupported blend mode: %s. Mode reverts to normal",
mode_name);
g_free (mode_name);
}
} }
const gchar * const gchar *

View file

@ -95,6 +95,8 @@ void psd_to_gimp_blend_mode (PSDlayer *psd_layer,
LayerModeInfo *mode_info); LayerModeInfo *mode_info);
const gchar * gimp_to_psd_blend_mode (const LayerModeInfo *mode_info); const gchar * gimp_to_psd_blend_mode (const LayerModeInfo *mode_info);
gboolean convert_psd_mode (const gchar *psd_mode,
GimpLayerMode *mode);
GimpColorTag psd_to_gimp_layer_color_tag (guint16 layer_color_tag); GimpColorTag psd_to_gimp_layer_color_tag (guint16 layer_color_tag);

View file

@ -580,6 +580,97 @@ typedef struct
gchar *info; /* Text information */ gchar *info; /* Text information */
} PSDText; } PSDText;
typedef struct
{
guint32 size;
guint32 ver;
guchar visible;
guint16 unused;
} PSDLayerStyleCommon;
typedef struct
{
guint32 size;
guint32 ver;
guint32 blur;
guint32 intensity;
gint32 angle;
guint32 distance;
guint16 color[5];
gchar blendsig[4];
guint32 effect;
guchar effecton;
guchar anglefx;
guchar opacity;
guint16 natcolor[5];
} PSDLayerStyleShadow;
typedef struct
{
guint32 size;
guint32 ver;
guint32 blur;
guint32 intensity;
guint16 color[5];
gchar blendsig[4];
guint32 effect;
guchar effecton;
guchar opacity;
/* Version 2 only */
guchar invert; /* Inner Glow Only */
guint16 natcolor[5];
} PSDLayerStyleGlow;
typedef struct
{
guint32 size;
guint32 ver;
gint32 angle;
guint32 strength;
guint32 blur;
guint32 highlightsig;
guint32 highlighteffect;
guint32 shadowsig;
guint32 shadoweffect;
guint16 highlightcolor[5];
guint16 shadowcolor[5];
guchar style;
guchar highlightopacity;
guchar shadowopacity;
guchar enabled;
guchar global;
guchar direction;
/* Version 2 only */
guint16 highlightnatcolor[5];
guint16 shadownatcolor[5];
} PSDLayerStyleBevel;
typedef struct
{
guint32 size;
guint32 ver;
gchar blend[4];
guint16 color[5];
guchar opacity;
guchar enabled;
guint16 natcolor[5];
} PSDLayerStyleSolidFill;
/* Older PSD Layer Styles format */
typedef struct
{
guint16 version;
guint16 count;
PSDLayerStyleCommon cmns; /* Common State */
PSDLayerStyleShadow dsdw; /* Drop Shadow */
PSDLayerStyleShadow isdw; /* Inner Shadow */
PSDLayerStyleGlow oglw; /* Outer Glow */
PSDLayerStyleGlow iglw; /* Inner Glow */
PSDLayerStyleBevel bevl; /* Bevel */
PSDLayerStyleSolidFill sofi; /* Solid Fill */
} PSDLayerStyles;
/* Partially or Unsupported Features */ /* Partially or Unsupported Features */
typedef struct typedef struct
{ {
@ -624,6 +715,7 @@ typedef struct
guint32 id; /* Layer ID (Tattoo) */ guint32 id; /* Layer ID (Tattoo) */
guchar group_type; /* 0 -> not a group; 1 -> open folder; 2 -> closed folder; 3 -> end of group */ guchar group_type; /* 0 -> not a group; 1 -> open folder; 2 -> closed folder; 3 -> end of group */
guint16 color_tag[4]; /* 4 * 16 bit color components */ guint16 color_tag[4]; /* 4 * 16 bit color components */
PSDLayerStyles *layer_styles; /* Older format of layer styles */
PSDSupport *unsupported_features; PSDSupport *unsupported_features;
} PSDlayer; } PSDlayer;