[gimp] plug-ins: in file-psd, improve PS <-> GIMP layer-mode mapping



commit 33255a439b3ff371b6ed5835ba5bc6e12826d350
Author: Ell <ell_se yahoo com>
Date:   Sun Aug 20 15:25:08 2017 -0400

    plug-ins: in file-psd, improve PS <-> GIMP layer-mode mapping
    
    Streamline the layer-mode mapping code, to reduce duplication.
    
    Add mappings for the following modes:  Subtract, Divide, Luma/
    luminance darken only (Darker Color), Luma/luminance lighten only
    (Lighter Color), and Luminance (Luminosity).

 plug-ins/file-psd/psd-load.c |   29 +--
 plug-ins/file-psd/psd-save.c |  247 ++++++-------------
 plug-ins/file-psd/psd-util.c |  587 ++++++++++++++++--------------------------
 plug-ins/file-psd/psd-util.h |   67 +++---
 plug-ins/file-psd/psd.h      |    9 +
 5 files changed, 345 insertions(+), 594 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 5e0f5af..0c4af56 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -1141,8 +1141,7 @@ add_layers (gint32     image_id,
   gboolean              empty_mask;
   GeglBuffer           *buffer;
   GimpImageType         image_type;
-  GimpLayerMode         layer_mode;
-  GimpLayerCompositeMode layer_composite;
+  LayerModeInfo         mode_info;
 
 
   IFDBG(2) g_debug ("Number of layers: %d", img_a->num_layers);
@@ -1409,14 +1408,11 @@ add_layers (gint32     image_id,
                   IFDBG(2) g_debug ("End group layer id %d.", layer_id);
                   if (layer_id != -1)
                     {
-                      layer_mode = psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode, &layer_composite);
-                      gimp_layer_set_mode (layer_id, layer_mode);
-                      gimp_layer_set_composite_mode (layer_id, layer_composite);
-                      /* FIXME: use perceptual blending and compositing
-                       * unconditionally for now
-                       */
-                      gimp_layer_set_blend_space (layer_id, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL);
-                      gimp_layer_set_composite_space (layer_id, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL);
+                      psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode, &mode_info);
+                      gimp_layer_set_mode (layer_id, mode_info.mode);
+                      gimp_layer_set_blend_space (layer_id, mode_info.blend_space);
+                      gimp_layer_set_composite_space (layer_id, mode_info.composite_space);
+                      gimp_layer_set_composite_mode (layer_id, mode_info.composite_mode);
                       gimp_layer_set_opacity (layer_id,
                                               lyr_a[lidx]->opacity * 100 / 255);
                       gimp_item_set_name (layer_id, lyr_a[lidx]->name);
@@ -1469,16 +1465,13 @@ add_layers (gint32     image_id,
                   g_free (lyr_chn[channel_idx[cidx]]->data);
                 }
 
-              layer_mode = psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode, &layer_composite);
+              psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode, &mode_info);
               layer_id = gimp_layer_new (image_id, lyr_a[lidx]->name, l_w, l_h,
                                          image_type, lyr_a[lidx]->opacity * 100 / 255,
-                                         layer_mode);
-              gimp_layer_set_composite_mode (layer_id, layer_composite);
-              /* FIXME: use perceptual blending and compositing for all layers
-               * for now
-               */
-              gimp_layer_set_blend_space (layer_id, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL);
-              gimp_layer_set_composite_space (layer_id, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL);
+                                         mode_info.mode);
+              gimp_layer_set_blend_space (layer_id, mode_info.blend_space);
+              gimp_layer_set_composite_space (layer_id, mode_info.composite_space);
+              gimp_layer_set_composite_mode (layer_id, mode_info.composite_mode);
               IFDBG(3) g_debug ("Layer tattoo: %d", layer_id);
               g_free (lyr_a[lidx]->name);
               gimp_image_insert_layer (image_id, layer_id, parent_group_id, 0);
diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c
index 753f4f0..d60c810 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -73,6 +73,7 @@
 #include "libgimp/gimp.h"
 #include "libgimp/gimpui.h"
 
+#include "psd.h"
 #include "psd-util.h"
 #include "psd-save.h"
 
@@ -85,6 +86,8 @@
 /* 1: Normal debuggin, 2: Deep debuggin */
 #define DEBUG_LEVEL 2
 
+#undef IFDBG /* previously defined in psd.h */
+
 #define IFDBG if (DEBUG)
 #define IF_DEEP_DBG if (DEBUG && DEBUG_LEVEL == 2)
 
@@ -129,180 +132,78 @@ static PSD_Image_Data PSDImageData;
 /* Declare some local functions.
  */
 
-static void        psd_lmode_layer      (gint32               idLayer,
-                                         gchar               *psdMode);
+static const gchar * psd_lmode_layer      (gint32         idLayer);
 
-static void        reshuffle_cmap_write (guchar              *mapGimp);
+static void          reshuffle_cmap_write (guchar        *mapGimp);
 
-static void        save_header          (FILE                *fd,
-                                         gint32               image_id);
+static void          save_header          (FILE          *fd,
+                                           gint32         image_id);
 
-static void        save_color_mode_data (FILE                *fd,
-                                         gint32               image_id);
+static void          save_color_mode_data (FILE          *fd,
+                                           gint32         image_id);
 
-static void        save_resources       (FILE                *fd,
-                                         gint32               image_id);
+static void          save_resources       (FILE          *fd,
+                                           gint32         image_id);
 
-static void        save_layer_and_mask  (FILE                *fd,
-                                         gint32               image_id);
+static void          save_layer_and_mask  (FILE          *fd,
+                                           gint32         image_id);
 
-static void        save_data            (FILE                *fd,
-                                         gint32               image_id);
+static void          save_data            (FILE          *fd,
+                                           gint32         image_id);
 
-static void        xfwrite              (FILE                *fd,
-                                         gconstpointer        buf,
-                                         glong                len,
-                                         const gchar         *why);
+static void          xfwrite              (FILE          *fd,
+                                           gconstpointer  buf,
+                                           glong          len,
+                                           const gchar   *why);
 
