diff --git a/plug-ins/file-psd/psd-layer-res-load.c b/plug-ins/file-psd/psd-layer-res-load.c index f3c78bcbfd..0733a6689d 100644 --- a/plug-ins/file-psd/psd-layer-res-load.c +++ b/plug-ins/file-psd/psd-layer-res-load.c @@ -356,8 +356,20 @@ load_layer_resource (PSDlayerres *res_a, load_resource_lfil (res_a, lyr_a, input, error); } - else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0 - || memcmp (res_a->key, PSD_LFX_FX2, 4) == 0) + else if (memcmp (res_a->key, PSD_LFX_FX, 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) { @@ -401,11 +413,6 @@ load_layer_resource (PSDlayerres *res_a, 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) { load_resource_lyvr (res_a, lyr_a, input, error); @@ -733,22 +740,24 @@ load_resource_lrfx (const PSDlayerres *res_a, GInputStream *input, GError **error) { - gint16 version = 0; - gint16 count = 0; - gchar signature[4]; - gchar effectname[4]; - gint i; + PSDLayerStyles *ls_a; + gchar signature[4]; + gchar effectname[5]; + gint i; + + ls_a = lyr_a->layer_styles; IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key); - if (psd_read (input, &version, 2, error) < 2 || - psd_read (input, &count, 2, error) < 2) + if (psd_read (input, &ls_a->version, 2, error) < 2 || + psd_read (input, &ls_a->count, 2, error) < 2) { psd_set_error (error); 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 || psd_read (input, &effectname, 4, error) < 4) @@ -756,6 +765,7 @@ load_resource_lrfx (const PSDlayerres *res_a, psd_set_error (error); return -1; } + effectname[4] = '\0'; /* Not sure if 8B64 is possible here but it won't hurt to check. */ if (memcmp (signature, "8BIM", 4) != 0 && @@ -767,15 +777,10 @@ load_resource_lrfx (const PSDlayerres *res_a, { if (memcmp (effectname, "cmnS", 4) == 0) { - gint32 size; - gint32 ver; - gchar visible; - gint16 unused; - - 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) + if (psd_read (input, &ls_a->cmns.size, 4, error) < 4 || + psd_read (input, &ls_a->cmns.ver, 4, error) < 4 || + psd_read (input, &ls_a->cmns.visible, 1, error) < 1 || + psd_read (input, &ls_a->cmns.unused, 2, error) < 2) { psd_set_error (error); return -1; @@ -784,41 +789,34 @@ load_resource_lrfx (const PSDlayerres *res_a, else if (memcmp (effectname, "dsdw", 4) == 0 || memcmp (effectname, "isdw", 4) == 0) { - gint32 size; - 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]; + PSDLayerStyleShadow shadow; - 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) + if (memcmp (effectname, "dsdw", 4) == 0) + shadow = ls_a->dsdw; + else + shadow = ls_a->isdw; + + if (psd_read (input, &shadow.size, 4, error) < 4 || + psd_read (input, &shadow.ver, 4, error) < 4 || + psd_read (input, &shadow.blur, 4, error) < 4 || + psd_read (input, &shadow.intensity, 4, error) < 4 || + psd_read (input, &shadow.angle, 4, error) < 4 || + psd_read (input, &shadow.distance, 4, error) < 4 || + psd_read (input, &shadow.color[0], 2, error) < 2 || + psd_read (input, &shadow.color[1], 2, error) < 2 || + psd_read (input, &shadow.color[2], 2, error) < 2 || + psd_read (input, &shadow.color[3], 2, error) < 2 || + psd_read (input, &shadow.color[4], 2, error) < 2 || + psd_read (input, &shadow.blendsig, 4, error) < 4 || + psd_read (input, &shadow.effect, 4, error) < 4 || + psd_read (input, &shadow.effecton, 1, error) < 1 || + psd_read (input, &shadow.anglefx, 1, error) < 1 || + 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); return -1; @@ -826,42 +824,33 @@ load_resource_lrfx (const PSDlayerres *res_a, } 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 || - psd_read (input, &ver, 4, error) < 4 || - psd_read (input, &blur, 4, error) < 4 || - psd_read (input, &intensity, 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, &opacity, 1, error) < 1) + if (psd_read (input, &ls_a->oglw.size, 4, error) < 4 || + psd_read (input, &ls_a->oglw.ver, 4, error) < 4 || + psd_read (input, &ls_a->oglw.blur, 4, error) < 4 || + psd_read (input, &ls_a->oglw.intensity, 4, error) < 4 || + psd_read (input, &ls_a->oglw.color[0], 2, error) < 2 || + psd_read (input, &ls_a->oglw.color[1], 2, error) < 2 || + psd_read (input, &ls_a->oglw.color[2], 2, error) < 2 || + psd_read (input, &ls_a->oglw.color[3], 2, error) < 2 || + psd_read (input, &ls_a->oglw.color[4], 2, error) < 2 || + psd_read (input, &ls_a->oglw.blendsig, 4, error) < 4 || + psd_read (input, &ls_a->oglw.effect, 4, error) < 4 || + psd_read (input, &ls_a->oglw.effecton, 1, error) < 1 || + psd_read (input, &ls_a->oglw.opacity, 1, error) < 1) { psd_set_error (error); 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 || - 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) + if (psd_read (input, &ls_a->oglw.natcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->oglw.natcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->oglw.natcolor[2], 2, error) < 2 || + psd_read (input, &ls_a->oglw.natcolor[3], 2, error) < 2 || + psd_read (input, &ls_a->oglw.natcolor[4], 2, error) < 2) { psd_set_error (error); return -1; @@ -870,56 +859,33 @@ load_resource_lrfx (const PSDlayerres *res_a, } else if (memcmp (effectname, "iglw", 4) == 0) { - gint32 size = 0; - gint32 ver; - gint32 blur; - gint32 intensity; - gint32 angle; - gint32 distance; - gint16 color[5]; - gint32 blendsig; - gint32 effect; - gchar effecton; - gchar anglefx; - gchar opacity; - gchar invert; - 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) + if (psd_read (input, &ls_a->iglw.size, 4, error) < 4 || + psd_read (input, &ls_a->iglw.ver, 4, error) < 4 || + psd_read (input, &ls_a->iglw.blur, 4, error) < 4 || + psd_read (input, &ls_a->iglw.intensity, 4, error) < 4 || + psd_read (input, &ls_a->iglw.color[0], 2, error) < 2 || + psd_read (input, &ls_a->iglw.color[1], 2, error) < 2 || + psd_read (input, &ls_a->iglw.color[2], 2, error) < 2 || + psd_read (input, &ls_a->iglw.color[3], 2, error) < 2 || + psd_read (input, &ls_a->iglw.color[4], 2, error) < 2 || + psd_read (input, &ls_a->iglw.blendsig, 4, error) < 4 || + psd_read (input, &ls_a->iglw.effect, 4, error) < 4 || + psd_read (input, &ls_a->iglw.effecton, 1, error) < 1 || + psd_read (input, &ls_a->iglw.opacity, 1, error) < 1) { psd_set_error (error); 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 || - psd_read (input, &natcolor[0], 2, error) < 2 || - 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) + if (psd_read (input, &ls_a->iglw.invert, 1, error) < 1 || + psd_read (input, &ls_a->iglw.natcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->iglw.natcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->iglw.natcolor[2], 2, error) < 2 || + psd_read (input, &ls_a->iglw.natcolor[3], 2, error) < 2 || + psd_read (input, &ls_a->iglw.natcolor[4], 2, error) < 2) { psd_set_error (error); return -1; @@ -928,70 +894,49 @@ load_resource_lrfx (const PSDlayerres *res_a, } else if (memcmp (effectname, "bevl", 4) == 0) { - gint32 size = 0; - gint32 ver; - gint32 angle; - gint32 strength; - gint32 blur; - gint32 highlightsig; - gint32 highlighteffect; - gint32 shadowsig; - gint32 shadoweffect; - gint16 highlightcolor[5]; - gint16 shadowcolor[5]; - gchar style; - gchar highlightopacity; - gchar shadowopacity; - gchar enabled; - gchar global; - gchar direction; - gint16 highlightnatcolor[5]; - gint16 shadownatcolor[5]; - - if (psd_read (input, &size, 4, error) < 4 || - psd_read (input, &ver, 4, error) < 4 || - psd_read (input, &angle, 4, error) < 4 || - psd_read (input, &strength, 4, error) < 4 || - psd_read (input, &blur, 4, error) < 4 || - 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) + if (psd_read (input, &ls_a->bevl.size, 4, error) < 4 || + psd_read (input, &ls_a->bevl.ver, 4, error) < 4 || + psd_read (input, &ls_a->bevl.angle, 4, error) < 4 || + psd_read (input, &ls_a->bevl.strength, 4, error) < 4 || + psd_read (input, &ls_a->bevl.blur, 4, error) < 4 || + psd_read (input, &ls_a->bevl.highlightsig, 4, error) < 4 || + psd_read (input, &ls_a->bevl.highlighteffect, 4, error) < 4 || + psd_read (input, &ls_a->bevl.shadowsig, 4, error) < 4 || + psd_read (input, &ls_a->bevl.shadoweffect, 4, error) < 4 || + psd_read (input, &ls_a->bevl.highlightcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightcolor[2], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightcolor[3], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightcolor[4], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadowcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadowcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadowcolor[2], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadowcolor[3], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadowcolor[4], 2, error) < 2 || + psd_read (input, &ls_a->bevl.style, 1, error) < 1 || + psd_read (input, &ls_a->bevl.highlightopacity, 1, error) < 1 || + psd_read (input, &ls_a->bevl.shadowopacity, 1, error) < 1 || + psd_read (input, &ls_a->bevl.enabled, 1, error) < 1 || + psd_read (input, &ls_a->bevl.global, 1, error) < 1 || + psd_read (input, &ls_a->bevl.direction, 1, error) < 1) { psd_set_error (error); 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 || - psd_read (input, &highlightnatcolor[0], 2, error) < 2 || - psd_read (input, &highlightnatcolor[1], 2, error) < 2 || - psd_read (input, &highlightnatcolor[2], 2, error) < 2 || - psd_read (input, &highlightnatcolor[3], 2, error) < 2 || - psd_read (input, &highlightnatcolor[4], 2, error) < 2 || - psd_read (input, &shadownatcolor[0], 2, error) < 2 || - psd_read (input, &shadownatcolor[0], 2, error) < 2 || - psd_read (input, &shadownatcolor[1], 2, error) < 2 || - psd_read (input, &shadownatcolor[2], 2, error) < 2 || - psd_read (input, &shadownatcolor[3], 2, error) < 2 || - psd_read (input, &shadownatcolor[4], 2, error) < 2) + if (psd_read (input, &ls_a->bevl.highlightnatcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightnatcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightnatcolor[2], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightnatcolor[3], 2, error) < 2 || + psd_read (input, &ls_a->bevl.highlightnatcolor[4], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadownatcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadownatcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadownatcolor[2], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadownatcolor[3], 2, error) < 2 || + psd_read (input, &ls_a->bevl.shadownatcolor[4], 2, error) < 2) { psd_set_error (error); return -1; @@ -1000,29 +945,26 @@ load_resource_lrfx (const PSDlayerres *res_a, } else if (memcmp (effectname, "sofi", 4) == 0) { - gint32 size; - gint32 ver; - gint32 key; - gint16 color[5]; - gchar opacity; - gchar enabled; - gint16 natcolor[5]; + /* Documentation forgets to include the 4 byte 'bim8' before + * the blend signature */ + gchar blendsig[4]; - if (psd_read (input, &size, 4, error) < 4 || - psd_read (input, &ver, 4, error) < 4 || - psd_read (input, &key, 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, &opacity, 1, error) < 1 || - psd_read (input, &enabled, 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) + if (psd_read (input, &ls_a->sofi.size, 4, error) < 4 || + psd_read (input, &ls_a->sofi.ver, 4, error) < 4 || + psd_read (input, &blendsig, 4, error) < 4 || + psd_read (input, &ls_a->sofi.blend, 4, error) < 4 || + psd_read (input, &ls_a->sofi.color[0], 2, error) < 2 || + psd_read (input, &ls_a->sofi.color[1], 2, error) < 2 || + psd_read (input, &ls_a->sofi.color[2], 2, error) < 2 || + psd_read (input, &ls_a->sofi.color[3], 2, error) < 2 || + psd_read (input, &ls_a->sofi.color[4], 2, error) < 2 || + psd_read (input, &ls_a->sofi.opacity, 1, error) < 1 || + psd_read (input, &ls_a->sofi.enabled, 1, error) < 1 || + psd_read (input, &ls_a->sofi.natcolor[0], 2, error) < 2 || + psd_read (input, &ls_a->sofi.natcolor[1], 2, error) < 2 || + psd_read (input, &ls_a->sofi.natcolor[2], 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); return -1; diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c index 8719657de6..d33ba0a5b7 100644 --- a/plug-ins/file-psd/psd-load.c +++ b/plug-ins/file-psd/psd-load.c @@ -90,6 +90,10 @@ static gint add_layers (GimpImage *image, GInputStream *input, GError **error); +static void add_legacy_layer_effects (GimpLayer *layer, + PSDlayer *lyr_a, + gboolean ibm_pc_format); + static gint add_merged_image (GimpImage *image, PSDimage *img_a, GInputStream *input, @@ -106,6 +110,11 @@ static GimpLayer * add_clipping_group (GimpImage *image, 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 GimpImageType get_gimp_image_type (GimpImageBaseType image_base_type, @@ -1235,6 +1244,8 @@ read_layer_info (PSDimage *img_a, PSD_TELL(input), block_rem); /* Adjustment layer info */ /* FIXME */ + lyr_a[lidx]->layer_styles = g_new (PSDLayerStyles, 1); + lyr_a[lidx]->layer_styles->count = 0; 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 */ if (lyr_a[lidx]->group_type == 0 || /* normal layer */ 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]->name); + g_free (lyr_a[lidx]->layer_styles); g_free (lyr_a[lidx]); } g_free (lyr_a); @@ -2732,6 +2751,41 @@ add_layers (GimpImage *image, 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 add_merged_image (GimpImage *image, PSDimage *img_a, @@ -3220,6 +3274,26 @@ get_psd_color_mode_name (PSDColorMode mode) 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 psd_to_gimp_color_map (guchar *map256) { diff --git a/plug-ins/file-psd/psd-util.c b/plug-ins/file-psd/psd-util.c index 1768fb97f9..339edf39be 100644 --- a/plug-ins/file-psd/psd-util.c +++ b/plug-ins/file-psd/psd-util.c @@ -787,9 +787,7 @@ void psd_to_gimp_blend_mode (PSDlayer *psd_layer, 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, * we use rgb-perceptual blending/compositing unconditionally. */ @@ -800,9 +798,27 @@ psd_to_gimp_blend_mode (PSDlayer *psd_layer, else 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) { @@ -811,19 +827,12 @@ psd_to_gimp_blend_mode (PSDlayer *psd_layer, layer_mode_map[i].name); } - mode_info->mode = layer_mode_map[i].gimp_mode; - - return; + *mode = layer_mode_map[i].gimp_mode; + return TRUE; } } - 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); - } + return FALSE; } const gchar * diff --git a/plug-ins/file-psd/psd-util.h b/plug-ins/file-psd/psd-util.h index 497b6bbb72..531ddd8bf3 100644 --- a/plug-ins/file-psd/psd-util.h +++ b/plug-ins/file-psd/psd-util.h @@ -95,6 +95,8 @@ void psd_to_gimp_blend_mode (PSDlayer *psd_layer, 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); diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h index 21db8b498f..33e5a01b98 100644 --- a/plug-ins/file-psd/psd.h +++ b/plug-ins/file-psd/psd.h @@ -580,6 +580,97 @@ typedef struct gchar *info; /* Text information */ } 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 */ typedef struct { @@ -624,6 +715,7 @@ typedef struct guint32 id; /* Layer ID (Tattoo) */ 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 */ + PSDLayerStyles *layer_styles; /* Older format of layer styles */ PSDSupport *unsupported_features; } PSDlayer;