-static void        write_pascalstring   (FILE               *fd,
-                                         const gchar        *val,
-                                         gint                padding,
-                                         const gchar        *why);
+static void          write_pascalstring   (FILE          *fd,
+                                           const gchar   *val,
+                                           gint           padding,
+                                           const gchar   *why);
 
-static void        write_string         (FILE               *fd,
-                                         const gchar        *val,
-                                         const gchar        *why);
+static void          write_string         (FILE          *fd,
+                                           const gchar   *val,
+                                           const gchar   *why);
 
-static void        write_gchar          (FILE               *fd,
-                                         guchar              val,
-                                         const gchar        *why);
+static void          write_gchar          (FILE          *fd,
+                                           guchar         val,
+                                           const gchar   *why);
 
-static void        write_gint16         (FILE               *fd,
-                                         gint16              val,
-                                         const gchar        *why);
+static void          write_gint16         (FILE          *fd,
+                                           gint16         val,
+                                           const gchar   *why);
 
-static void        write_gint32         (FILE               *fd,
-                                         gint32              val,
-                                         const gchar        *why);
+static void          write_gint32         (FILE          *fd,
+                                           gint32         val,
+                                           const gchar   *why);
 
-static void        write_datablock_luni (FILE               *fd,
-                                         const gchar        *val,
-                                         const gchar        *why);
+static void          write_datablock_luni (FILE          *fd,
+                                           const gchar   *val,
+                                           const gchar   *why);
 
 
-static void        write_pixel_data     (FILE               *fd,
-                                         gint32              drawableID,
-                                         glong              *ChanLenPosition,
-                                         gint32              rowlenOffset);
+static void          write_pixel_data     (FILE          *fd,
+                                           gint32         drawableID,
+                                           glong         *ChanLenPosition,
+                                           gint32         rowlenOffset);
 
-static gint32      create_merged_image  (gint32              imageID);
+static gint32        create_merged_image  (gint32         imageID);
 
-static const Babl* get_pixel_format     (gint32 drawableID);
-static const Babl* get_channel_format     (gint32 drawableID);
-static const Babl* get_mask_format     (gint32 drawableID);
+static const Babl  * get_pixel_format     (gint32         drawableID);
+static const Babl  * get_channel_format   (gint32         drawableID);
+static const Babl  * get_mask_format      (gint32         drawableID);
 
-static void
-psd_lmode_layer (gint32  idLayer,
-                 gchar  *psdMode)
+static const gchar *
+psd_lmode_layer (gint32 idLayer)
 {
-  switch (gimp_layer_get_mode (idLayer))
-    {
-    case GIMP_LAYER_MODE_NORMAL_LEGACY:
-      strcpy (psdMode, "norm");
-      break;
-    case GIMP_LAYER_MODE_DARKEN_ONLY:
-    case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
-      strcpy (psdMode, "dark");
-      break;
-    case GIMP_LAYER_MODE_LIGHTEN_ONLY:
-    case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
-      strcpy (psdMode, "lite");
-      break;
-    case GIMP_LAYER_MODE_LCH_HUE:
-    case GIMP_LAYER_MODE_HSV_HUE_LEGACY:
-      strcpy (psdMode, "hue ");
-      break;
-    case GIMP_LAYER_MODE_LCH_CHROMA:
-    case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY:
-      strcpy (psdMode, "sat ");
-      break;
-    case GIMP_LAYER_MODE_LCH_COLOR:
-    case GIMP_LAYER_MODE_HSL_COLOR_LEGACY:
-      strcpy (psdMode, "colr");
-      break;
-    case GIMP_LAYER_MODE_ADDITION:
-    case GIMP_LAYER_MODE_ADDITION_LEGACY:
-      strcpy (psdMode, "lddg");
-      break;
-    case GIMP_LAYER_MODE_MULTIPLY:
-    case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
-      strcpy (psdMode, "mul ");
-      break;
-    case GIMP_LAYER_MODE_SCREEN:
-    case GIMP_LAYER_MODE_SCREEN_LEGACY:
-      strcpy (psdMode, "scrn");
-      break;
-    case GIMP_LAYER_MODE_DISSOLVE:
-      strcpy (psdMode, "diss");
-      break;
-    case GIMP_LAYER_MODE_DIFFERENCE:
-    case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
-      strcpy (psdMode, "diff");
-      break;
-    case GIMP_LAYER_MODE_LCH_LIGHTNESS:
-    case GIMP_LAYER_MODE_HSV_VALUE_LEGACY:                  /* ? */
-      strcpy (psdMode, "lum ");
-      break;
-    case GIMP_LAYER_MODE_HARDLIGHT:
-    case GIMP_LAYER_MODE_HARDLIGHT_LEGACY:
-      strcpy (psdMode, "hLit");
-      break;
-    case GIMP_LAYER_MODE_OVERLAY_LEGACY:
-    case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY:
-      strcpy (psdMode, "sLit");
-      break;
-    case GIMP_LAYER_MODE_OVERLAY:
-      strcpy (psdMode, "over");
-      break;
-    case GIMP_LAYER_MODE_DODGE:
-    case GIMP_LAYER_MODE_DODGE_LEGACY:
-      strcpy (psdMode, "div");
-      break;
-    case GIMP_LAYER_MODE_EXCLUSION:
-      strcpy (psdMode, "smud");
-      break;
-    case GIMP_LAYER_MODE_BURN:
-    case GIMP_LAYER_MODE_BURN_LEGACY:
-      strcpy (psdMode, "idiv");
-      break;
-    case GIMP_LAYER_MODE_LINEAR_BURN:
-      strcpy (psdMode, "lbrn");
-      break;
-    case GIMP_LAYER_MODE_LINEAR_LIGHT:
-      strcpy (psdMode, "lLit");
-      break;
-    case GIMP_LAYER_MODE_PIN_LIGHT:
-      strcpy (psdMode, "pLit");
-      break;
-    case GIMP_LAYER_MODE_VIVID_LIGHT:
-      strcpy (psdMode, "vLit");
-      break;
-    case GIMP_LAYER_MODE_HARD_MIX:
-      strcpy (psdMode, "hMix");
-      break;
-    case GIMP_LAYER_MODE_PASS_THROUGH:
-      strcpy (psdMode, "pass");
-      break;
-      
-    default:
-      {
-        const gchar *nick = "?";
-
-        gimp_enum_get_value (GIMP_TYPE_LAYER_MODE,
-                             gimp_layer_get_mode (idLayer),
-                             NULL, &nick, NULL, NULL);
+  LayerModeInfo mode_info;
 
-        g_message (_("Unable to export layer with mode '%s'.  Either the PSD "
-                     "file format or the export plug-in does not support that, "
-                     "using normal mode instead."), nick);
+  mode_info.mode            = gimp_layer_get_mode (idLayer);
+  mode_info.blend_space     = gimp_layer_get_blend_space (idLayer);
+  mode_info.composite_space = gimp_layer_get_composite_space (idLayer);
+  mode_info.composite_mode  = gimp_layer_get_composite_mode (idLayer);
 
-        IFDBG printf ("PSD: Warning - unsupported layer-blend mode: %s, "
-                      "using normal mode\n", nick);
-
-        strcpy (psdMode, "norm");
-      }
-      break;
-    }
+  return gimp_to_psd_blend_mode (&mode_info);
 }
 
 static void
@@ -947,25 +848,25 @@ static void
 save_layer_and_mask (FILE   *fd,
                      gint32  image_id)
 {
-  gint     i,j;
-  gint     idChannel;
-  gint     offset_x;                    /* X offset for each layer */
-  gint     offset_y;                    /* Y offset for each layer */
-  gint32   layerWidth;                  /* Width of each layer */
-  gint32   layerHeight;                 /* Height of each layer */
-  gchar    blendMode[5];                /* Blending mode of the layer */
-  guchar   layerOpacity;                /* Opacity of the layer */
-  guchar   flags;                       /* Layer flags */
-  gint     nChannelsLayer;              /* Number of channels of a layer */
-  gint32   ChanSize;                    /* Data length for a channel */
-  gchar   *layerName;                   /* Layer name */
-  gint     mask;                        /* Layer mask */
-
-  glong    eof_pos;                     /* Position: End of file */
-  glong    ExtraDataPos;                /* Position: Extra data length */
-  glong    LayerMaskPos;                /* Position: Layer & Mask section length */
-  glong    LayerInfoPos;                /* Position: Layer info section length*/
-  glong  **ChannelLengthPos;            /* Position: Channel length */
+  gint          i,j;
+  gint          idChannel;
+  gint          offset_x;               /* X offset for each layer */
+  gint          offset_y;               /* Y offset for each layer */
+  gint32        layerWidth;             /* Width of each layer */
+  gint32        layerHeight;            /* Height of each layer */
+  const gchar  *blendMode;              /* Blending mode of the layer */
+  guchar        layerOpacity;           /* Opacity of the layer */
+  guchar        flags;                  /* Layer flags */
+  gint          nChannelsLayer;         /* Number of channels of a layer */
+  gint32        ChanSize;               /* Data length for a channel */
+  gchar        *layerName;              /* Layer name */
+  gint          mask;                   /* Layer mask */
+
+  glong         eof_pos;                /* Position: End of file */
+  glong         ExtraDataPos;           /* Position: Extra data length */
+  glong         LayerMaskPos;           /* Position: Layer & Mask section length */
+  glong         LayerInfoPos;           /* Position: Layer info section length*/
+  glong       **ChannelLengthPos;       /* Position: Channel length */
 
 
   IFDBG printf (" Function: save_layer_and_mask\n");
@@ -1060,7 +961,7 @@ save_layer_and_mask (FILE   *fd,
 
       xfwrite (fd, "8BIM", 4, "blend mode signature");
 
-      psd_lmode_layer (PSDImageData.lLayers[i], blendMode);
+      blendMode = psd_lmode_layer (PSDImageData.lLayers[i]);
       IFDBG printf ("\t\tBlend mode: %s\n", blendMode);
       xfwrite (fd, blendMode, 4, "blend mode key");
 
diff --git a/plug-ins/file-psd/psd-util.c b/plug-ins/file-psd/psd-util.c
index 342b669..a42c8ee 100644
--- a/plug-ins/file-psd/psd-util.c
+++ b/plug-ins/file-psd/psd-util.c
@@ -31,11 +31,140 @@
 
 #include "libgimp/stdplugins-intl.h"
 
-/*  Local constants */
+/*  Local constants  */
 #define MIN_RUN     3
 
+/*  Local types  */
+typedef struct
+{
+  const gchar   *name;
+  const gchar   *psd_mode;
+  GimpLayerMode  gimp_mode;
+  gboolean       exact; /* does the modes behave (more-or-less) the same in
+                         * Photoshop and in GIMP?
+                         */
+} LayerModeMapping;
+
 /*  Local function prototypes  */
-static gchar * gimp_layer_mode_effects_name (GimpLayerMode mode);
+static const gchar * get_enum_value_nick (GType type,
+                                          gint  value);
+
+/*  Local varaibles  */
+
+/* mapping table between Photoshop and GIMP modes.  in case a mode matches more
+ * than one entry (in either direction), the first entry wins.
+ */
+static const LayerModeMapping layer_mode_map[] =
+{
+/*  Name             PSD     GIMP                                   Exact?  */
+
+  /* Normal (ps3) */
+  { "Normal",        "norm", GIMP_LAYER_MODE_NORMAL,                TRUE },
+  { "Normal",        "norm", GIMP_LAYER_MODE_NORMAL_LEGACY,         TRUE },
+
+  /* Dissolve (ps3) */
+  { "Dissolve",      "diss", GIMP_LAYER_MODE_DISSOLVE,              TRUE },
+
+  /* Multiply (ps3) */
+  { "Multiply",      "mul ", GIMP_LAYER_MODE_MULTIPLY,              TRUE },
+  { "Multiply",      "mul ", GIMP_LAYER_MODE_MULTIPLY_LEGACY,       TRUE },
+
+  /* Screen (ps3) */
+  { "Screen",        "scrn", GIMP_LAYER_MODE_SCREEN,                TRUE },
+  { "Screen",        "scrn", GIMP_LAYER_MODE_SCREEN_LEGACY,         TRUE },
+
+  /* Overlay (ps3) */
+  { "Overlay",       "over", GIMP_LAYER_MODE_OVERLAY,               TRUE },
+
+  /* Difference (ps3) */
+  { "Difference",    "diff", GIMP_LAYER_MODE_DIFFERENCE,            TRUE },
+  { "Difference",    "diff", GIMP_LAYER_MODE_DIFFERENCE_LEGACY,     TRUE },
+
+  /* Linear Dodge (cs2) */
+  { "Linear Dodge",  "lddg", GIMP_LAYER_MODE_ADDITION,              TRUE },
+  { "Linear Dodge",  "lddg", GIMP_LAYER_MODE_ADDITION_LEGACY,       TRUE },
+
+  /* Subtract (??) */
+  { "Subtract",      "fsub", GIMP_LAYER_MODE_SUBTRACT,              TRUE },
+  { "Subtract",      "fsub", GIMP_LAYER_MODE_SUBTRACT_LEGACY,       TRUE },
+
+  /* Darken (ps3) */
+  { "Darken",        "dark", GIMP_LAYER_MODE_DARKEN_ONLY,           TRUE },
+  { "Darken",        "dark", GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY,    TRUE },
+
+  /* Lighten (ps3) */
+  { "Ligten",        "lite", GIMP_LAYER_MODE_LIGHTEN_ONLY,          TRUE },
+  { "Ligten",        "lite", GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY,   TRUE },
+
+  /* Hue (ps3) */
+  { "Hue",           "hue ", GIMP_LAYER_MODE_LCH_HUE,               FALSE },
+  { "Hue",           "hue ", GIMP_LAYER_MODE_HSV_HUE,               FALSE },
+  { "Hue",           "hue ", GIMP_LAYER_MODE_HSV_HUE_LEGACY,        FALSE },
+
+  /* Stauration (ps3) */
+  { "Saturation",    "sat ", GIMP_LAYER_MODE_LCH_CHROMA,            FALSE },
+  { "Saturation",    "sat ", GIMP_LAYER_MODE_HSV_SATURATION,        FALSE },
+  { "Saturation",    "sat ", GIMP_LAYER_MODE_HSV_SATURATION_LEGACY, FALSE },
+
+  /* Color (ps3) */
+  { "Color",         "colr", GIMP_LAYER_MODE_LCH_COLOR,             FALSE },
+  { "Color",         "colr", GIMP_LAYER_MODE_HSL_COLOR,             FALSE },
+  { "Color",         "colr", GIMP_LAYER_MODE_HSL_COLOR_LEGACY,      FALSE },
+
+  /* Luminosity (ps3) */
+  { "Luminosity",    "lum ", GIMP_LAYER_MODE_LCH_LIGHTNESS,         FALSE },
+  { "Luminosity",    "lum ", GIMP_LAYER_MODE_HSV_VALUE,             FALSE },
+  { "Luminosity",    "lum ", GIMP_LAYER_MODE_HSV_VALUE_LEGACY,      FALSE },
+  { "Luminosity",    "lum ", GIMP_LAYER_MODE_LUMINANCE,             FALSE },
+
+  /* Divide (??) */
+  { "Divide",        "fdiv", GIMP_LAYER_MODE_DIVIDE,                TRUE },
+  { "Divide",        "fdiv", GIMP_LAYER_MODE_DIVIDE_LEGACY,         TRUE },
+
+  /* Color Dodge (ps6) */
+  { "Color Dodge",   "div ", GIMP_LAYER_MODE_DODGE,                 TRUE },
+  { "Color Dodge",   "div ", GIMP_LAYER_MODE_DODGE_LEGACY,          TRUE },
+
+  /* Color Burn (ps6) */
+  { "Color Burn",    "idiv", GIMP_LAYER_MODE_BURN,                  TRUE },
+  { "Color Burn",    "idiv", GIMP_LAYER_MODE_BURN_LEGACY,           TRUE },
+
+  /* Hard Light (ps3) */
+  { "Hard Light",    "hLit", GIMP_LAYER_MODE_HARDLIGHT,             TRUE },
+  { "Hard Light",    "hLit", GIMP_LAYER_MODE_HARDLIGHT_LEGACY,      TRUE },
+
+  /* Soft Light (ps3) */
+  { "Soft Light",    "sLit", GIMP_LAYER_MODE_SOFTLIGHT,             FALSE },
+  { "Soft Light",    "sLit", GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,      FALSE },
+  { "Soft Light",    "sLit", GIMP_LAYER_MODE_OVERLAY_LEGACY,        FALSE },
+
+  /* Vivid Light (ps7)*/
+  { "Vivid Light",   "vLit", GIMP_LAYER_MODE_VIVID_LIGHT,           TRUE },
+
+  /* Pin Light (ps7)*/
+  { "Pin Light",     "pLit", GIMP_LAYER_MODE_PIN_LIGHT,             TRUE },
+
+  /* Linear Light (ps7)*/
+  { "Linear Light",  "lLit", GIMP_LAYER_MODE_LINEAR_LIGHT,          TRUE },
+
+  /* Hard Mix (CS)*/
+  { "Hard Mix",      "hMix", GIMP_LAYER_MODE_HARD_MIX,              TRUE },
+
+  /* Exclusion (ps6) */
+  { "Exclusion",     "smud", GIMP_LAYER_MODE_EXCLUSION,             TRUE },
+
+  /* Linear Burn (ps7)*/
+  { "Linear Burn",   "lbrn", GIMP_LAYER_MODE_LINEAR_BURN,           TRUE },
+
+  /* Darker Color (??)*/
+  { "Darker Color",  "dkCl", GIMP_LAYER_MODE_LUMA_DARKEN_ONLY,      FALSE },
+
+  /* Lighter Color (??)*/
+  { "Lighter Color", "lgCl", GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY,     FALSE },
+
+  /* Pass Through (CS)*/
+  { "Pass Through",  "pass", GIMP_LAYER_MODE_PASS_THROUGH,          TRUE },
+};
 
 
 /* Utility function */
@@ -605,405 +734,105 @@ encode_packbits (const gchar *src,
   return g_string_free (dst_str, FALSE);
 }
 
-GimpLayerMode
-psd_to_gimp_blend_mode (const gchar            *psd_mode,
-                        GimpLayerCompositeMode *layer_composite)
+void
+psd_to_gimp_blend_mode (const gchar   *psd_mode,
+                        LayerModeInfo *mode_info)
 {
-  /* FIXME: Do all photoshop modes use the union rule?  We always return
-   * "union", effectively, only returning "auto" for modes that default to
-   * "union", to reduce UI clutter.
-   */
-  if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_SRC_OVER;
-
-  if (g_ascii_strncasecmp (psd_mode, "pass", 4) == 0)           /* Pass through (CS)*/
-    {
-      if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_AUTO;
-      return GIMP_LAYER_MODE_PASS_THROUGH;
-    }
-
-  if (g_ascii_strncasecmp (psd_mode, "norm", 4) == 0)           /* Normal (ps3) */
-    {
-      if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_AUTO;
-      return GIMP_LAYER_MODE_NORMAL;
-    }
-
-  if (g_ascii_strncasecmp (psd_mode, "dark", 4) == 0)           /* Darken (ps3) */
-    return GIMP_LAYER_MODE_DARKEN_ONLY;
-
-  if (g_ascii_strncasecmp (psd_mode, "lite", 4) == 0)           /* Lighten (ps3) */
-      return GIMP_LAYER_MODE_LIGHTEN_ONLY;
-
-  if (g_ascii_strncasecmp (psd_mode, "hue ", 4) == 0)           /* Hue (ps3) */
-    return GIMP_LAYER_MODE_LCH_HUE;
-
-  if (g_ascii_strncasecmp (psd_mode, "sat ", 4) == 0)           /* Saturation (ps3) */
-    {
-      if (CONVERSION_WARNINGS)
-        {
-          static gchar  *mode_name = "SATURATION";
-          g_message ("Gimp uses a different equation to photoshop for "
-                     "blend mode: %s. Results will differ.",
-                     mode_name);
-        }
-      return GIMP_LAYER_MODE_LCH_CHROMA;
-    }
-
-  if (g_ascii_strncasecmp (psd_mode, "colr", 4) == 0)           /* Color (ps3) */
-    return GIMP_LAYER_MODE_LCH_COLOR;
-
-  if (g_ascii_strncasecmp (psd_mode, "lum ", 4) == 0)           /* Luminosity (ps3) */
-    {
-      if (CONVERSION_WARNINGS)
-        {
-          static gchar  *mode_name = "LUMINOSITY (VALUE)";
-          g_message ("Gimp uses a different equation to photoshop for "
-                     "blend mode: %s. Results will differ.",
-                     mode_name);
-        }
-      return GIMP_LAYER_MODE_LCH_LIGHTNESS;
-    }
+  gint i;
 
-  if (g_ascii_strncasecmp (psd_mode, "mul ", 4) == 0)           /* Multiply (ps3) */
-    return GIMP_LAYER_MODE_MULTIPLY;
-
-  if (g_ascii_strncasecmp (psd_mode, "lddg", 4) == 0)           /* Linear Dodge (cs2) */
-    return GIMP_LAYER_MODE_ADDITION;
-
-  if (g_ascii_strncasecmp (psd_mode, "scrn", 4) == 0)           /* Screen (ps3) */
-    return GIMP_LAYER_MODE_SCREEN;
-
-  if (g_ascii_strncasecmp (psd_mode, "diss", 4) == 0)           /* Dissolve (ps3) */
-    {
-      if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_AUTO;
-      return GIMP_LAYER_MODE_DISSOLVE;
-    }
-
-  if (g_ascii_strncasecmp (psd_mode, "over", 4) == 0)           /* Overlay (ps3) */
-    return GIMP_LAYER_MODE_OVERLAY;
-
-  if (g_ascii_strncasecmp (psd_mode, "hLit", 4) == 0)           /* Hard light (ps3) */
-    return GIMP_LAYER_MODE_HARDLIGHT;
+  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.
+   */
+  mode_info->blend_space     = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL;
+  mode_info->composite_space = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL;
+  mode_info->composite_mode  = GIMP_LAYER_COMPOSITE_SRC_OVER;
 
-  if (g_ascii_strncasecmp (psd_mode, "sLit", 4) == 0)           /* Soft light (ps3) */
+  for (i = 0; i < G_N_ELEMENTS (layer_mode_map); i++)
     {
-      if (CONVERSION_WARNINGS)
+      if (g_ascii_strncasecmp (psd_mode, layer_mode_map[i].psd_mode, 4) == 0)
         {
-          static gchar  *mode_name = "SOFT LIGHT";
-          g_message ("GIMP uses a different equation to Photoshop for "
-                     "blend mode: %s. Results will differ.",
-                     mode_name);
-        }
-    return GIMP_LAYER_MODE_SOFTLIGHT;
-    }
-
-  if (g_ascii_strncasecmp (psd_mode, "diff", 4) == 0)           /* Difference (ps3) */
-    return GIMP_LAYER_MODE_DIFFERENCE;
-
-  if (g_ascii_strncasecmp (psd_mode, "smud", 4) == 0)           /* Exclusion (ps6) */
-      return GIMP_LAYER_MODE_EXCLUSION;
-
-  if (g_ascii_strncasecmp (psd_mode, "div ", 4) == 0)           /* Color dodge (ps6) */
-      return GIMP_LAYER_MODE_DODGE;
-
-  if (g_ascii_strncasecmp (psd_mode, "idiv", 4) == 0)           /* Color burn (ps6) */
-      return GIMP_LAYER_MODE_BURN;
-
-  if (g_ascii_strncasecmp (psd_mode, "lbrn", 4) == 0)           /* Linear burn (ps7)*/
-      return GIMP_LAYER_MODE_LINEAR_BURN;
-
-  if (g_ascii_strncasecmp (psd_mode, "lddg", 4) == 0)           /* Linear dodge (ps7)*/
-      return GIMP_LAYER_MODE_ADDITION;
-
-  if (g_ascii_strncasecmp (psd_mode, "lLit", 4) == 0)           /* Linear light (ps7)*/
-      return GIMP_LAYER_MODE_LINEAR_LIGHT;
-
-  if (g_ascii_strncasecmp (psd_mode, "pLit", 4) == 0)           /* Pin light (ps7)*/
-      return GIMP_LAYER_MODE_PIN_LIGHT;
-
-  if (g_ascii_strncasecmp (psd_mode, "vLit", 4) == 0)           /* Vivid light (ps7)*/
-    return GIMP_LAYER_MODE_VIVID_LIGHT;
+          if (! layer_mode_map[i].exact && CONVERSION_WARNINGS)
+            {
+              g_message ("GIMP uses a different equation than Photoshop for "
+                         "blend mode: %s. Results will differ.",
+                         layer_mode_map[i].name);
+            }
 
-  if (g_ascii_strncasecmp (psd_mode, "hMix", 4) == 0)           /* Hard Mix (CS)*/
-      return GIMP_LAYER_MODE_HARD_MIX;
+          mode_info->mode = layer_mode_map[i].gimp_mode;
 
-  if (g_ascii_strncasecmp (psd_mode, "dkCl", 4) == 0)           /* Darker Color */
-    {
-      if (CONVERSION_WARNINGS)
-        {
-          static gchar  *mode_name = "DARKER COLOR";
-          g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                     mode_name);
+          return;
         }
-      if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_AUTO;
-      return GIMP_LAYER_MODE_NORMAL;
-    }
-
-  if (g_ascii_strncasecmp (psd_mode, "lgCl", 4) == 0)           /* Lighter Color */
-    {
-      if (CONVERSION_WARNINGS)
-        {
-          static gchar  *mode_name = "LIGHTER COLOR";
-          g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                     mode_name);
-        }
-      if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_AUTO;
-      return GIMP_LAYER_MODE_NORMAL;
     }
 
   if (CONVERSION_WARNINGS)
     {
-      gchar  *mode_name = g_strndup (psd_mode, 4);
+      gchar *mode_name = g_strndup (psd_mode, 4);
       g_message ("Unsupported blend mode: %s. Mode reverts to normal",
                  mode_name);
       g_free (mode_name);
     }
-
-  if (layer_composite) *layer_composite = GIMP_LAYER_COMPOSITE_AUTO;
-
-  return GIMP_LAYER_MODE_NORMAL;
 }
 
-gchar *
-gimp_to_psd_blend_mode (GimpLayerMode          layer_mode,
-                        GimpLayerCompositeMode layer_composite)
+const gchar *
+gimp_to_psd_blend_mode (const LayerModeInfo *mode_info)
 {
-  gchar *psd_mode;
+  gint i;
 
-  if (((layer_mode == GIMP_LAYER_MODE_NORMAL_LEGACY ||
-        layer_mode == GIMP_LAYER_MODE_DISSOLVE) &&
-       (layer_composite != GIMP_LAYER_COMPOSITE_AUTO &&
-        layer_composite != GIMP_LAYER_COMPOSITE_SRC_OVER)) ||
-      layer_composite != GIMP_LAYER_COMPOSITE_SRC_OVER)
+  /* FIXME: select the image mode based on the layer mode color spaces.  for
+   * now, we assume rgb-perceptual blending/compositing unconditionally.
+   */
+  if (mode_info->blend_space != GIMP_LAYER_COLOR_SPACE_AUTO &&
+      mode_info->blend_space != GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL)
     {
-      /* FIXME, and above if() */
+      if (CONVERSION_WARNINGS)
+        g_message ("Unsupported blend color space: %s. "
+                   "Blend color space reverts to rgb-perceptual",
+                   get_enum_value_nick (GIMP_TYPE_LAYER_COLOR_SPACE,
+                                        mode_info->blend_space));
     }
 
-  switch (layer_mode)
+  if (mode_info->composite_space != GIMP_LAYER_COLOR_SPACE_AUTO &&
+      mode_info->composite_space != GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL)
     {
-
-    case GIMP_LAYER_MODE_PASS_THROUGH:
-      psd_mode = g_strndup ("pass", 4);                       /* Pass through (CS) */
-      break;
-
-    case GIMP_LAYER_MODE_NORMAL_LEGACY:
-      psd_mode = g_strndup ("norm", 4);                       /* Normal (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_DISSOLVE:
-      psd_mode = g_strndup ("diss", 4);                       /* Dissolve (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_BEHIND:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
-      break;
-
-    case GIMP_LAYER_MODE_MULTIPLY:
-    case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
-      psd_mode = g_strndup ("mul ", 4);                       /* Multiply (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_SCREEN:
-    case GIMP_LAYER_MODE_SCREEN_LEGACY:
-      psd_mode = g_strndup ("scrn", 4);                       /* Screen (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_OVERLAY:
-      psd_mode = g_strndup ("over", 4);                       /* Overlay (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_DIFFERENCE:
-    case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
-      psd_mode = g_strndup ("diff", 4);                       /* Difference (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_ADDITION:
-    case GIMP_LAYER_MODE_ADDITION_LEGACY:
-      psd_mode = g_strndup ("lddg", 4);                       /* Linear dodge (ps7)*/
-      break;
-
-    case GIMP_LAYER_MODE_SUBTRACT_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
-      break;
-
-    case GIMP_LAYER_MODE_DARKEN_ONLY:
-    case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
-      psd_mode = g_strndup ("dark", 4);                       /* Darken (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_LIGHTEN_ONLY:
-    case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
-      psd_mode = g_strndup ("lite", 4);                       /* Lighten (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_LCH_HUE:
-    case GIMP_LAYER_MODE_HSV_HUE_LEGACY:
-      psd_mode = g_strndup ("hue ", 4);                       /* Hue (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_LCH_CHROMA:
-    case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("GIMP uses a different equation to Photoshop for "
-                   "blend mode: %s. Results may differ.",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("sat ", 4);                       /* Saturation (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_LCH_COLOR:
-    case GIMP_LAYER_MODE_HSL_COLOR_LEGACY:
-      psd_mode = g_strndup ("colr", 4);                       /* Color (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_LCH_LIGHTNESS:
-    case GIMP_LAYER_MODE_HSV_VALUE_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("GIMP uses a different equation to Photoshop for "
-                   "blend mode: %s. Results may differ.",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("lum ", 4);                       /* Luminosity (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_DIVIDE_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
-      break;
-
-    case GIMP_LAYER_MODE_DODGE:
-    case GIMP_LAYER_MODE_DODGE_LEGACY:
-      psd_mode = g_strndup ("div ", 4);                       /* Color Dodge (ps6) */
-      break;
-
-    case GIMP_LAYER_MODE_EXCLUSION:
-      psd_mode = g_strndup ("smud", 4);                       /* Exclusion (ps6) */
-      break;
-
-    case GIMP_LAYER_MODE_BURN:
-    case GIMP_LAYER_MODE_BURN_LEGACY:
-      psd_mode = g_strndup ("idiv", 4);                       /* Color Burn (ps6) */
-      break;
-
-    case GIMP_LAYER_MODE_LINEAR_BURN:
-      psd_mode = g_strndup ("lbrn", 4);                       /* Linear Burn (ps6) */
-      break;
-
-    case GIMP_LAYER_MODE_HARDLIGHT:
-    case GIMP_LAYER_MODE_HARDLIGHT_LEGACY:
-      psd_mode = g_strndup ("hLit", 4);                       /* Hard Light (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_VIVID_LIGHT:
       if (CONVERSION_WARNINGS)
-        g_message ("GIMP uses a different equation to Photoshop for "
-                   "blend mode: %s. Results may differ.",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("vLit", 4);                       /* Vivid Light (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_LINEAR_LIGHT:
-      psd_mode = g_strndup ("lLit", 4);                       /* Linear light (ps7)*/
-      break;
-
-    case GIMP_LAYER_MODE_PIN_LIGHT:
-      psd_mode = g_strndup ("pLit", 4);                       /* Pin light (ps7)*/
-      break;
-
-    case GIMP_LAYER_MODE_HARD_MIX:
-      psd_mode = g_strndup ("hMix", 4);                       /* Hard Mix (CS)*/
-      break;
-
-    case GIMP_LAYER_MODE_OVERLAY_LEGACY:
-    case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("sLit", 4);                       /* Soft Light (ps3) */
-      break;
-
-    case GIMP_LAYER_MODE_GRAIN_EXTRACT:
-    case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
-      break;
+        g_message ("Unsupported composite color space: %s. "
+                   "Composite color space reverts to rgb-perceptual",
+                   get_enum_value_nick (GIMP_TYPE_LAYER_COLOR_SPACE,
+                                        mode_info->composite_space));
+    }
 
-    case GIMP_LAYER_MODE_GRAIN_MERGE:
-    case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
+  if (mode_info->composite_mode != GIMP_LAYER_COMPOSITE_AUTO &&
+      mode_info->composite_mode != GIMP_LAYER_COMPOSITE_SRC_OVER)
+    {
       if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
-      break;
+        g_message ("Unsupported composite mode: %s. "
+                   "Composite mode reverts to src-over",
+                   get_enum_value_nick (GIMP_TYPE_LAYER_COMPOSITE_MODE,
+                                        mode_info->composite_mode));
+    }
 
-    case GIMP_LAYER_MODE_COLOR_ERASE:
-    case GIMP_LAYER_MODE_COLOR_ERASE_LEGACY:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
-      break;
+  for (i = 0; i < G_N_ELEMENTS (layer_mode_map); i++)
+    {
+      if (layer_mode_map[i].gimp_mode == mode_info->mode)
+        {
+          if (! layer_mode_map[i].exact && CONVERSION_WARNINGS)
+            {
+              g_message ("GIMP uses a different equation than Photoshop for "
+                         "blend mode: %s. Results may differ.",
+                         get_enum_value_nick (GIMP_TYPE_LAYER_MODE,
+                                              mode_info->mode));
+            }
 
-    default:
-      if (CONVERSION_WARNINGS)
-        g_message ("Unsupported blend mode: %s. Mode reverts to normal",
-                   gimp_layer_mode_effects_name (layer_mode));
-      psd_mode = g_strndup ("norm", 4);
+          return layer_mode_map[i].psd_mode;
+        }
     }
 
-  return psd_mode;
-}
+  if (CONVERSION_WARNINGS)
+    g_message ("Unsupported blend mode: %s. Mode reverts to normal",
+               get_enum_value_nick (GIMP_TYPE_LAYER_MODE, mode_info->mode));
 
-static gchar *
-gimp_layer_mode_effects_name (GimpLayerMode mode)
-{
-  static gchar *layer_mode_effects_names[] =
-  {
-    "NORMAL",
-    "DISSOLVE",
-    "BEHIND",
-    "MULTIPLY",
-    "SCREEN",
-    "OVERLAY",
-    "DIFFERENCE",
-    "ADD",
-    "SUBTRACT",
-    "EXCLUSION"
-    "DARKEN",
-    "LIGHTEN",
-    "HUE",
-    "SATURATION",
-    "COLOR",
-    "VALUE",
-    "DIVIDE",
-    "DODGE",
-    "BURN",
-    "LINEAR BURN"
-    "HARD LIGHT",
-    "SOFT LIGHT",
-    "VIVID LIGHT",
-    "LINEAR LIGHT",
-    "PIN LIGHT",
-    "HARD MIX"
-    "GRAIN EXTRACT",
-    "GRAIN MERGE",
-    "COLOR ERASE"
-    "PASS THROUGH"
-  };
-  static gchar *err_name = NULL;
-  if (mode >= 0 && mode <= GIMP_LAYER_MODE_COLOR_ERASE_LEGACY)
-    return layer_mode_effects_names[mode];
-  g_free (err_name);
-
-  err_name = g_strdup_printf ("UNKNOWN (%d)", mode);
-  return err_name;
+  return "norm";
 }
 
 GimpColorTag
@@ -1095,3 +924,23 @@ gimp_to_psd_layer_color_tag (GimpColorTag layer_color_tag)
 
   return color_tag;
 }
+
+static const gchar *
+get_enum_value_nick (GType type,
+                     gint  value)
+{
+  const gchar *nick;
+
+  if (gimp_enum_get_value (type, value, NULL, &nick, NULL, NULL))
+    {
+      return nick;
+    }
+  else
+    {
+      static gchar err_name[32];
+
+      snprintf (err_name, sizeof (err_name), "UNKNOWN (%d)", value);
+
+      return err_name;
+    }
+}
diff --git a/plug-ins/file-psd/psd-util.h b/plug-ins/file-psd/psd-util.h
index e3d6c1d..a5ead70 100644
--- a/plug-ins/file-psd/psd-util.h
+++ b/plug-ins/file-psd/psd-util.h
@@ -24,65 +24,64 @@
 /*
  *  Set file read error
  */
-void                    psd_set_error          (gboolean        file_eof,
-                                                gint            err_no,
-                                                GError        **error);
+void                    psd_set_error          (gboolean             file_eof,
+                                                gint                 err_no,
+                                                GError             **error);
 
 /*
  * Reads a pascal string from the file padded to a multiple of mod_len
  * and returns a utf-8 string.
  */
-gchar                 * fread_pascal_string    (gint32         *bytes_read,
-                                                gint32         *bytes_written,
-                                                guint16         mod_len,
-                                                FILE           *f,
-                                                GError        **error);
+gchar                 * fread_pascal_string    (gint32              *bytes_read,
+                                                gint32              *bytes_written,
+                                                guint16              mod_len,
+                                                FILE                *f,
+                                                GError             **error);
 
 /*
  *  Converts utf-8 string to current locale and writes as pascal
  *  string with padding to a multiple of mod_len.
  */
-gint32                  fwrite_pascal_string   (const gchar    *src,
-                                                guint16         mod_len,
-                                                FILE           *f,
-                                                GError        **error);
+gint32                  fwrite_pascal_string   (const gchar         *src,
+                                                guint16              mod_len,
+                                                FILE                *f,
+                                                GError             **error);
 
 /*
  * Reads a utf-16 string from the file padded to a multiple of mod_len
  * and returns a utf-8 string.
  */
-gchar                 * fread_unicode_string   (gint32         *bytes_read,
-                                                gint32         *bytes_written,
-                                                guint16         mod_len,
-                                                FILE           *f,
-                                                GError        **error);
+gchar                 * fread_unicode_string   (gint32              *bytes_read,
+                                                gint32              *bytes_written,
+                                                guint16              mod_len,
+                                                FILE                *f,
+                                                GError             **error);
 
 /*
  *  Converts utf-8 string to utf-16 and writes 4 byte length
  *  then string padding to multiple of mod_len.
  */
-gint32                  fwrite_unicode_string  (const gchar    *src,
-                                                guint16         mod_len,
-                                                FILE           *f,
-                                                GError        **error);
+gint32                  fwrite_unicode_string  (const gchar         *src,
+                                                guint16              mod_len,
+                                                FILE                *f,
+                                                GError             **error);
 
-gint                    decode_packbits        (const gchar    *src,
-                                                gchar          *dst,
-                                                guint16         packed_len,
-                                                guint32         unpacked_len);
+gint                    decode_packbits        (const gchar         *src,
+                                                gchar               *dst,
+                                                guint16              packed_len,
+                                                guint32              unpacked_len);
 
-gchar                 * encode_packbits        (const gchar    *src,
-                                                guint32         unpacked_len,
-                                                guint16        *packed_len);
+gchar                 * encode_packbits        (const gchar         *src,
+                                                guint32              unpacked_len,
+                                                guint16             *packed_len);
 
-GimpLayerMode           psd_to_gimp_blend_mode (const gchar            *psd_mode,
-                                                GimpLayerCompositeMode *layer_composite);
+void                    psd_to_gimp_blend_mode (const gchar          *psd_mode,
+                                                LayerModeInfo        *mode_info);
 
-gchar *                 gimp_to_psd_blend_mode (GimpLayerMode           layer_mode,
-                                                GimpLayerCompositeMode  layer_composite);
+const gchar *           gimp_to_psd_blend_mode (const LayerModeInfo  *mode_info);
 
-GimpColorTag            psd_to_gimp_layer_color_tag (guint16 layer_color_tag);
+GimpColorTag            psd_to_gimp_layer_color_tag (guint16          layer_color_tag);
 
-guint16                 gimp_to_psd_layer_color_tag (GimpColorTag layer_color_tag);
+guint16                 gimp_to_psd_layer_color_tag (GimpColorTag     layer_color_tag);
 
 #endif /* __PSD_UTIL_H__ */
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index 48bf767..29c056c 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -419,6 +419,15 @@ typedef union
   CMGrayColor       gray;
 } CMColor;
 
+/* GIMP layer mode info */
+typedef struct
+{
+  GimpLayerMode          mode;
+  GimpLayerColorSpace    blend_space;
+  GimpLayerColorSpace    composite_space;
+  GimpLayerCompositeMode composite_mode;
+} LayerModeInfo;
+
 /* Image resolution data */
 typedef struct {
   Fixed         hRes;                   /* Horizontal resolution pixels/inch */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]